1 #include "ColorFilter.h"
2 #include "Correlation.h"
3 #include "DocumentModelCoords.h"
4 #include "EngaugeAssert.h"
5 #include "GridClassifier.h"
11 #include "QtToString.h"
12 #include "Transformation.h"
14 int GridClassifier::NUM_PIXELS_PER_HISTOGRAM_BINS = 1;
15 double GridClassifier::PEAK_HALF_WIDTH = 4;
16 int GridClassifier::MIN_STEP_PIXELS = 4 * GridClassifier::PEAK_HALF_WIDTH;
24 int GridClassifier::binFromCoordinate (
double coord,
26 double coordMax)
const
28 ENGAUGE_ASSERT (coordMin < coordMax);
29 ENGAUGE_ASSERT (coordMin <= coord);
30 ENGAUGE_ASSERT (coord <= coordMax);
32 int bin = 0.5 + (m_numHistogramBins - 1.0) * (coord - coordMin) / (coordMax - coordMin);
38 const QPixmap &originalPixmap,
47 LOG4CPP_INFO_S ((*mainCat)) <<
"GridClassifier::classify";
49 QImage image = originalPixmap.toImage ();
51 m_numHistogramBins = image.width() / NUM_PIXELS_PER_HISTOGRAM_BINS;
53 double xMin, xMax, yMin, yMax;
54 double binStartX, binStepX, binStartY, binStepY;
56 m_binsX =
new double [m_numHistogramBins];
57 m_binsY =
new double [m_numHistogramBins];
59 computeGraphCoordinateLimits (image,
65 initializeHistogramBins ();
66 populateHistogramBins (image,
72 searchStartStepSpace (isGnuplot,
85 searchCountSpace (m_binsX,
89 searchCountSpace (m_binsY,
98 void GridClassifier::computeGraphCoordinateLimits (
const QImage &image,
105 LOG4CPP_INFO_S ((*mainCat)) <<
"GridClassifier::computeGraphCoordinateLimits";
110 QPointF posGraphTL, posGraphTR, posGraphBL, posGraphBR;
120 xMin = qMin (qMin (qMin (posGraphTL.x(), posGraphTR.x()), posGraphBL.x()), posGraphBR.x());
121 xMax = qMax (qMax (qMax (posGraphTL.x(), posGraphTR.x()), posGraphBL.x()), posGraphBR.x());
122 yMin = qMin (qMin (qMin (posGraphTL.y(), posGraphTR.y()), posGraphBL.y()), posGraphBR.y());
123 yMax = qMax (qMax (qMax (posGraphTL.y(), posGraphTR.y()), posGraphBL.y()), posGraphBR.y());
131 yMax = qMax (qMax (qMax (posGraphTL.y(), posGraphTR.y()), posGraphBL.y()), posGraphBR.y());
135 ENGAUGE_ASSERT (xMin < xMax);
136 ENGAUGE_ASSERT (yMin < yMax);
139 double GridClassifier::coordinateFromBin (
int bin,
141 double coordMax)
const
143 ENGAUGE_ASSERT (bin < m_numHistogramBins);
144 ENGAUGE_ASSERT (coordMin < coordMax);
146 return coordMin + (coordMax - coordMin) * (
double) bin / ((
double) m_numHistogramBins - 1.0);
149 void GridClassifier::dumpGnuplotCoordinate (const QString &filename,
151 double coordinateMin,
152 double coordinateMax,
156 cout <<
"Writing gnuplot file: " << filename.toLatin1().data() <<
"\n";
158 QFile fileDump (filename);
159 fileDump.open (QIODevice::WriteOnly | QIODevice::Text);
160 QTextStream strDump (&fileDump);
163 const QString DELIMITER (
"\t");
167 for (bin = 0; bin < m_numHistogramBins; bin++) {
168 if (bins [bin] > binCountMax) {
169 binCountMax = qMax ((
double) binCountMax,
175 double *picketFence =
new double [m_numHistogramBins];
176 loadPicketFence (picketFence,
184 << DELIMITER <<
"coordinate"
185 << DELIMITER <<
"binCount"
186 << DELIMITER <<
"startStep"
187 << DELIMITER <<
"picketFence" <<
"\n";
190 for (bin = 0; bin < m_numHistogramBins; bin++) {
192 double coordinate = coordinateFromBin (bin,
195 double startStepValue (((bin - binStart) % binStep == 0) ? 1 : 0);
197 << DELIMITER << coordinate
198 << DELIMITER << bins [bin]
199 << DELIMITER << binCountMax * startStepValue
200 << DELIMITER << binCountMax * picketFence [bin] <<
"\n";
206 void GridClassifier::initializeHistogramBins ()
208 LOG4CPP_INFO_S ((*mainCat)) <<
"GridClassifier::initializeHistogramBins";
210 for (
int bin = 0; bin < m_numHistogramBins; bin++) {
216 void GridClassifier::loadPicketFence (
double picketFence [],
222 const double PEAK_HEIGHT = 1.0;
226 ENGAUGE_ASSERT (binStart >= PEAK_HALF_WIDTH);
228 count = 1 + (m_numHistogramBins - binStart - PEAK_HALF_WIDTH) / binStep;
232 int binStartMinusHalfWidth = binStart - PEAK_HALF_WIDTH;
233 int binStopPlusHalfWidth = (binStart + (count - 1) * binStep) + PEAK_HALF_WIDTH;
237 double areaUnnormalized = count * PEAK_HEIGHT * PEAK_HALF_WIDTH;
238 double normalizationOffset = -1.0 * areaUnnormalized / m_numHistogramBins;
240 for (
int bin = 0; bin < m_numHistogramBins; bin++) {
244 picketFence [bin] = normalizationOffset;
246 if ((binStartMinusHalfWidth <= bin) &&
247 (bin <= binStopPlusHalfWidth)) {
250 int ordinalClosestPeak = (int) ((bin - binStart + binStep / 2) / binStep);
251 int binClosestPeak = binStart + ordinalClosestPeak * binStep;
254 int distanceToClosestPeak = qAbs (bin - binClosestPeak);
256 if (distanceToClosestPeak < PEAK_HALF_WIDTH) {
259 picketFence [bin] = 1.0 - (double) distanceToClosestPeak / PEAK_HALF_WIDTH + normalizationOffset;
266 void GridClassifier::populateHistogramBins (
const QImage &image,
273 LOG4CPP_INFO_S ((*mainCat)) <<
"GridClassifier::populateHistogramBins";
278 for (
int x = 0; x < image.width(); x++) {
279 for (
int y = 0; y < image.height(); y++) {
281 QColor pixel = image.pixel (x, y);
294 while (posGraph.x() < xMin) {
297 while (posGraph.x() > xMax) {
302 int binX = binFromCoordinate (posGraph.x(), xMin, xMax);
303 int binY = binFromCoordinate (posGraph.y(), yMin, yMax);
305 ENGAUGE_ASSERT (0 <= binX);
306 ENGAUGE_ASSERT (0 <= binY);
307 ENGAUGE_ASSERT (binX < m_numHistogramBins);
308 ENGAUGE_ASSERT (binY < m_numHistogramBins);
311 binX = qMin (binX, m_numHistogramBins - 1);
312 binY = qMin (binY, m_numHistogramBins - 1);
321 void GridClassifier::searchCountSpace (
double bins [],
326 LOG4CPP_INFO_S ((*mainCat)) <<
"GridClassifier::searchCountSpace"
327 <<
" start=" << binStart
328 <<
" step=" << binStep;
332 double picketFence [m_numHistogramBins];
333 double corr, corrMax;
335 int countStop = 1 + (m_numHistogramBins - binStart) / binStep;
336 for (
int count = 2; count <= countStop; count++) {
338 loadPicketFence (picketFence,
344 correlation.correlateWithoutShift (m_numHistogramBins,
348 if (isFirst || (corr > corrMax)) {
357 void GridClassifier::searchStartStepSpace (
bool isGnuplot,
366 double &binStartXMax,
368 double &binStartYMax,
371 LOG4CPP_INFO_S ((*mainCat)) <<
"GridClassifier::searchStartStepSpace";
375 double picketFence [m_numHistogramBins];
376 int binStartX, binStartY;
377 double corrX, corrY, corrXMax, corrYMax;
382 const int BIN_START_UNSHIFTED = PEAK_HALF_WIDTH;
385 for (
int binStep = MIN_STEP_PIXELS; binStep < m_numHistogramBins / 4; binStep++) {
387 loadPicketFence (picketFence,
393 correlation.correlateWithShift (m_numHistogramBins,
398 correlation.correlateWithShift (m_numHistogramBins,
403 if (isFirst || (corrX > corrXMax)) {
404 binStartXMax = binStartX;
405 binStepXMax = binStep;
410 QString filenameGnuplotX = QString (
"gridclassifier_x_corr%1_startMax%2_stepMax%3.gnuplot")
411 .arg (corrX, 8,
'f', 3,
'0')
414 dumpGnuplotCoordinate(filenameGnuplotX,
423 if (isFirst || (corrY > corrYMax)) {
424 binStartYMax = binStartY;
425 binStepYMax = binStep;
430 QString filenameGnuplotY = QString (
"gridclassifier_y_corr%1_startMax%2_stepMax%3.gnuplot")
431 .arg (corrY, 8,
'f', 3,
'0')
434 dumpGnuplotCoordinate(filenameGnuplotY,
447 startX = coordinateFromBin (binStartXMax,
450 startY = coordinateFromBin (binStartYMax,
453 double nextX = coordinateFromBin (binStartXMax + binStepXMax,
456 double nextY = coordinateFromBin (binStartYMax + binStepYMax,
460 stepX = nextX - startX;
461 stepY = nextY - startY;
double originRadius() const
Get method for origin radius in polar mode.
Fast cross correlation between two functions.
Class for filtering image to remove unimportant information.
double thetaPeriod() const
Return the period of the theta value for polar coordinates, consistent with CoordThetaUnits.
QRgb marginColor(const QImage *image) const
Identify the margin color of the image, which is defined as the most common color in the four margins...
GridClassifier()
Single constructor.
CoordsType coordsType() const
Get method for coordinates type.
bool colorCompare(QRgb rgb1, QRgb rgb2) const
See if the two color values are close enough to be considered to be the same.
Classify the grid pattern in an original image.
void classify(bool isGnuplot, const QPixmap &originalPixmap, const Transformation &transformation, int &countX, double &startX, double &stepX, int &countY, double &startY, double &stepY)
Classify the specified image, and return the most probably x and y grid settings. ...