Skip to content

Commit 7d44366

Browse files
committed
Merge pull request #1146 from saskatchewancatch:i1138
2 parents b74c25d + 3ec8e0a commit 7d44366

File tree

4 files changed

+91
-11
lines changed

4 files changed

+91
-11
lines changed

modules/ximgproc/doc/ximgproc.bib

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,3 +222,40 @@ @article{paillou1997detecting
222222
pages={191--196},
223223
year={1997}
224224
}
225+
226+
@book{Niblack1985,
227+
title={An introduction to digital image processing},
228+
author={Niblack, Wayne},
229+
year={1985},
230+
publisher={Strandberg Publishing Company}
231+
}
232+
233+
@inproceedings{Sauvola1997,
234+
title={Adaptive document binarization},
235+
author={Sauvola, Jaakko and Seppanen, Tapio and Haapakoski, Sami and Pietikainen, Matti},
236+
booktitle={Document Analysis and Recognition, 1997., Proceedings of the Fourth International Conference on},
237+
volume={1},
238+
pages={147--152},
239+
year={1997},
240+
organization={IEEE}
241+
}
242+
243+
@article{Wolf2004,
244+
title={Extraction and recognition of artificial text in multimedia documents},
245+
author={Wolf, Christian and Jolion, J-M},
246+
journal={Pattern Analysis \& Applications},
247+
volume={6},
248+
number={4},
249+
pages={309--326},
250+
year={2004},
251+
publisher={Springer}
252+
}
253+
254+
@inproceedings{Khurshid2009,
255+
title={Comparison of Niblack inspired Binarization methods for ancient documents},
256+
author={Khurshid, Khurram and Siddiqi, Imran and Faure, Claudie and Vincent, Nicole},
257+
booktitle={IS\&T/SPIE Electronic Imaging},
258+
pages={72470U--72470U},
259+
year={2009},
260+
organization={International Society for Optics and Photonics}
261+
}

modules/ximgproc/include/opencv2/ximgproc.hpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,21 @@ enum ThinningTypes{
7979
THINNING_GUOHALL = 1 // Thinning technique of Guo-Hall
8080
};
8181

82+
/**
83+
* @brief Specifies the binarization method to use in cv::ximgproc::niBlackThreshold
84+
*/
85+
enum LocalBinarizationMethods{
86+
BINARIZATION_NIBLACK = 0, //!< Classic Niblack binarization. See @cite Niblack1985 .
87+
BINARIZATION_SAUVOLA = 1, //!< Sauvola's technique. See @cite Sauvola1997 .
88+
BINARIZATION_WOLF = 2, //!< Wolf's technique. See @cite Wolf2004 .
89+
BINARIZATION_NICK = 3 //!< NICK technique. See @cite Khurshid2009 .
90+
};
91+
8292
//! @addtogroup ximgproc
8393
//! @{
8494

85-
/** @brief Applies Niblack thresholding to input image.
95+
/** @brief Performs thresholding on input images using Niblack's technique or some of the
96+
popular variations it inspired.
8697
8798
The function transforms a grayscale image to a binary image according to the formulae:
8899
- **THRESH_BINARY**
@@ -91,8 +102,9 @@ The function transforms a grayscale image to a binary image according to the for
91102
\f[dst(x,y) = \fork{0}{if \(src(x,y) > T(x,y)\)}{\texttt{maxValue}}{otherwise}\f]
92103
where \f$T(x,y)\f$ is a threshold calculated individually for each pixel.
93104
94-
The threshold value \f$T(x, y)\f$ is the mean minus \f$ delta \f$ times standard deviation
95-
of \f$\texttt{blockSize} \times\texttt{blockSize}\f$ neighborhood of \f$(x, y)\f$.
105+
The threshold value \f$T(x, y)\f$ is determined based on the binarization method chosen. For
106+
classic Niblack, it is the mean minus \f$ k \f$ times standard deviation of
107+
\f$\texttt{blockSize} \times\texttt{blockSize}\f$ neighborhood of \f$(x, y)\f$.
96108
97109
The function can't process the image in-place.
98110
@@ -103,14 +115,17 @@ used with the THRESH_BINARY and THRESH_BINARY_INV thresholding types.
103115
@param type Thresholding type, see cv::ThresholdTypes.
104116
@param blockSize Size of a pixel neighborhood that is used to calculate a threshold value
105117
for the pixel: 3, 5, 7, and so on.
106-
@param delta Constant multiplied with the standard deviation and subtracted from the mean.
107-
Normally, it is taken to be a real number between 0 and 1.
118+
@param k The user-adjustable parameter used by Niblack and inspired techniques. For Niblack, this is
119+
normally a value between 0 and 1 that is multiplied with the standard deviation and subtracted from
120+
the mean.
121+
@param binarizationMethod Binarization method to use. By default, Niblack's technique is used.
122+
Other techniques can be specified, see cv::ximgproc::LocalBinarizationMethods.
108123
109124
@sa threshold, adaptiveThreshold
110125
*/
111126
CV_EXPORTS_W void niBlackThreshold( InputArray _src, OutputArray _dst,
112127
double maxValue, int type,
113-
int blockSize, double delta );
128+
int blockSize, double k, int binarizationMethod = BINARIZATION_NIBLACK );
114129

115130
/** @brief Applies a binary blob thinning operation, to achieve a skeletization of the input image.
116131

modules/ximgproc/samples/niblack_thresholding.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Mat_<uchar> src;
1616
int k_ = 8;
1717
int blockSize_ = 11;
1818
int type_ = THRESH_BINARY;
19+
int method_ = BINARIZATION_NIBLACK;
1920

2021
void on_trackbar(int, void*);
2122

@@ -34,6 +35,7 @@ int main(int argc, char** argv)
3435
namedWindow("Niblack", WINDOW_AUTOSIZE);
3536
createTrackbar("k", "Niblack", &k_, 20, on_trackbar);
3637
createTrackbar("blockSize", "Niblack", &blockSize_, 30, on_trackbar);
38+
createTrackbar("method", "Niblack", &method_, 3, on_trackbar);
3739
createTrackbar("threshType", "Niblack", &type_, 4, on_trackbar);
3840
on_trackbar(0, 0);
3941
waitKey(0);
@@ -47,7 +49,8 @@ void on_trackbar(int, void*)
4749
int blockSize = 2*(blockSize_ >= 1 ? blockSize_ : 1) + 1; // 3,5,7,...,61
4850
int type = type_; // THRESH_BINARY, THRESH_BINARY_INV,
4951
// THRESH_TRUNC, THRESH_TOZERO, THRESH_TOZERO_INV
52+
int method = method_; //BINARIZATION_NIBLACK, BINARIZATION_SAUVOLA, BINARIZATION_WOLF, BINARIZATION_NICK
5053
Mat dst;
51-
niBlackThreshold(src, dst, 255, type, blockSize, k);
54+
niBlackThreshold(src, dst, 255, type, blockSize, k, method);
5255
imshow("Niblack", dst);
5356
}

modules/ximgproc/src/niblack_thresholding.cpp

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,15 @@ namespace cv {
4747
namespace ximgproc {
4848

4949
void niBlackThreshold( InputArray _src, OutputArray _dst, double maxValue,
50-
int type, int blockSize, double delta )
50+
int type, int blockSize, double k, int binarizationMethod )
5151
{
5252
// Input grayscale image
5353
Mat src = _src.getMat();
5454
CV_Assert(src.channels() == 1);
5555
CV_Assert(blockSize % 2 == 1 && blockSize > 1);
56+
if (binarizationMethod == BINARIZATION_SAUVOLA) {
57+
CV_Assert(src.depth() == CV_8U);
58+
}
5659
type &= THRESH_MASK;
5760

5861
// Compute local threshold (T = mean + k * stddev)
@@ -61,13 +64,35 @@ void niBlackThreshold( InputArray _src, OutputArray _dst, double maxValue,
6164
Mat thresh;
6265
{
6366
// note that: Var[X] = E[X^2] - E[X]^2
64-
Mat mean, sqmean, stddev;
67+
Mat mean, sqmean, variance, stddev, sqrtVarianceMeanSum;
68+
double srcMin, stddevMax;
6569
boxFilter(src, mean, CV_32F, Size(blockSize, blockSize),
6670
Point(-1,-1), true, BORDER_REPLICATE);
6771
sqrBoxFilter(src, sqmean, CV_32F, Size(blockSize, blockSize),
6872
Point(-1,-1), true, BORDER_REPLICATE);
69-
sqrt(sqmean - mean.mul(mean), stddev);
70-
thresh = mean + stddev * static_cast<float>(delta);
73+
variance = sqmean - mean.mul(mean);
74+
sqrt(variance, stddev);
75+
switch (binarizationMethod)
76+
{
77+
case BINARIZATION_NIBLACK:
78+
thresh = mean + stddev * static_cast<float>(k);
79+
break;
80+
case BINARIZATION_SAUVOLA:
81+
thresh = mean.mul(1. + static_cast<float>(k) * (stddev / 128.0 - 1.));
82+
break;
83+
case BINARIZATION_WOLF:
84+
minMaxIdx(src, &srcMin);
85+
minMaxIdx(stddev, NULL, &stddevMax);
86+
thresh = mean - static_cast<float>(k) * (mean - srcMin - stddev.mul(mean - srcMin) / stddevMax);
87+
break;
88+
case BINARIZATION_NICK:
89+
sqrt(variance + sqmean, sqrtVarianceMeanSum);
90+
thresh = mean + static_cast<float>(k) * sqrtVarianceMeanSum;
91+
break;
92+
default:
93+
CV_Error( CV_StsBadArg, "Unknown binarization method" );
94+
break;
95+
}
7196
thresh.convertTo(thresh, src.depth());
7297
}
7398

0 commit comments

Comments
 (0)