22 #ifndef CRNIMAGEGRAY_HEADER
23 #define CRNIMAGEGRAY_HEADER
47 template<
typename T>
void Abs(
Image<T> &img,
typename std::enable_if<std::is_arithmetic<T>::value>::type *dummy =
nullptr) noexcept
66 const auto mM =
MinMax(img);
67 auto h =
Histogram(
size_t(mM.second - mM.first + 1));
69 h.IncBin(
size_t(v - mM.first));
90 template<
typename T>
size_t StrokesWidth(
const Image<T> &img,
size_t maxval = 50,
size_t defaultval = 0,
typename std::enable_if<std::is_arithmetic<T>::value>::type *dummy =
nullptr)
92 auto strokeswidth = size_t(0);
94 for (strokeswidth = 1; strokeswidth <
Min(maxval, img.
GetWidth()); strokeswidth++)
97 for (
size_t y = 0; y < img.
GetHeight(); y++)
101 for (
size_t x = 0; x < img.
GetWidth(); x++)
103 auto tx = int(x) - int(strokeswidth);
104 if (tx < 0) tx += int(img.
GetWidth());
106 tacc +=
Abs(img.
At(x + yoffset) - img.
At(tx + yoffset));
131 template<
typename T>
size_t StrokesHeight(
const Image<T> &img,
size_t maxval = 50,
size_t defaultval = 0,
typename std::enable_if<std::is_arithmetic<T>::value>::type *dummy =
nullptr)
133 auto strokesheight = size_t(0);
135 for (strokesheight = 1; strokesheight <
Min(maxval, img.
GetHeight()); strokesheight++)
138 for (
size_t y = 0; y < img.
GetHeight(); y++)
141 for (
size_t x = 0; x < img.
GetWidth(); x++)
143 auto ty = int(y) - int(strokesheight);
146 tacc +=
Abs(img.
At(x, y) - img.
At(x, ty));
154 return strokesheight;
180 for (
auto tmp :
Range(img))
182 auto v = img.
At(tmp);
186 uint8_t(
int(32 + v * 33) & 0xFF),
187 uint8_t(
int(32 + v * 55) & 0xFF),
188 uint8_t(
int(32 + v * 77) & 0xFF)
207 for (
auto i :
Range(img))
208 out.
At(i) = cmp(img.
At(i), thresh) ? pixel::BWBlack : pixel::BWWhite;
229 template<
typename T>
ImageBW Niblack(
const Image<T> &img,
size_t halfwin,
double k = 0.5,
typename std::enable_if<std::is_arithmetic<T>::value>::type *dummy =
nullptr)
235 auto x1 = (x < halfwin) ? 0 : x - halfwin;
236 auto y1 = (y < halfwin) ? 0 : y - halfwin;
237 auto x2 = x + halfwin;
239 auto y2 = y + halfwin;
245 for (
auto ty = y1; ty <= y2; ty++)
246 for (
auto tx = x1; tx <= x2; tx++)
252 auto size = (x2 - x1 + 1) * (y2 - y1 + 1);
253 auto m = sum / double(size);
254 auto sd = sqrt(sqrsum /
double(size) -
Sqr(m));
257 auto t = m + k * sd ;
259 out.At(x, y) = (img.
At(x, y) < T(t)) ? pixel::BWBlack : pixel::BWWhite;
282 template<
typename T>
ImageBW Sauvola(
const Image<T> &img,
size_t halfwin,
double k = 0.5,
typename std::enable_if<std::is_arithmetic<T>::value>::type *dummy =
nullptr)
285 const auto mM =
MinMax(img);
292 auto x1 = (x < halfwin) ? 0 : x - halfwin;
293 auto y1 = (y < halfwin) ? 0 : y - halfwin;
294 auto x2 = x + halfwin;
296 auto y2 = y + halfwin;
303 for (
auto ty = y1; ty <= y2; ty++)
304 for (
auto tx = x1; tx <= x2; tx++)
311 auto size = (x2 - x1 + 1) * (y2 - y1 + 1);
312 auto m = sum / double(size);
313 auto sd = sqrt(sqrsum /
double(size) -
Sqr(m));
317 auto t = m * (1 + k * (sd / dynRge - 1));
319 out.At(x, y) = (img.
At(x, y) < T(t)) ? pixel::BWBlack : pixel::BWWhite;
335 template<
typename T>
ImageBW kMeansHisto(
const Image<T> &img,
size_t classes,
size_t black_classes,
size_t maxcnt = 10000,
typename std::enable_if<std::is_arithmetic<T>::value>::type *dummy =
nullptr)
337 if (classes < 2 || black_classes < 1)
341 if (histo.Size() < 3)
344 auto protos = std::vector<int>(classes);
345 for (
auto tmp :
Range(protos))
347 protos[tmp] = int(tmp * (histo.Size() - 1) / (classes));
352 auto cumul = std::vector<int>(classes, 0);
353 auto cnt = std::vector<int>(classes, 0);
355 for (
auto tmp :
Range(histo))
359 auto d =
Abs(
int(tmp) - protos[0]);
360 for (
auto tmpc =
size_t(1); tmpc < classes; ++tmpc)
362 const auto td =
Abs(
int(tmp) - protos[tmpc]);
369 cumul[c] += int(tmp);
370 cnt[c] += int(histo[tmp]);
372 for (
auto tmp :
Range(cumul))
374 cumul[tmp] /= cnt[tmp];
375 ok = (protos == cumul);
383 double threshold = double(protos[black_classes - 1] + protos[black_classes]) / 2.0;
385 for (
auto tmp :
Range(img))
387 if (
double(img.
At(tmp)) > threshold)
388 out.
At(tmp) = pixel::BWWhite;
390 out.
At(tmp) = pixel::BWBlack;
404 template<
typename T>
ImageBW LocalMin(
const Image<T> &img,
size_t area = 1,
typename std::enable_if<std::is_arithmetic<T>::value>::type *dummy =
nullptr)
408 auto offset = size_t(0);
409 for (
int y = 0; y < int(img.
GetHeight()); y++)
410 for (
int x = 0; x < int(img.
GetWidth()); x++)
412 auto val = img.
At(offset);
413 for (
int ty =
Max(y -
int(area), 0); ty <=
Min(
int(img.
GetHeight()) - 1, y +
int(area)); ty++)
414 for (
int tx =
Max(x -
int(area), 0); tx <=
Min(
int(img.
GetWidth()) - 1, x +
int(area)); tx++)
416 if (img.
At(tx, ty) < val)
418 ibw.At(offset) = pixel::BWWhite;
429 auto offset = size_t(0);
430 for (
int y = 0; y < int(img.
GetHeight()); y++)
431 for (
int x = 0; x < int(img.
GetWidth()); x++)
433 if (ibw.At(offset) == pixel::BWBlack)
435 auto val = img.
At(offset);
436 for (
int ty =
Max(y -
int(area), 0); ty <=
Min(
int(img.
GetHeight()) - 1, y +
int(area)); ty++)
437 for (
int tx =
Max(x -
int(area), 0); tx <=
Min(
int(img.
GetWidth()) - 1, x +
int(area)); tx++)
439 if ((ibw.At(tx, ty) == pixel::BWWhite) &&
440 (img.
At(tx, ty) == val))
442 ibw.At(offset) = pixel::BWWhite;
463 template<
typename T>
ImageBW LocalMax(
const Image<T> &img,
size_t area = 1,
typename std::enable_if<std::is_arithmetic<T>::value>::type *dummy =
nullptr)
467 auto offset = size_t(0);
468 for (
int y = 0; y < int(img.
GetHeight()); y++)
469 for (
int x = 0; x < int(img.
GetWidth()); x++)
471 auto val = img.
At(offset);
472 for (
int ty =
Max(y -
int(area), 0); ty <=
Min(
int(img.
GetHeight()) - 1, y +
int(area)); ty++)
473 for (
int tx =
Max(x -
int(area), 0); tx <=
Min(
int(img.
GetWidth()) - 1, x +
int(area)); tx++)
475 if (img.
At(tx, ty) > val)
477 ibw.
At(offset) = pixel::BWWhite;
488 auto offset = size_t(0);
489 for (
int y = 0; y < int(img.
GetHeight()); y++)
490 for (
int x = 0; x < int(img.
GetWidth()); x++)
492 if (ibw.
At(offset) == pixel::BWBlack)
494 auto val = img.
At(offset);
495 for (
int ty =
Max(y -
int(area), 0); ty <=
Min(
int(img.
GetHeight()) - 1, y +
int(area)); ty++)
496 for (
int tx =
Max(x -
int(area), 0); tx <=
Min(
int(img.
GetWidth()) - 1, x +
int(area)); tx++)
498 if ((ibw.
At(tx, ty) == pixel::BWWhite) &&
499 (img.
At(tx, ty) == val))
501 ibw.
At(offset) = pixel::BWWhite;
521 template<
typename T>
ImageBW Fisher(
const Image<T> &img,
typename std::enable_if<std::is_arithmetic<T>::value>::type *dummy =
nullptr)
523 const auto mM =
MinMax(img);
537 const auto t = h.Fisher();
540 thresh = T(mM.first + T(
double(t) / 100.0));
542 thresh = T(mM.first + T(t));
553 template<
typename T>
ImageBW Entropy(
const Image<T> &img,
typename std::enable_if<std::is_arithmetic<T>::value>::type *dummy =
nullptr)
555 const auto mM =
MinMax(img);
569 const auto t = h.EntropyThreshold();
572 thresh = T(mM.first + T(
double(t) / 100.0));
574 thresh = T(mM.first + T(t));
585 template<
typename T>
ImageBW Otsu(
const Image<T> &img,
typename std::enable_if<std::is_arithmetic<T>::value>::type *dummy =
nullptr)
589 const auto hsize = h.Size();
590 auto mu = std::vector<double>(hsize, 0.0);
591 auto w = std::vector<double>(hsize, 0.0);
592 auto s2 = std::vector<double>(hsize, 0.0);
593 auto hnorm = std::vector<double>(hsize, 0.0);
595 const auto cumul = double(h.CumulateBins());
596 for (
size_t k = 0; k < hsize; ++k)
598 hnorm[k] = double(h.GetBin(k))/ cumul;
601 for (
size_t k = 0; k < hsize; ++k)
603 for (
size_t j = 0; j < k; ++j)
605 mu[k] += double(j) * hnorm[j];
609 for (
size_t k = 0; k < hsize; ++k)
611 s2[k] = w[k] * (1 - w[k]) * (mu[hsize-1] * w[k] - mu[k]) * (mu[hsize-1] * w[k] - mu[k]);
616 for (
size_t k = 0;k < hsize; k++)
typename TypeInfo< T >::SumType SumType
virtual StringUTF8 GetClassName() const override
void AutoContrast(ImageGray &img)
Abstract class for images.
ImageBW Sauvola(const Image< T > &img, size_t halfwin, double k=0.5, typename std::enable_if< std::is_arithmetic< T >::value >::type *dummy=nullptr)
ImageBW Entropy(const Image< T > &img, typename std::enable_if< std::is_arithmetic< T >::value >::type *dummy=nullptr)
Image< pixel::BW > ImageBW
Black and white image class.
ScalarRange< T > Range(T b, T e)
Creates a range [[b, e[[.
#define CRN_SERIALIZATION_CONSTRUCTOR(classname)
Defines a default constructor from xml element.
ImageBW Fisher(const Image< T > &img, typename std::enable_if< std::is_arithmetic< T >::value >::type *dummy=nullptr)
ImageBW MakeImageBW(const ImageGray &img)
virtual ~Gray2BWEntropy() override
virtual StringUTF8 GetClassName() const override
Fisher binarization action.
std::vector< pixel_type >::reference At(size_t x, size_t y) noexcept
Returns a reference to a pixel.
size_t GetHeight() const noexcept
Image< uint8_t > ImageGray
Grayscale image class.
virtual StringUTF8 GetClassName() const override
const T & Max(const T &a, const T &b)
Returns the max of two values.
Image< pixel::RGB< uint8_t >> ImageRGB
Color image class.
virtual ~Gray2BWSauvola() override
virtual ImageBW Binarize(const ImageGray &img) override
Action = binarize a gray image.
virtual ~Gray2BWkMeansHisto() override
Niblack binarization action.
Otsu binarization action.
ImageBW kMeansHisto(const Image< T > &img, size_t classes, size_t black_classes, size_t maxcnt=10000, typename std::enable_if< std::is_arithmetic< T >::value >::type *dummy=nullptr)
#define FOREACHPIXEL(x, y, img)
Convenience macro to sweep an image.
void Sqrt(ImageDoubleGray &img) noexcept
Replaces the pixels with their square root.
ImageBW LocalMin(const Image< T > &img, size_t area=1, typename std::enable_if< std::is_arithmetic< T >::value >::type *dummy=nullptr)
virtual ~Gray2BWLocalMax() override
size_t EstimateLeading(const ImageGray &img)
Computes the median distance between two baselines.
ImageBW Niblack(const Image< T > &img, size_t halfwin, double k=0.5, typename std::enable_if< std::is_arithmetic< T >::value >::type *dummy=nullptr)
size_t StrokesHeight(const Image< T > &img, size_t maxval=50, size_t defaultval=0, typename std::enable_if< std::is_arithmetic< T >::value >::type *dummy=nullptr)
virtual StringUTF8 GetClassName() const override
virtual ~Gray2BWThreshold() override
virtual ~Gray2BWOtsu() override
Image< double > ImageDoubleGray
double Grayscale image class
ImageBW Otsu(const Image< T > &img, typename std::enable_if< std::is_arithmetic< T >::value >::type *dummy=nullptr)
constexpr SumType< T > Sqr(const T &v) noexcept(noexcept(v *v))
Returns the square of a value.
Threshold binarization action.
virtual ~Gray2BWLocalMin() override
ImageBW Threshold(const Image< T > &img, T thresh, CMP cmp=std::less< T >{})
virtual ~Gray2BWFisher() override
typename TypeInfo< T >::DecimalType DecimalType
virtual ~Gray2BWNiblack() override
virtual StringUTF8 GetClassName() const override
void Abs(Image< T > &img, typename std::enable_if< std::is_arithmetic< T >::value >::type *dummy=nullptr) noexcept
Replaces each pixel by its absolute value.
const T & Min(const T &a, const T &b)
Returns the min of two values.
virtual StringUTF8 GetClassName() const override
virtual ImageBW Binarize(const ImageGray &img)=0
Action = binarize a gray image.
size_t EstimateLinesXHeight(const ImageGray &img, unsigned int xdiv=16)
Computes the mean text line x-height.
Mother class for integer histograms.
virtual StringUTF8 GetClassName() const override
Entropy binarization action.
Local max binarization action.
ImageBW LocalMax(const Image< T > &img, size_t area=1, typename std::enable_if< std::is_arithmetic< T >::value >::type *dummy=nullptr)
std::pair< T, T > MinMax(const Image< T > &img, CMP cmp=CMP{})
Returns min and max pixel values.
size_t GetWidth() const noexcept
Angle< Radian > EstimateSkew(const ImageGray &img)
Estimates the mean skew of the document's lines.
virtual ~Gray2BW() override
#define CRN_DECLARE_CLASS_CONSTRUCTOR(classname)
Declares a class constructor.
virtual StringUTF8 GetClassName() const override
virtual StringUTF8 GetClassName() const override
size_t StrokesWidth(const Image< T > &img, size_t maxval=50, size_t defaultval=0, typename std::enable_if< std::is_arithmetic< T >::value >::type *dummy=nullptr)
Histogram HorizontalProjection(const ImageBW &img)
Computes the horizontal projection.
CRN_ALIAS_SMART_PTR(ImageBW)
A character string class.
Sauvola binarization action.
k-means histo binarization action
ImageRGB RandomColors(const Image< T > &img, typename std::enable_if< std::is_arithmetic< T >::value >::type *dummy=nullptr)
Histogram MakeHistogram(const Image< T > &img, typename std::enable_if< std::is_arithmetic< T >::value >::type *dummy=nullptr)
Histogram VerticalProjection(const ImageBW &img)
Computes the vertical projection.
Local min binarization action.
Gray2BWThreshold(uint8_t t=127)
Default constructor.