1 #include "DocumentModelGridRemoval.h"
2 #include "EngaugeAssert.h"
3 #include "GridHealer.h"
10 const BoundaryGroup BOUNDARY_GROUP_FIRST = 100;
14 m_boundaryGroupNext (BOUNDARY_GROUP_FIRST),
15 m_modelGridRemoval (modelGridRemoval)
17 LOG4CPP_INFO_S ((*mainCat)) <<
"GridHealer::GridHealer";
20 ENGAUGE_ASSERT (NUM_PIXEL_STATES < BOUNDARY_GROUP_FIRST);
22 m_pixels.resize (imageBefore.height());
23 for (
int row = 0; row < imageBefore.height(); row++) {
24 m_pixels [row].resize (imageBefore.width());
26 for (
int col = 0; col < imageBefore.width(); col++) {
28 QRgb rgb = imageBefore.pixel(col, row);
29 if (qGray (rgb) > 128) {
30 m_pixels [row] [col] = PIXEL_STATE_BACKGROUND;
32 m_pixels [row] [col] = PIXEL_STATE_FOREGROUND;
38 void GridHealer::connectCloseGroups(QImage &imageToHeal)
40 LOG4CPP_INFO_S ((*mainCat)) <<
"GridHealer::connectCloseGroups";
43 for (
int iFrom = 0; iFrom < m_groupNumberToCentroid.count() - 1; iFrom++) {
45 BoundaryGroup groupFrom = m_groupNumberToCentroid.keys().at (iFrom);
47 ENGAUGE_ASSERT (m_groupNumberToCentroid.contains (groupFrom));
48 ENGAUGE_ASSERT (m_groupNumberToPixel.contains (groupFrom));
50 QPointF posCentroidFrom = m_groupNumberToCentroid [groupFrom];
51 QPointF pixelPointFrom = m_groupNumberToPixel [groupFrom];
53 for (
int iTo = iFrom + 1; iTo < m_groupNumberToCentroid.count(); iTo++) {
55 BoundaryGroup groupTo = m_groupNumberToCentroid.keys().at (iTo);
57 ENGAUGE_ASSERT (m_groupNumberToCentroid.contains (groupTo));
58 ENGAUGE_ASSERT (m_groupNumberToPixel.contains (groupTo));
60 QPointF posCentroidTo = m_groupNumberToCentroid [groupTo];
61 QPointF pixelPointTo = m_groupNumberToPixel [groupTo];
63 QPointF separation = posCentroidFrom - posCentroidTo;
64 double separationMagnitude = qSqrt (separation.x() * separation.x() + separation.y() * separation.y());
66 if (separationMagnitude < m_modelGridRemoval.
closeDistance()) {
69 int count = 1 + qMax (qAbs (pixelPointFrom.x() - pixelPointTo.x()),
70 qAbs (pixelPointFrom.y() - pixelPointTo.y()));
72 for (
int index = 0; index < count; index++) {
75 double s = (double) index / (
double) (count - 1);
76 int xCol = (int) (0.5 + (1.0 - s) * pixelPointFrom.y() + s * pixelPointTo.y());
77 int yRow = (int) (0.5 + (1.0 - s) * pixelPointFrom.x() + s * pixelPointTo.x());
78 m_pixels [yRow] [xCol] = PIXEL_STATE_HEALED;
81 imageToHeal.setPixel (QPoint (xCol,
93 m_pixels [yRow] [xCol] = PIXEL_STATE_REMOVED;
95 for (
int rowOffset = -1; rowOffset <= 1; rowOffset++) {
96 int rowSearch = yRow + rowOffset;
97 if (0 <= rowSearch && rowSearch < m_pixels.count()) {
99 for (
int colOffset = -1; colOffset <= 1; colOffset++) {
100 int colSearch = xCol + colOffset;
101 if (0 <= colSearch && colSearch < m_pixels[0].count()) {
103 if (m_pixels [rowSearch] [colSearch] == PIXEL_STATE_FOREGROUND) {
105 m_pixels [rowSearch] [colSearch] = PIXEL_STATE_ADJACENT;
114 void GridHealer::groupContiguousAdjacentPixels()
116 LOG4CPP_INFO_S ((*mainCat)) <<
"GridHealer::groupContiguousAdjacentPixels";
118 for (
int row = 0; row < m_pixels.count(); row++) {
119 for (
int col = 0; col < m_pixels [0].count(); col++) {
121 if (m_pixels [row] [col] == PIXEL_STATE_ADJACENT) {
125 int centroidCount = 0;
126 double rowCentroidSum = 0, colCentroidSum = 0;
128 recursiveSearchForAdjacentPixels (m_boundaryGroupNext,
136 m_groupNumberToCentroid [m_boundaryGroupNext] = QPointF (rowCentroidSum / centroidCount,
137 colCentroidSum / centroidCount);
138 m_groupNumberToPixel [m_boundaryGroupNext] = QPointF (row,
141 ++m_boundaryGroupNext;
149 LOG4CPP_INFO_S ((*mainCat)) <<
"GridHealer::heal";
151 groupContiguousAdjacentPixels ();
152 connectCloseGroups (imageToHeal);
155 void GridHealer::recursiveSearchForAdjacentPixels (
int boundaryGroup,
159 double &rowCentroidSum,
160 double &colCentroidSum)
162 ENGAUGE_ASSERT (m_pixels [row] [col] == PIXEL_STATE_ADJACENT);
166 rowCentroidSum += row;
167 colCentroidSum += col;
169 m_pixels [row] [col] = boundaryGroup;
171 for (
int rowOffset = -1; rowOffset <= 1; rowOffset++) {
172 int rowNeighbor = row + rowOffset;
173 if (0 <= rowNeighbor && rowNeighbor < m_pixels.count()) {
175 for (
int colOffset = -1; colOffset <= 1; colOffset++) {
176 int colNeighbor = col + colOffset;
177 if (0 <= colNeighbor && colNeighbor < m_pixels[0].count()) {
179 if (m_pixels [rowNeighbor] [colNeighbor] == PIXEL_STATE_ADJACENT) {
181 recursiveSearchForAdjacentPixels (boundaryGroup,
double closeDistance() const
Get method for close distance.
void erasePixel(int xCol, int yRow)
Remember that pixel was erased since it belongs to an grid line.
GridHealer(const QImage &imageBefore, const DocumentModelGridRemoval &modelGridRemoval)
Single constructor.
Model for DlgSettingsGridRemoval and CmdSettingsGridRemoval. The settings are unstable until the user...
void heal(QImage &imageToHeal)
Heal the broken curve lines by spanning the gaps across the newly-removed grid lines.