Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv_contrib
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv_contrib
Commits
a29ec8a1
Commit
a29ec8a1
authored
Feb 12, 2016
by
Maksim Shabunin
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #542 from amroamroamro:fix_niblack
parents
f162a935
6c7a806a
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
110 additions
and
74 deletions
+110
-74
ximgproc.hpp
modules/ximgproc/include/opencv2/ximgproc.hpp
+44
-10
niblack_thresholding.cpp
modules/ximgproc/samples/niblack_thresholding.cpp
+21
-26
niblack_thresholding.cpp
modules/ximgproc/src/niblack_thresholding.cpp
+45
-38
No files found.
modules/ximgproc/include/opencv2/ximgproc.hpp
View file @
a29ec8a1
...
...
@@ -52,8 +52,8 @@
@{
@defgroup ximgproc_edge Structured forests for fast edge detection
This module contains implementations of modern structured edge detection algorithms,
i.e. algorithms
which somehow takes into account pixel affinities in natural images.
This module contains implementations of modern structured edge detection algorithms,
i.e. algorithms
which somehow takes into account pixel affinities in natural images.
@defgroup ximgproc_filters Filters
...
...
@@ -63,13 +63,47 @@ which somehow takes into account pixel affinities in natural images.
@}
*/
namespace
cv
{
namespace
ximgproc
{
CV_EXPORTS_W
void
niBlackThreshold
(
InputArray
_src
,
OutputArray
_dst
,
double
maxValue
,
int
type
,
int
blockSize
,
double
delta
);
namespace
cv
{
namespace
ximgproc
{
}
// namespace
ximgproc
}
//namespace cv
//! @addtogroup
ximgproc
//! @{
#endif
/** @brief Applies Niblack thresholding to input image.
The function transforms a grayscale image to a binary image according to the formulae:
- **THRESH_BINARY**
\f[dst(x,y) = \fork{\texttt{maxValue}}{if \(src(x,y) > T(x,y)\)}{0}{otherwise}\f]
- **THRESH_BINARY_INV**
\f[dst(x,y) = \fork{0}{if \(src(x,y) > T(x,y)\)}{\texttt{maxValue}}{otherwise}\f]
where \f$T(x,y)\f$ is a threshold calculated individually for each pixel.
The threshold value \f$T(x, y)\f$ is the mean minus \f$ delta \f$ times standard deviation
of \f$\texttt{blockSize} \times\texttt{blockSize}\f$ neighborhood of \f$(x, y)\f$.
The function can't process the image in-place.
@param _src Source 8-bit single-channel image.
@param _dst Destination image of the same size and the same type as src.
@param maxValue Non-zero value assigned to the pixels for which the condition is satisfied,
used with the THRESH_BINARY and THRESH_BINARY_INV thresholding types.
@param type Thresholding type, see cv::ThresholdTypes.
@param blockSize Size of a pixel neighborhood that is used to calculate a threshold value
for the pixel: 3, 5, 7, and so on.
@param delta Constant multiplied with the standard deviation and subtracted from the mean.
Normally, it is taken to be a real number between 0 and 1.
@sa threshold, adaptiveThreshold
*/
CV_EXPORTS_W
void
niBlackThreshold
(
InputArray
_src
,
OutputArray
_dst
,
double
maxValue
,
int
type
,
int
blockSize
,
double
delta
);
//! @}
}
}
#endif // __OPENCV_XIMGPROC_HPP__
modules/ximgproc/samples/niblack_thresholding.cpp
View file @
a29ec8a1
/*
* Sample C++ to demonstrate Niblack thresholding.
*
* C++ sample to demonstrate Niblack thresholding.
*/
#include <iostream>
#include <cstdio>
#include "opencv2/highgui.hpp"
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/ximgproc.hpp"
using
namespace
std
;
using
namespace
cv
;
using
namespace
cv
::
ximgproc
;
Mat_
<
uchar
>
src
,
dst
;
const
int
k_max_value
=
10
;
int
k_from_slider
=
0
;
double
k_actual
=
0.0
;
Mat_
<
uchar
>
src
;
int
k_
=
8
;
int
blockSize_
=
11
;
int
type_
=
THRESH_BINARY
;
void
on_trackbar
(
int
,
void
*
);
int
main
(
int
argc
,
char
**
argv
)
{
/*
* Read filename from the command-line and load
* corresponding gray-scale image.
*/
// read gray-scale image
if
(
argc
!=
2
)
{
cout
<<
"Usage: ./niblack_thresholding [IMAGE]
\n
"
;
return
1
;
}
const
char
*
filename
=
argv
[
1
];
src
=
imread
(
filename
,
1
);
namedWindow
(
"k-slider"
,
1
);
string
trackbar_name
=
"k"
;
createTrackbar
(
trackbar_name
,
"k-slider"
,
&
k_from_slider
,
k_max_value
,
on_trackbar
);
on_trackbar
(
k_from_slider
,
0
);
src
=
imread
(
filename
,
IMREAD_GRAYSCALE
);
imshow
(
"Source"
,
src
);
namedWindow
(
"Niblack"
,
WINDOW_AUTOSIZE
);
createTrackbar
(
"k"
,
"Niblack"
,
&
k_
,
20
,
on_trackbar
);
createTrackbar
(
"blockSize"
,
"Niblack"
,
&
blockSize_
,
30
,
on_trackbar
);
createTrackbar
(
"threshType"
,
"Niblack"
,
&
type_
,
4
,
on_trackbar
);
on_trackbar
(
0
,
0
);
waitKey
(
0
);
return
0
;
...
...
@@ -51,8 +43,11 @@ int main(int argc, char** argv)
void
on_trackbar
(
int
,
void
*
)
{
k_actual
=
(
double
)
k_from_slider
/
k_max_value
;
niBlackThreshold
(
src
,
dst
,
255
,
THRESH_BINARY
,
3
,
k_actual
);
imshow
(
"Destination"
,
dst
);
double
k
=
static_cast
<
double
>
(
k_
-
10
)
/
10
;
// [-1.0, 1.0]
int
blockSize
=
2
*
(
blockSize_
>=
1
?
blockSize_
:
1
)
+
1
;
// 3,5,7,...,61
int
type
=
type_
;
// THRESH_BINARY, THRESH_BINARY_INV,
// THRESH_TRUNC, THRESH_TOZERO, THRESH_TOZERO_INV
Mat
dst
;
niBlackThreshold
(
src
,
dst
,
255
,
type
,
blockSize
,
k
);
imshow
(
"Niblack"
,
dst
);
}
modules/ximgproc/src/niblack_thresholding.cpp
View file @
a29ec8a1
...
...
@@ -49,52 +49,59 @@ namespace ximgproc {
void
niBlackThreshold
(
InputArray
_src
,
OutputArray
_dst
,
double
maxValue
,
int
type
,
int
blockSize
,
double
delta
)
{
// Input grayscale image
Mat
src
=
_src
.
getMat
();
CV_Assert
(
src
.
type
()
==
CV_8UC1
);
CV_Assert
(
blockSize
%
2
==
1
&&
blockSize
>
1
);
Size
size
=
src
.
size
()
;
CV_Assert
(
src
.
channels
()
==
1
);
CV_Assert
(
blockSize
%
2
==
1
&&
blockSize
>
1
);
type
&=
THRESH_MASK
;
_dst
.
create
(
size
,
src
.
type
()
);
Mat
dst
=
_dst
.
getMat
();
if
(
maxValue
<
0
)
// Compute local threshold (T = mean + k * stddev)
// using mean and standard deviation in the neighborhood of each pixel
// (intermediate calculations are done with floating-point precision)
Mat
thresh
;
{
dst
=
Scalar
(
0
);
return
;
// note that: Var[X] = E[X^2] - E[X]^2
Mat
mean
,
sqmean
,
stddev
;
boxFilter
(
src
,
mean
,
CV_32F
,
Size
(
blockSize
,
blockSize
),
Point
(
-
1
,
-
1
),
true
,
BORDER_REPLICATE
);
sqrBoxFilter
(
src
,
sqmean
,
CV_32F
,
Size
(
blockSize
,
blockSize
),
Point
(
-
1
,
-
1
),
true
,
BORDER_REPLICATE
);
sqrt
(
sqmean
-
mean
.
mul
(
mean
),
stddev
);
thresh
=
mean
+
stddev
*
static_cast
<
float
>
(
delta
);
thresh
.
convertTo
(
thresh
,
src
.
depth
());
}
// Calculate and store the mean and mean of squares in the neighborhood
// of each pixel and store them in Mat mean and sqmean.
Mat_
<
float
>
mean
(
size
),
sqmean
(
size
);
if
(
src
.
data
!=
dst
.
data
)
mean
=
dst
;
boxFilter
(
src
,
mean
,
CV_64F
,
Size
(
blockSize
,
blockSize
),
Point
(
-
1
,
-
1
),
true
,
BORDER_REPLICATE
);
sqrBoxFilter
(
src
,
sqmean
,
CV_64F
,
Size
(
blockSize
,
blockSize
),
Point
(
-
1
,
-
1
),
true
,
BORDER_REPLICATE
);
// Prepare output image
_dst
.
create
(
src
.
size
(),
src
.
type
());
Mat
dst
=
_dst
.
getMat
();
CV_Assert
(
src
.
data
!=
dst
.
data
);
// no inplace processing
// Compute (k * standard deviation) in the neighborhood of each pixel
// and store in Mat stddev. Also threshold the values in the src matrix to compute dst matrix.
Mat_
<
float
>
stddev
(
size
);
int
i
,
j
,
threshold
;
uchar
imaxval
=
saturate_cast
<
uchar
>
(
maxValue
);
for
(
i
=
0
;
i
<
size
.
height
;
++
i
)
// Apply thresholding: ( pixel > threshold ) ? foreground : background
Mat
mask
;
switch
(
type
)
{
for
(
j
=
0
;
j
<
size
.
width
;
++
j
)
{
stddev
.
at
<
float
>
(
i
,
j
)
=
saturate_cast
<
float
>
(
delta
)
*
cvRound
(
sqrt
(
sqmean
.
at
<
float
>
(
i
,
j
)
-
mean
.
at
<
float
>
(
i
,
j
)
*
mean
.
at
<
float
>
(
i
,
j
))
);
threshold
=
cvRound
(
mean
.
at
<
float
>
(
i
,
j
)
+
stddev
.
at
<
float
>
(
i
,
j
));
if
(
src
.
at
<
uchar
>
(
i
,
j
)
>
threshold
)
dst
.
at
<
uchar
>
(
i
,
j
)
=
(
type
==
THRESH_BINARY
)
?
imaxval
:
0
;
else
dst
.
at
<
uchar
>
(
i
,
j
)
=
(
type
==
THRESH_BINARY
)
?
0
:
imaxval
;
}
case
THRESH_BINARY
:
// dst = (src > thresh) ? maxval : 0
case
THRESH_BINARY_INV
:
// dst = (src > thresh) ? 0 : maxval
compare
(
src
,
thresh
,
mask
,
(
type
==
THRESH_BINARY
?
CMP_GT
:
CMP_LE
));
dst
.
setTo
(
0
);
dst
.
setTo
(
maxValue
,
mask
);
break
;
case
THRESH_TRUNC
:
// dst = (src > thresh) ? thresh : src
compare
(
src
,
thresh
,
mask
,
CMP_GT
);
src
.
copyTo
(
dst
);
thresh
.
copyTo
(
dst
,
mask
);
break
;
case
THRESH_TOZERO
:
// dst = (src > thresh) ? src : 0
case
THRESH_TOZERO_INV
:
// dst = (src > thresh) ? 0 : src
compare
(
src
,
thresh
,
mask
,
(
type
==
THRESH_TOZERO
?
CMP_GT
:
CMP_LE
));
dst
.
setTo
(
0
);
src
.
copyTo
(
dst
,
mask
);
break
;
default
:
CV_Error
(
CV_StsBadArg
,
"Unknown threshold type"
);
break
;
}
}
}
// namespace ximgproc
}
//namespace cv
}
//
namespace cv
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment