00001
00002
00003
00004
00005
00006
00007 #include "DocumentModelGridRemoval.h"
00008 #include "EngaugeAssert.h"
00009 #include "GridHealer.h"
00010 #include "Logger.h"
00011 #include <QImage>
00012 #include <qmath.h>
00013 #include <QRgb>
00014
00015
00016 const BoundaryGroup BOUNDARY_GROUP_FIRST = 100;
00017
00018 GridHealer::GridHealer(const QImage &imageBefore,
00019 const DocumentModelGridRemoval &modelGridRemoval) :
00020 m_boundaryGroupNext (BOUNDARY_GROUP_FIRST),
00021 m_modelGridRemoval (modelGridRemoval)
00022 {
00023 LOG4CPP_INFO_S ((*mainCat)) << "GridHealer::GridHealer";
00024
00025
00026 ENGAUGE_ASSERT (NUM_PIXEL_STATES < BOUNDARY_GROUP_FIRST);
00027
00028 m_pixels.resize (imageBefore.height());
00029 for (int row = 0; row < imageBefore.height(); row++) {
00030 m_pixels [row].resize (imageBefore.width());
00031
00032 for (int col = 0; col < imageBefore.width(); col++) {
00033
00034 QRgb rgb = imageBefore.pixel(col, row);
00035 if (qGray (rgb) > 128) {
00036 m_pixels [row] [col] = PIXEL_STATE_BACKGROUND;
00037 } else {
00038 m_pixels [row] [col] = PIXEL_STATE_FOREGROUND;
00039 }
00040 }
00041 }
00042 }
00043
00044 void GridHealer::connectCloseGroups(QImage &imageToHeal)
00045 {
00046 LOG4CPP_INFO_S ((*mainCat)) << "GridHealer::connectCloseGroups";
00047
00048
00049 for (int iFrom = 0; iFrom < m_groupNumberToCentroid.count() - 1; iFrom++) {
00050
00051 BoundaryGroup groupFrom = m_groupNumberToCentroid.keys().at (iFrom);
00052
00053 ENGAUGE_ASSERT (m_groupNumberToCentroid.contains (groupFrom));
00054 ENGAUGE_ASSERT (m_groupNumberToPixel.contains (groupFrom));
00055
00056 QPointF posCentroidFrom = m_groupNumberToCentroid [groupFrom];
00057 QPointF pixelPointFrom = m_groupNumberToPixel [groupFrom];
00058
00059 for (int iTo = iFrom + 1; iTo < m_groupNumberToCentroid.count(); iTo++) {
00060
00061 BoundaryGroup groupTo = m_groupNumberToCentroid.keys().at (iTo);
00062
00063 ENGAUGE_ASSERT (m_groupNumberToCentroid.contains (groupTo));
00064 ENGAUGE_ASSERT (m_groupNumberToPixel.contains (groupTo));
00065
00066 QPointF posCentroidTo = m_groupNumberToCentroid [groupTo];
00067 QPointF pixelPointTo = m_groupNumberToPixel [groupTo];
00068
00069 QPointF separation = posCentroidFrom - posCentroidTo;
00070 double separationMagnitude = qSqrt (separation.x() * separation.x() + separation.y() * separation.y());
00071
00072 if (separationMagnitude < m_modelGridRemoval.closeDistance()) {
00073
00074
00075 int count = 1 + qMax (qAbs (pixelPointFrom.x() - pixelPointTo.x()),
00076 qAbs (pixelPointFrom.y() - pixelPointTo.y()));
00077
00078 for (int index = 0; index < count; index++) {
00079
00080
00081 double s = (double) index / (double) (count - 1);
00082 int xCol = (int) (0.5 + (1.0 - s) * pixelPointFrom.y() + s * pixelPointTo.y());
00083 int yRow = (int) (0.5 + (1.0 - s) * pixelPointFrom.x() + s * pixelPointTo.x());
00084 m_pixels [yRow] [xCol] = PIXEL_STATE_HEALED;
00085
00086
00087 imageToHeal.setPixel (QPoint (xCol,
00088 yRow),
00089 Qt::black);
00090 }
00091 }
00092 }
00093 }
00094 }
00095
00096 void GridHealer::erasePixel (int xCol,
00097 int yRow)
00098 {
00099 m_pixels [yRow] [xCol] = PIXEL_STATE_REMOVED;
00100
00101 for (int rowOffset = -1; rowOffset <= 1; rowOffset++) {
00102 int rowSearch = yRow + rowOffset;
00103 if (0 <= rowSearch && rowSearch < m_pixels.count()) {
00104
00105 for (int colOffset = -1; colOffset <= 1; colOffset++) {
00106 int colSearch = xCol + colOffset;
00107 if (0 <= colSearch && colSearch < m_pixels[0].count()) {
00108
00109 if (m_pixels [rowSearch] [colSearch] == PIXEL_STATE_FOREGROUND) {
00110
00111 m_pixels [rowSearch] [colSearch] = PIXEL_STATE_ADJACENT;
00112
00113 }
00114 }
00115 }
00116 }
00117 }
00118 }
00119
00120 void GridHealer::groupContiguousAdjacentPixels()
00121 {
00122 LOG4CPP_INFO_S ((*mainCat)) << "GridHealer::groupContiguousAdjacentPixels";
00123
00124 for (int row = 0; row < m_pixels.count(); row++) {
00125 for (int col = 0; col < m_pixels [0].count(); col++) {
00126
00127 if (m_pixels [row] [col] == PIXEL_STATE_ADJACENT) {
00128
00129
00130
00131 int centroidCount = 0;
00132 double rowCentroidSum = 0, colCentroidSum = 0;
00133
00134 recursiveSearchForAdjacentPixels (m_boundaryGroupNext,
00135 row,
00136 col,
00137 centroidCount,
00138 rowCentroidSum,
00139 colCentroidSum);
00140
00141
00142 m_groupNumberToCentroid [m_boundaryGroupNext] = QPointF (rowCentroidSum / centroidCount,
00143 colCentroidSum / centroidCount);
00144 m_groupNumberToPixel [m_boundaryGroupNext] = QPointF (row,
00145 col);
00146
00147 ++m_boundaryGroupNext;
00148 }
00149 }
00150 }
00151 }
00152
00153 void GridHealer::heal (QImage &imageToHeal)
00154 {
00155 LOG4CPP_INFO_S ((*mainCat)) << "GridHealer::heal";
00156
00157 groupContiguousAdjacentPixels ();
00158 connectCloseGroups (imageToHeal);
00159 }
00160
00161 void GridHealer::recursiveSearchForAdjacentPixels (int boundaryGroup,
00162 int row,
00163 int col,
00164 int ¢roidCount,
00165 double &rowCentroidSum,
00166 double &colCentroidSum)
00167 {
00168 ENGAUGE_ASSERT (m_pixels [row] [col] == PIXEL_STATE_ADJACENT);
00169
00170
00171 ++centroidCount;
00172 rowCentroidSum += row;
00173 colCentroidSum += col;
00174
00175 m_pixels [row] [col] = boundaryGroup;
00176
00177 for (int rowOffset = -1; rowOffset <= 1; rowOffset++) {
00178 int rowNeighbor = row + rowOffset;
00179 if (0 <= rowNeighbor && rowNeighbor < m_pixels.count()) {
00180
00181 for (int colOffset = -1; colOffset <= 1; colOffset++) {
00182 int colNeighbor = col + colOffset;
00183 if (0 <= colNeighbor && colNeighbor < m_pixels[0].count()) {
00184
00185 if (m_pixels [rowNeighbor] [colNeighbor] == PIXEL_STATE_ADJACENT) {
00186
00187 recursiveSearchForAdjacentPixels (boundaryGroup,
00188 rowNeighbor,
00189 colNeighbor,
00190 centroidCount,
00191 rowCentroidSum,
00192 colCentroidSum);
00193 }
00194 }
00195 }
00196 }
00197 }
00198 }