From c9683d2bb63611fea2a71c1c640b689ba2fcba29 Mon Sep 17 00:00:00 2001 From: zvezdochiot Date: Tue, 13 Aug 2024 02:53:51 +0300 Subject: [PATCH] 1.0.20: threshold: new method Grad: lower/upper bound --- src/app/DefaultParamsDialog.cpp | 6 +++--- src/core/filters/output/OptionsWidget.cpp | 2 +- src/core/filters/output/OutputGenerator.cpp | 6 ++++-- src/imageproc/Binarize.cpp | 9 +++++++-- src/imageproc/Binarize.h | 7 ++++++- 5 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/app/DefaultParamsDialog.cpp b/src/app/DefaultParamsDialog.cpp index 982efd36..4bd4f852 100644 --- a/src/app/DefaultParamsDialog.cpp +++ b/src/app/DefaultParamsDialog.cpp @@ -667,10 +667,10 @@ std::unique_ptr DefaultParamsDialog::buildParams() const { blackWhiteOptions.setBinarizationMethod(binarizationMethod); blackWhiteOptions.setThresholdAdjustment(thresholdSlider->value()); blackWhiteOptions.setSauvolaCoef(sauvolaCoef->value()); - if (binarizationMethod == T_SAUVOLA || binarizationMethod == T_BRADLEY || binarizationMethod == T_GRAD - || binarizationMethod == T_EDGEPLUS || binarizationMethod == T_BLURDIV || binarizationMethod == T_EDGEDIV) { + if (binarizationMethod == T_SAUVOLA || binarizationMethod == T_BRADLEY || binarizationMethod == T_EDGEPLUS + || binarizationMethod == T_BLURDIV || binarizationMethod == T_EDGEDIV) { blackWhiteOptions.setWindowSize(sauvolaWindowSize->value()); - } else if (binarizationMethod == T_WOLF) { + } else if (binarizationMethod == T_WOLF || binarizationMethod == T_GRAD) { blackWhiteOptions.setWindowSize(wolfWindowSize->value()); } blackWhiteOptions.setWolfCoef(wolfCoef->value()); diff --git a/src/core/filters/output/OptionsWidget.cpp b/src/core/filters/output/OptionsWidget.cpp index 8eb945b1..4abe91aa 100644 --- a/src/core/filters/output/OptionsWidget.cpp +++ b/src/core/filters/output/OptionsWidget.cpp @@ -58,7 +58,7 @@ OptionsWidget::OptionsWidget(std::shared_ptr settings, const PageSelec QPointer wolfBinarizationOptionsWidget = new WolfBinarizationOptionsWidget(m_settings); QPointer bradleyBinarizationOptionsWidget = new SauvolaBinarizationOptionsWidget(m_settings); - QPointer gradBinarizationOptionsWidget = new SauvolaBinarizationOptionsWidget(m_settings); + QPointer gradBinarizationOptionsWidget = new WolfBinarizationOptionsWidget(m_settings); QPointer edgeplusBinarizationOptionsWidget = new SauvolaBinarizationOptionsWidget(m_settings); QPointer blurdivBinarizationOptionsWidget diff --git a/src/core/filters/output/OutputGenerator.cpp b/src/core/filters/output/OutputGenerator.cpp index bc44ea9c..9c8e5375 100644 --- a/src/core/filters/output/OutputGenerator.cpp +++ b/src/core/filters/output/OutputGenerator.cpp @@ -2330,9 +2330,11 @@ BinaryImage OutputGenerator::Processor::binarize(const QImage& image) const { case T_GRAD: { const double thresholdDelta = blackWhiteOptions.thresholdAdjustment(); const QSize windowsSize = QSize(blackWhiteOptions.getWindowSize(), blackWhiteOptions.getWindowSize()); - const double thresholdCoef = blackWhiteOptions.getSauvolaCoef(); + const auto lowerBound = (unsigned char) blackWhiteOptions.getWolfLowerBound(); + const auto upperBound = (unsigned char) blackWhiteOptions.getWolfUpperBound(); + const double thresholdCoef = blackWhiteOptions.getWolfCoef(); - binarized = binarizeGrad(image, windowsSize, thresholdCoef, thresholdDelta); + binarized = binarizeGrad(image, windowsSize, lowerBound, upperBound, thresholdCoef, thresholdDelta); break; } case T_EDGEPLUS: { diff --git a/src/imageproc/Binarize.cpp b/src/imageproc/Binarize.cpp index b24c6ef4..be434027 100644 --- a/src/imageproc/Binarize.cpp +++ b/src/imageproc/Binarize.cpp @@ -277,7 +277,12 @@ BinaryImage binarizeBradley(const QImage& src, const QSize windowSize, const dou return bwImg; } // binarizeBradley -BinaryImage binarizeGrad(const QImage& src, const QSize windowSize, const double k, const double delta) { +BinaryImage binarizeGrad(const QImage& src, + const QSize windowSize, + const unsigned char lowerBound, + const unsigned char upperBound, + const double k, + const double delta) { if (windowSize.isEmpty()) { throw std::invalid_argument("binarizeGrad: invalid windowSize"); } @@ -376,7 +381,7 @@ BinaryImage binarizeGrad(const QImage& src, const QSize windowSize, const double const double threshold = meanGrad + mean * k; const uint32_t msb = uint32_t(1) << 31; const uint32_t mask = msb >> (x & 31); - if (origin < (threshold + delta)) { + if ((grayLine[x] < lowerBound) || ((grayLine[x] <= upperBound) && (origin < (threshold + delta)))) { // black bwLine[x >> 5] |= mask; } else { diff --git a/src/imageproc/Binarize.h b/src/imageproc/Binarize.h index 481ff830..637d3c01 100644 --- a/src/imageproc/Binarize.h +++ b/src/imageproc/Binarize.h @@ -74,7 +74,12 @@ BinaryImage binarizeBradley(const QImage& src, QSize windowSize, double k = 0.34 * * Grad (aka "Gradient snip"), zvezdochiot 2024. "Adaptive/global document image binarization". */ -BinaryImage binarizeGrad(const QImage& src, QSize windowSize, double k = 0.34, double delta = 0.0); +BinaryImage binarizeGrad(const QImage& src, + QSize windowSize, + unsigned char lowerBound = 1, + unsigned char upperBound = 254, + double k = 0.3, + double delta = 0.0); /** * \brief Image binarization using EdgeDiv (EdgePlus & BlurDiv) local/global thresholding method.