Improve image preprocessing
This commit is contained in:
parent
5f53aaec23
commit
cb203b912e
@ -90,34 +90,118 @@ static double getScale(Pix *source)
|
|||||||
return scale;
|
return scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Smart pointer for Pix
|
||||||
|
class PixGuard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit PixGuard(Pix *pix = nullptr)
|
||||||
|
: pix_(pix)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~PixGuard()
|
||||||
|
{
|
||||||
|
if (pix_)
|
||||||
|
pixDestroy(&pix_);
|
||||||
|
}
|
||||||
|
void operator=(Pix *pix)
|
||||||
|
{
|
||||||
|
if (!pix)
|
||||||
|
return;
|
||||||
|
if (pix_)
|
||||||
|
pixDestroy(&pix_);
|
||||||
|
pix_ = pix;
|
||||||
|
}
|
||||||
|
operator Pix *() { return pix_; }
|
||||||
|
Pix *operator->() { return pix_; }
|
||||||
|
Pix *&get() { return pix_; }
|
||||||
|
Pix *take()
|
||||||
|
{
|
||||||
|
auto ret = pix_;
|
||||||
|
pix_ = nullptr;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
void trace(const QString &name) const
|
||||||
|
{
|
||||||
|
LTRACE() << qPrintable(name) << pix_;
|
||||||
|
#if 0
|
||||||
|
if (!pix_)
|
||||||
|
return;
|
||||||
|
auto fileName = name + ".png";
|
||||||
|
fileName.replace(' ', "_");
|
||||||
|
convertImage(*pix_).save(fileName);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Pix *pix_;
|
||||||
|
|
||||||
|
Q_DISABLE_COPY(PixGuard);
|
||||||
|
};
|
||||||
|
|
||||||
static Pix *prepareImage(const QImage &image)
|
static Pix *prepareImage(const QImage &image)
|
||||||
{
|
{
|
||||||
auto pix = convertImage(image);
|
auto pix = PixGuard(convertImage(image));
|
||||||
SOFT_ASSERT(pix, return nullptr);
|
SOFT_ASSERT(pix, return nullptr);
|
||||||
LTRACE() << "Converted Pix" << pix;
|
pix.trace("Pix 1 Converted");
|
||||||
|
|
||||||
auto gray = pixConvertRGBToGray(pix, 0.0, 0.0, 0.0);
|
{
|
||||||
LTRACE() << "Created gray Pix" << gray;
|
pix = pixConvertRGBToGray(pix, 0.0, 0.0, 0.0);
|
||||||
SOFT_ASSERT(gray, return nullptr);
|
pix.trace("Pix 2 Gray");
|
||||||
pixDestroy(&pix);
|
|
||||||
LTRACE() << "Removed converted Pix";
|
|
||||||
|
|
||||||
auto scaleSource = gray;
|
|
||||||
auto scaled = scaleSource;
|
|
||||||
|
|
||||||
if (const auto scale = getScale(scaleSource); scale > 1.0) {
|
|
||||||
scaled = pixScale(scaleSource, scale, scale);
|
|
||||||
LTRACE() << "Scaled Pix for OCR" << LARG(scale) << LARG(scaled);
|
|
||||||
if (!scaled)
|
|
||||||
scaled = scaleSource;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scaled != scaleSource) {
|
if (const auto scale = getScale(pix); scale > 1.0) {
|
||||||
pixDestroy(&scaleSource);
|
pix = pixScaleGrayLI(pix, scale, scale);
|
||||||
LTRACE() << "Removed unscaled Pix";
|
pix.trace("Pix 3 Scaled");
|
||||||
}
|
}
|
||||||
|
|
||||||
return scaled;
|
l_int32 otsuSx = 5000;
|
||||||
|
l_int32 otsuSy = 5000;
|
||||||
|
l_int32 otsuSmoothx = 0;
|
||||||
|
l_int32 otsuSmoothy = 0;
|
||||||
|
l_float32 otsuScorefract = 0.1f;
|
||||||
|
|
||||||
|
{
|
||||||
|
PixGuard otsu;
|
||||||
|
pixOtsuAdaptiveThreshold(pix, otsuSx, otsuSy, otsuSmoothx, otsuSmoothy,
|
||||||
|
otsuScorefract, nullptr, &otsu.get());
|
||||||
|
pix.trace("Pix 4 Test Color Otsu");
|
||||||
|
|
||||||
|
// Get the average intensity of the border pixels,
|
||||||
|
// with average of 0.0 being completely white and 1.0 being completely black
|
||||||
|
// Top
|
||||||
|
auto avg = pixAverageOnLine(otsu, 0, 0, otsu->w - 1, 0, 1);
|
||||||
|
// Bottom
|
||||||
|
avg += pixAverageOnLine(otsu, 0, otsu->h - 1, otsu->w - 1, otsu->h - 1, 1);
|
||||||
|
// Left
|
||||||
|
avg += pixAverageOnLine(otsu, 0, 0, 0, otsu->h - 1, 1);
|
||||||
|
// Right
|
||||||
|
avg += pixAverageOnLine(otsu, otsu->w - 1, 0, otsu->w - 1, otsu->h - 1, 1);
|
||||||
|
avg /= 4.0f;
|
||||||
|
|
||||||
|
// If background is dark
|
||||||
|
l_float32 threshold = 0.5f;
|
||||||
|
if (avg > threshold) {
|
||||||
|
pix = pixInvert(nullptr, pix);
|
||||||
|
pix.trace("Pix 5 Inverted");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
l_int32 usm_halfwidth = 5;
|
||||||
|
l_float32 usm_fract = 2.5f;
|
||||||
|
pix = pixUnsharpMaskingGray(pix, usm_halfwidth, usm_fract);
|
||||||
|
pix.trace("Pix 6 Unshapred");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
pixOtsuAdaptiveThreshold(pix, otsuSx, otsuSy, otsuSmoothx, otsuSmoothy, 0.0,
|
||||||
|
nullptr, &pix.get());
|
||||||
|
pix.trace("Pix 7 Binarized");
|
||||||
|
}
|
||||||
|
|
||||||
|
pix.trace("Pix 8 Result");
|
||||||
|
|
||||||
|
return pix.take();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cleanupImage(Pix **image)
|
static void cleanupImage(Pix **image)
|
||||||
|
Loading…
Reference in New Issue
Block a user