Skip to content

Commit

Permalink
Merge pull request ScanTailor-Advanced#48 from ImageProcessing-Electr…
Browse files Browse the repository at this point in the history
…onicPublications/master

feature ScanTailor-Advanced#47: binarizeEdgePlus
feature ScanTailor-Advanced#8 
feature ScanTailor-Advanced#59
  • Loading branch information
vigri authored Jul 16, 2023
2 parents 8d45d0d + 3fe3b73 commit b0788fc
Show file tree
Hide file tree
Showing 31 changed files with 309 additions and 83 deletions.
6 changes: 5 additions & 1 deletion src/app/DefaultParamsDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ DefaultParamsDialog::DefaultParamsDialog(QWidget* parent)
thresholdMethodBox->addItem(tr("Otsu"), OTSU);
thresholdMethodBox->addItem(tr("Sauvola"), SAUVOLA);
thresholdMethodBox->addItem(tr("Wolf"), WOLF);
thresholdMethodBox->addItem(tr("EdgePlus"), EDGEPLUS);
thresholdMethodBox->addItem(tr("BlurDiv"), BLURDIV);
thresholdMethodBox->addItem(tr("EdgeDiv"), EDGEDIV);

pictureShapeSelector->addItem(tr("Off"), OFF_SHAPE);
pictureShapeSelector->addItem(tr("Free"), FREE_SHAPE);
Expand Down Expand Up @@ -662,7 +665,8 @@ std::unique_ptr<DefaultParams> DefaultParamsDialog::buildParams() const {
blackWhiteOptions.setBinarizationMethod(binarizationMethod);
blackWhiteOptions.setThresholdAdjustment(thresholdSlider->value());
blackWhiteOptions.setSauvolaCoef(sauvolaCoef->value());
if (binarizationMethod == SAUVOLA) {
if (binarizationMethod == SAUVOLA || binarizationMethod == EDGEPLUS || binarizationMethod == BLURDIV
|| binarizationMethod == EDGEDIV) {
blackWhiteOptions.setWindowSize(sauvolaWindowSize->value());
} else if (binarizationMethod == WOLF) {
blackWhiteOptions.setWindowSize(wolfWindowSize->value());
Expand Down
5 changes: 3 additions & 2 deletions src/app/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2080,8 +2080,9 @@ void MainWindow::execGotoPageDialog() {
bool ok;
const PageSequence pageSequence = m_thumbSequence->toPageSequence();
const PageId& selectionLeader = m_thumbSequence->selectionLeader().id();
int pageNumber = QInputDialog::getInt(this, tr("Go To Page"), tr("Enter the page number:"),
pageSequence.pageNo(selectionLeader) + 1, 1, pageSequence.numPages(), 1, &ok);
int pageNumber
= QInputDialog::getInt(this, tr("Go To Page"), tr("Enter the page number:"),
pageSequence.pageNo(selectionLeader) + 1, 1, (int) (pageSequence.numPages()), 1, &ok);
if (ok) {
const PageId& newSelectionLeader = pageSequence.pageAt(pageNumber - 1).id();
if (selectionLeader != newSelectionLeader) {
Expand Down
2 changes: 1 addition & 1 deletion src/app/RelinkablePathVisualization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ void RelinkablePathVisualization::clear() {

void RelinkablePathVisualization::setPath(const RelinkablePath& path, bool clickable) {
clear();
#if QT_VERSION_MAJOR == 5 and QT_VERSION_MINOR < 14
#if QT_VERSION_MAJOR == 5 && QT_VERSION_MINOR < 14
auto opt = QString::SkipEmptyParts;
#else
auto opt = Qt::SkipEmptyParts;
Expand Down
2 changes: 1 addition & 1 deletion src/core/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ std::list<QString> Application::getLanguagesList() const {
}

void Application::initTranslations() {
#if QT_VERSION_MAJOR == 5 and QT_VERSION_MINOR < 14
#if QT_VERSION_MAJOR == 5 && QT_VERSION_MINOR < 14
auto opt = QString::SkipEmptyParts;
#else
auto opt = Qt::SkipEmptyParts;
Expand Down
4 changes: 2 additions & 2 deletions src/core/BackgroundTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ class BackgroundTask : public AbstractCommand<FilterResultPtr>, public TaskStatu
Type type() const { return m_type; }

void cancel() override {
#if QT_VERSION_MAJOR == 5 and QT_VERSION_MINOR < 14
#if QT_VERSION_MAJOR == 5 && QT_VERSION_MINOR < 14
m_cancelFlag.store(1);
#else
m_cancelFlag.storeRelaxed(1);
#endif
}

bool isCancelled() const override {
#if QT_VERSION_MAJOR == 5 and QT_VERSION_MINOR < 14
#if QT_VERSION_MAJOR == 5 && QT_VERSION_MINOR < 14
return m_cancelFlag.load() != 0;
#else
return m_cancelFlag.loadRelaxed() != 0;
Expand Down
2 changes: 1 addition & 1 deletion src/core/RelinkablePath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ QString RelinkablePath::normalize(const QString& path) {
frontSlashes.replace(QChar('\\'), QLatin1String("/"));

QStringList newComponents;
#if QT_VERSION_MAJOR == 5 and QT_VERSION_MINOR < 14
#if QT_VERSION_MAJOR == 5 && QT_VERSION_MINOR < 14
auto opt = QString::KeepEmptyParts;
#else
auto opt = Qt::KeepEmptyParts;
Expand Down
17 changes: 16 additions & 1 deletion src/core/filters/output/BlackWhiteOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ BinarizationMethod BlackWhiteOptions::parseBinarizationMethod(const QString& str
return WOLF;
} else if (str == "sauvola") {
return SAUVOLA;
} else if (str == "edgeplus") {
return EDGEPLUS;
} else if (str == "blurdiv") {
return BLURDIV;
} else if (str == "edgediv") {
return EDGEDIV;
} else {
return OTSU;
}
Expand All @@ -89,6 +95,15 @@ QString BlackWhiteOptions::formatBinarizationMethod(BinarizationMethod type) {
case WOLF:
str = "wolf";
break;
case EDGEPLUS:
str = "edgeplus";
break;
case BLURDIV:
str = "blurdiv";
break;
case EDGEDIV:
str = "edgediv";
break;
}
return str;
}
Expand Down Expand Up @@ -129,4 +144,4 @@ bool BlackWhiteOptions::ColorSegmenterOptions::operator==(const BlackWhiteOption
bool BlackWhiteOptions::ColorSegmenterOptions::operator!=(const BlackWhiteOptions::ColorSegmenterOptions& other) const {
return !(*this == other);
}
} // namespace output
} // namespace output
2 changes: 1 addition & 1 deletion src/core/filters/output/BlackWhiteOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class QDomDocument;
class QDomElement;

namespace output {
enum BinarizationMethod { OTSU, SAUVOLA, WOLF };
enum BinarizationMethod { OTSU, SAUVOLA, WOLF, EDGEPLUS, BLURDIV, EDGEDIV };

class BlackWhiteOptions {
public:
Expand Down
2 changes: 1 addition & 1 deletion src/core/filters/output/DewarpingView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ void DewarpingView::onPaint(QPainter& painter, const InteractionState& interacti
const dewarping::Curve& bottomCurve = m_distortionModel.bottomCurve();
painter.drawLine(topCurve.polyline().front(), bottomCurve.polyline().front());
painter.drawLine(topCurve.polyline().back(), bottomCurve.polyline().back());
#if QT_VERSION_MAJOR == 5 and QT_VERSION_MINOR < 14
#if QT_VERSION_MAJOR == 5 && QT_VERSION_MINOR < 14
painter.drawPolyline(QVector<QPointF>::fromStdVector(topCurve.polyline()));
painter.drawPolyline(QVector<QPointF>::fromStdVector(bottomCurve.polyline()));
#else
Expand Down
14 changes: 13 additions & 1 deletion src/core/filters/output/OptionsWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ OptionsWidget::OptionsWidget(std::shared_ptr<Settings> settings, const PageSelec
thresholdMethodBox->addItem(tr("Otsu"), OTSU);
thresholdMethodBox->addItem(tr("Sauvola"), SAUVOLA);
thresholdMethodBox->addItem(tr("Wolf"), WOLF);
thresholdMethodBox->addItem(tr("EdgePlus"), EDGEPLUS);
thresholdMethodBox->addItem(tr("BlurDiv"), BLURDIV);
thresholdMethodBox->addItem(tr("EdgeDiv"), EDGEDIV);

fillingColorBox->addItem(tr("Background"), FILL_BACKGROUND);
fillingColorBox->addItem(tr("White"), FILL_WHITE);
Expand All @@ -51,13 +54,22 @@ OptionsWidget::OptionsWidget(std::shared_ptr<Settings> settings, const PageSelec
QPointer<BinarizationOptionsWidget> sauvolaBinarizationOptionsWidget
= new SauvolaBinarizationOptionsWidget(m_settings);
QPointer<BinarizationOptionsWidget> wolfBinarizationOptionsWidget = new WolfBinarizationOptionsWidget(m_settings);
QPointer<BinarizationOptionsWidget> edgeplusBinarizationOptionsWidget
= new SauvolaBinarizationOptionsWidget(m_settings);
QPointer<BinarizationOptionsWidget> blurdivBinarizationOptionsWidget
= new SauvolaBinarizationOptionsWidget(m_settings);
QPointer<BinarizationOptionsWidget> edgedivBinarizationOptionsWidget
= new SauvolaBinarizationOptionsWidget(m_settings);

while (binarizationOptions->count() != 0) {
binarizationOptions->removeWidget(binarizationOptions->widget(0));
}
addBinarizationOptionsWidget(otsuBinarizationOptionsWidget);
addBinarizationOptionsWidget(sauvolaBinarizationOptionsWidget);
addBinarizationOptionsWidget(wolfBinarizationOptionsWidget);
addBinarizationOptionsWidget(edgeplusBinarizationOptionsWidget);
addBinarizationOptionsWidget(blurdivBinarizationOptionsWidget);
addBinarizationOptionsWidget(edgedivBinarizationOptionsWidget);
updateBinarizationOptionsDisplay(binarizationOptions->currentIndex());

pictureShapeSelector->addItem(tr("Off"), OFF_SHAPE);
Expand Down Expand Up @@ -983,4 +995,4 @@ void OptionsWidget::applyProcessingParamsConfirmed(const std::set<PageId>& pages
void OptionsWidget::updateProcessingDisplay() {
blackOnWhiteCB->setChecked(m_settings->getParams(m_pageId).isBlackOnWhite());
}
} // namespace output
} // namespace output
34 changes: 30 additions & 4 deletions src/core/filters/output/OutputGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2219,19 +2219,45 @@ BinaryImage OutputGenerator::Processor::binarize(const QImage& image) const {
break;
}
case SAUVOLA: {
double thresholdDelta = blackWhiteOptions.thresholdAdjustment();
QSize windowsSize = QSize(blackWhiteOptions.getWindowSize(), blackWhiteOptions.getWindowSize());
double sauvolaCoef = blackWhiteOptions.getSauvolaCoef();
double thresholdCoef = blackWhiteOptions.getSauvolaCoef();

binarized = binarizeSauvola(image, windowsSize, sauvolaCoef);
binarized = binarizeSauvola(image, windowsSize, thresholdCoef, thresholdDelta);
break;
}
case WOLF: {
double thresholdDelta = blackWhiteOptions.thresholdAdjustment();
QSize windowsSize = QSize(blackWhiteOptions.getWindowSize(), blackWhiteOptions.getWindowSize());
auto lowerBound = (unsigned char) blackWhiteOptions.getWolfLowerBound();
auto upperBound = (unsigned char) blackWhiteOptions.getWolfUpperBound();
double wolfCoef = blackWhiteOptions.getWolfCoef();
double thresholdCoef = blackWhiteOptions.getWolfCoef();

binarized = binarizeWolf(image, windowsSize, lowerBound, upperBound, wolfCoef);
binarized = binarizeWolf(image, windowsSize, lowerBound, upperBound, thresholdCoef, thresholdDelta);
break;
}
case EDGEPLUS: {
double thresholdDelta = blackWhiteOptions.thresholdAdjustment();
QSize windowsSize = QSize(blackWhiteOptions.getWindowSize(), blackWhiteOptions.getWindowSize());
double thresholdCoef = blackWhiteOptions.getSauvolaCoef();

binarized = binarizeEdgeDiv(image, windowsSize, thresholdCoef, 0.0, thresholdDelta);
break;
}
case BLURDIV: {
double thresholdDelta = blackWhiteOptions.thresholdAdjustment();
QSize windowsSize = QSize(blackWhiteOptions.getWindowSize(), blackWhiteOptions.getWindowSize());
double thresholdCoef = blackWhiteOptions.getSauvolaCoef();

binarized = binarizeEdgeDiv(image, windowsSize, 0.0, thresholdCoef, thresholdDelta);
break;
}
case EDGEDIV: {
double thresholdDelta = blackWhiteOptions.thresholdAdjustment();
QSize windowsSize = QSize(blackWhiteOptions.getWindowSize(), blackWhiteOptions.getWindowSize());
double thresholdCoef = blackWhiteOptions.getSauvolaCoef();

binarized = binarizeEdgeDiv(image, windowsSize, thresholdCoef, thresholdCoef, thresholdDelta);
break;
}
}
Expand Down
13 changes: 12 additions & 1 deletion src/core/filters/output/SauvolaBinarizationOptionsWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ void SauvolaBinarizationOptionsWidget::updateUi(const PageId& pageId) {
updateView();
}

void SauvolaBinarizationOptionsWidget::sauvolaDeltaChanged(double value) {
BlackWhiteOptions opt(m_colorParams.blackWhiteOptions());
opt.setThresholdAdjustment(value);
m_colorParams.setBlackWhiteOptions(opt);
m_settings->setColorParams(m_pageId, m_colorParams);

m_delayedStateChanger.start(750);
}

void SauvolaBinarizationOptionsWidget::windowSizeChanged(int value) {
BlackWhiteOptions opt(m_colorParams.blackWhiteOptions());
opt.setWindowSize(value);
Expand All @@ -49,6 +58,7 @@ void SauvolaBinarizationOptionsWidget::sauvolaCoefChanged(double value) {

void SauvolaBinarizationOptionsWidget::updateView() {
BlackWhiteOptions blackWhiteOptions = m_colorParams.blackWhiteOptions();
sauvolaDelta->setValue(blackWhiteOptions.thresholdAdjustment());
windowSize->setValue(blackWhiteOptions.getWindowSize());
sauvolaCoef->setValue(blackWhiteOptions.getSauvolaCoef());
}
Expand All @@ -60,10 +70,11 @@ void SauvolaBinarizationOptionsWidget::sendStateChanged() {
#define CONNECT(...) m_connectionManager.addConnection(connect(__VA_ARGS__))

void SauvolaBinarizationOptionsWidget::setupUiConnections() {
CONNECT(sauvolaDelta, SIGNAL(valueChanged(double)), this, SLOT(sauvolaDeltaChanged(double)));
CONNECT(windowSize, SIGNAL(valueChanged(int)), this, SLOT(windowSizeChanged(int)));
CONNECT(sauvolaCoef, SIGNAL(valueChanged(double)), this, SLOT(sauvolaCoefChanged(double)));
CONNECT(&m_delayedStateChanger, SIGNAL(timeout()), this, SLOT(sendStateChanged()));
}

#undef CONNECT
} // namespace output
} // namespace output
2 changes: 2 additions & 0 deletions src/core/filters/output/SauvolaBinarizationOptionsWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class SauvolaBinarizationOptionsWidget : public BinarizationOptionsWidget,

private slots:

void sauvolaDeltaChanged(double value);

void windowSizeChanged(int value);

void sauvolaCoefChanged(double value);
Expand Down
47 changes: 35 additions & 12 deletions src/core/filters/output/SauvolaBinarizationOptionsWidget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -50,27 +50,57 @@
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QLabel" name="sauvolaCoefLabel">
<item row="0" column="0">
<widget class="QLabel" name="sauvolaDeltaLabel">
<property name="text">
<string>Coef:</string>
<string>Delta:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="sauvolaDelta">
<property name="toolTip">
<string>Default value is 0.</string>
</property>
<property name="minimum">
<double>-100.0</double>
</property>
<property name="maximum">
<double>100.0</double>
</property>
<property name="singleStep">
<double>1.0</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="windowSizeLabel">
<property name="text">
<string>Window size:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="windowSize">
<property name="toolTip">
<string>The dimensions of a pixel neighborhood to consider.</string>
</property>
<property name="minimum">
<number>5</number>
<number>3</number>
</property>
<property name="maximum">
<number>9999</number>
</property>
</widget>
</item>
<item row="1" column="1">
<item row="2" column="0">
<widget class="QLabel" name="sauvolaCoefLabel">
<property name="text">
<string>Coef:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="sauvolaCoef">
<property name="toolTip">
<string>Default value is 0.34.</string>
Expand All @@ -86,13 +116,6 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="windowSizeLabel">
<property name="text">
<string>Window size:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
Expand Down
13 changes: 12 additions & 1 deletion src/core/filters/output/WolfBinarizationOptionsWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ void WolfBinarizationOptionsWidget::updateUi(const PageId& pageId) {
updateView();
}

void WolfBinarizationOptionsWidget::wolfDeltaChanged(double value) {
BlackWhiteOptions opt(m_colorParams.blackWhiteOptions());
opt.setThresholdAdjustment(value);
m_colorParams.setBlackWhiteOptions(opt);
m_settings->setColorParams(m_pageId, m_colorParams);

m_delayedStateChanger.start(750);
}

void WolfBinarizationOptionsWidget::windowSizeChanged(int value) {
BlackWhiteOptions opt(m_colorParams.blackWhiteOptions());
opt.setWindowSize(value);
Expand Down Expand Up @@ -66,6 +75,7 @@ void WolfBinarizationOptionsWidget::wolfCoefChanged(double value) {

void WolfBinarizationOptionsWidget::updateView() {
BlackWhiteOptions blackWhiteOptions = m_colorParams.blackWhiteOptions();
wolfDelta->setValue(blackWhiteOptions.thresholdAdjustment());
windowSize->setValue(blackWhiteOptions.getWindowSize());
lowerBound->setValue(blackWhiteOptions.getWolfLowerBound());
upperBound->setValue(blackWhiteOptions.getWolfUpperBound());
Expand All @@ -79,6 +89,7 @@ void WolfBinarizationOptionsWidget::sendStateChanged() {
#define CONNECT(...) m_connectionManager.addConnection(connect(__VA_ARGS__))

void WolfBinarizationOptionsWidget::setupUiConnections() {
CONNECT(wolfDelta, SIGNAL(valueChanged(double)), this, SLOT(wolfDeltaChanged(double)));
CONNECT(windowSize, SIGNAL(valueChanged(int)), this, SLOT(windowSizeChanged(int)));
CONNECT(lowerBound, SIGNAL(valueChanged(int)), this, SLOT(lowerBoundChanged(int)));
CONNECT(upperBound, SIGNAL(valueChanged(int)), this, SLOT(upperBoundChanged(int)));
Expand All @@ -87,4 +98,4 @@ void WolfBinarizationOptionsWidget::setupUiConnections() {
}

#undef CONNECT
} // namespace output
} // namespace output
2 changes: 2 additions & 0 deletions src/core/filters/output/WolfBinarizationOptionsWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class WolfBinarizationOptionsWidget : public BinarizationOptionsWidget, private

private slots:

void wolfDeltaChanged(double value);

void windowSizeChanged(int value);

void wolfCoefChanged(double value);
Expand Down
Loading

0 comments on commit b0788fc

Please sign in to comment.