7 #include "DocumentModelGridRemoval.h"
8 #include "EngaugeAssert.h"
9 #include "GridHealer.h"
16 const BoundaryGroup BOUNDARY_GROUP_FIRST = 100;
20 m_boundaryGroupNext (BOUNDARY_GROUP_FIRST),
21 m_modelGridRemoval (modelGridRemoval)
23 LOG4CPP_INFO_S ((*mainCat)) <<
"GridHealer::GridHealer";
26 ENGAUGE_ASSERT (NUM_PIXEL_STATES < BOUNDARY_GROUP_FIRST);
28 m_pixels.resize (imageBefore.height());
29 for (
int row = 0; row < imageBefore.height(); row++) {
30 m_pixels [row].resize (imageBefore.width());
32 for (
int col = 0; col < imageBefore.width(); col++) {
34 QRgb rgb = imageBefore.pixel(col, row);
35 if (qGray (rgb) > 128) {
36 m_pixels [row] [col] = PIXEL_STATE_BACKGROUND;
38 m_pixels [row] [col] = PIXEL_STATE_FOREGROUND;
44 void GridHealer::connectCloseGroups(QImage &imageToHeal)
46 LOG4CPP_INFO_S ((*mainCat)) <<
"GridHealer::connectCloseGroups";
49 for (
int iFrom = 0; iFrom < m_groupNumberToCentroid.count() - 1; iFrom++) {
51 BoundaryGroup groupFrom = m_groupNumberToCentroid.keys().at (iFrom);
53 ENGAUGE_ASSERT (m_groupNumberToCentroid.contains (groupFrom));
54 ENGAUGE_ASSERT (m_groupNumberToPixel.contains (groupFrom));
56 QPointF posCentroidFrom = m_groupNumberToCentroid [groupFrom];
57 QPointF pixelPointFrom = m_groupNumberToPixel [groupFrom];
59 for (
int iTo = iFrom + 1; iTo < m_groupNumberToCentroid.count(); iTo++) {
61 BoundaryGroup groupTo = m_groupNumberToCentroid.keys().at (iTo);
63 ENGAUGE_ASSERT (m_groupNumberToCentroid.contains (groupTo));
64 ENGAUGE_ASSERT (m_groupNumberToPixel.contains (groupTo));
66 QPointF posCentroidTo = m_groupNumberToCentroid [groupTo];
67 QPointF pixelPointTo = m_groupNumberToPixel [groupTo];
69 QPointF separation = posCentroidFrom - posCentroidTo;
70 double separationMagnitude = qSqrt (separation.x() * separation.x() + separation.y() * separation.y());
72 if (separationMagnitude < m_modelGridRemoval.
closeDistance()) {
75 int count = 1 + qMax (qAbs (pixelPointFrom.x() - pixelPointTo.x()),
76 qAbs (pixelPointFrom.y() - pixelPointTo.y()));
79 for (
int index = 0; index < count; index++) {
82 double s = (double) index / (
double) (count - 1);
83 int xCol = (int) (0.5 + (1.0 - s) * pixelPointFrom.y() + s * pixelPointTo.y());
84 int yRow = (int) (0.5 + (1.0 - s) * pixelPointFrom.x() + s * pixelPointTo.x());
85 m_pixels [yRow] [xCol] = PIXEL_STATE_HEALED;
88 imageToHeal.setPixel (QPoint (xCol,
101 m_pixels [yRow] [xCol] = PIXEL_STATE_REMOVED;
103 for (
int rowOffset = -1; rowOffset <= 1; rowOffset++) {
104 int rowSearch = yRow + rowOffset;
105 if (0 <= rowSearch && rowSearch < m_pixels.count()) {
107 for (
int colOffset = -1; colOffset <= 1; colOffset++) {
108 int colSearch = xCol + colOffset;
109 if (0 <= colSearch && colSearch < m_pixels[0].count()) {
111 if (m_pixels [rowSearch] [colSearch] == PIXEL_STATE_FOREGROUND) {
113 m_pixels [rowSearch] [colSearch] = PIXEL_STATE_ADJACENT;
122 void GridHealer::groupContiguousAdjacentPixels()
124 LOG4CPP_INFO_S ((*mainCat)) <<
"GridHealer::groupContiguousAdjacentPixels";
126 for (
int row = 0; row < m_pixels.count(); row++) {
127 for (
int col = 0; col < m_pixels [0].count(); col++) {
129 if (m_pixels [row] [col] == PIXEL_STATE_ADJACENT) {
133 int centroidCount = 0;
134 double rowCentroidSum = 0, colCentroidSum = 0;
136 recursiveSearchForAdjacentPixels (m_boundaryGroupNext,
143 if (centroidCount > 0) {
145 m_groupNumberToCentroid [m_boundaryGroupNext] = QPointF (rowCentroidSum / centroidCount,
146 colCentroidSum / centroidCount);
147 m_groupNumberToPixel [m_boundaryGroupNext] = QPointF (row,
150 ++m_boundaryGroupNext;
159 LOG4CPP_INFO_S ((*mainCat)) <<
"GridHealer::heal";
161 groupContiguousAdjacentPixels ();
162 connectCloseGroups (imageToHeal);
165 void GridHealer::recursiveSearchForAdjacentPixels (
int boundaryGroup,
169 double &rowCentroidSum,
170 double &colCentroidSum)
172 ENGAUGE_ASSERT (m_pixels [row] [col] == PIXEL_STATE_ADJACENT);
176 rowCentroidSum += row;
177 colCentroidSum += col;
179 m_pixels [row] [col] = boundaryGroup;
181 for (
int rowOffset = -1; rowOffset <= 1; rowOffset++) {
182 int rowNeighbor = row + rowOffset;
183 if (0 <= rowNeighbor && rowNeighbor < m_pixels.count()) {
185 for (
int colOffset = -1; colOffset <= 1; colOffset++) {
186 int colNeighbor = col + colOffset;
187 if (0 <= colNeighbor && colNeighbor < m_pixels[0].count()) {
189 if (m_pixels [rowNeighbor] [colNeighbor] == PIXEL_STATE_ADJACENT) {
191 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.