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;
17 const QString GNUPLOT_DELIMITER (
"\t");
21 int GridClassifier::BIN_START_UNSHIFTED = GridClassifier::PEAK_HALF_WIDTH;
29 int GridClassifier::binFromCoordinate (
double coord,
31 double coordMax)
const
33 ENGAUGE_ASSERT (coordMin < coordMax);
34 ENGAUGE_ASSERT (coordMin <= coord);
35 ENGAUGE_ASSERT (coord <= coordMax);
37 int bin = 0.5 + (m_numHistogramBins - 1.0) * (coord - coordMin) / (coordMax - coordMin);
43 const QPixmap &originalPixmap,
52 LOG4CPP_INFO_S ((*mainCat)) <<
"GridClassifier::classify";
54 QImage image = originalPixmap.toImage ();
56 m_numHistogramBins = image.width() / NUM_PIXELS_PER_HISTOGRAM_BINS;
58 double xMin, xMax, yMin, yMax;
59 double binStartX, binStepX, binStartY, binStepY;
61 m_binsX =
new double [m_numHistogramBins];
62 m_binsY =
new double [m_numHistogramBins];
64 computeGraphCoordinateLimits (image,
70 initializeHistogramBins ();
71 populateHistogramBins (image,
77 searchStartStepSpace (isGnuplot,
86 searchStartStepSpace (isGnuplot,
95 searchCountSpace (m_binsX,
99 searchCountSpace (m_binsY,
108 void GridClassifier::computeGraphCoordinateLimits (
const QImage &image,
115 LOG4CPP_INFO_S ((*mainCat)) <<
"GridClassifier::computeGraphCoordinateLimits";
120 QPointF posGraphTL, posGraphTR, posGraphBL, posGraphBR;
130 xMin = qMin (qMin (qMin (posGraphTL.x(), posGraphTR.x()), posGraphBL.x()), posGraphBR.x());
131 xMax = qMax (qMax (qMax (posGraphTL.x(), posGraphTR.x()), posGraphBL.x()), posGraphBR.x());
132 yMin = qMin (qMin (qMin (posGraphTL.y(), posGraphTR.y()), posGraphBL.y()), posGraphBR.y());
133 yMax = qMax (qMax (qMax (posGraphTL.y(), posGraphTR.y()), posGraphBL.y()), posGraphBR.y());
141 yMax = qMax (qMax (qMax (posGraphTL.y(), posGraphTR.y()), posGraphBL.y()), posGraphBR.y());
145 ENGAUGE_ASSERT (xMin < xMax);
146 ENGAUGE_ASSERT (yMin < yMax);
149 double GridClassifier::coordinateFromBin (
int bin,
151 double coordMax)
const
153 ENGAUGE_ASSERT (bin < m_numHistogramBins);
154 ENGAUGE_ASSERT (coordMin < coordMax);
156 return coordMin + (coordMax - coordMin) * (
double) bin / ((
double) m_numHistogramBins - 1.0);
162 for (
int bin = 0; bin < m_numHistogramBins; bin++) {
163 to [bin] = from [bin];
167 void GridClassifier::dumpGnuplotCoordinate (
const QString &coordinateLabel,
170 double coordinateMin,
171 double coordinateMax,
175 QString filename = QString (
"gridclassifier_%1_corr%2_startMax%3_stepMax%4.gnuplot")
176 .arg (coordinateLabel)
177 .arg (corr, 8,
'f', 3,
'0')
181 cout <<
"Writing gnuplot file: " << filename.toLatin1().data() <<
"\n";
183 QFile fileDump (filename);
184 fileDump.open (QIODevice::WriteOnly | QIODevice::Text);
185 QTextStream strDump (&fileDump);
191 for (bin = 0; bin < m_numHistogramBins; bin++) {
192 if (bins [bin] > binCountMax) {
193 binCountMax = qMax ((
double) binCountMax,
199 double *picketFence =
new double [m_numHistogramBins];
200 loadPicketFence (picketFence,
208 << GNUPLOT_DELIMITER <<
"coordinate"
209 << GNUPLOT_DELIMITER <<
"binCount"
210 << GNUPLOT_DELIMITER <<
"startStep"
211 << GNUPLOT_DELIMITER <<
"picketFence" <<
"\n";
214 for (bin = 0; bin < m_numHistogramBins; bin++) {
216 double coordinate = coordinateFromBin (bin,
219 double startStepValue (((bin - binStart) % binStep == 0) ? 1 : 0);
221 << GNUPLOT_DELIMITER << coordinate
222 << GNUPLOT_DELIMITER << bins [bin]
223 << GNUPLOT_DELIMITER << binCountMax * startStepValue
224 << GNUPLOT_DELIMITER << binCountMax * picketFence [bin] <<
"\n";
230 void GridClassifier::dumpGnuplotCorrelations (
const QString &coordinateLabel,
233 const double signalA [],
234 const double signalB [],
235 const double correlations [])
237 QString filename = QString (
"gridclassifier_%1_correlations.gnuplot")
238 .arg (coordinateLabel);
240 cout <<
"Writing gnuplot file: " << filename.toLatin1().data() <<
"\n";
242 QFile fileDump (filename);
243 fileDump.open (QIODevice::WriteOnly | QIODevice::Text);
244 QTextStream strDump (&fileDump);
249 double signalAMax = 1, signalBMax = 1, correlationsMax = 1;
250 for (bin = 0; bin < m_numHistogramBins; bin++) {
251 if (bin == 0 || signalA [bin] > signalAMax) {
252 signalAMax = signalA [bin];
254 if (bin == 0 || signalB [bin] > signalBMax) {
255 signalBMax = signalB [bin];
257 if (bin == 0 || correlations [bin] > correlationsMax) {
258 correlationsMax = correlations [bin];
263 for (
int bin = 0; bin < m_numHistogramBins; bin++) {
265 strDump << coordinateFromBin (bin,
268 << GNUPLOT_DELIMITER << signalA [bin] / signalAMax
269 << GNUPLOT_DELIMITER << signalB [bin] / signalBMax
270 << GNUPLOT_DELIMITER << correlations [bin] / correlationsMax <<
"\n";
274 void GridClassifier::initializeHistogramBins ()
276 LOG4CPP_INFO_S ((*mainCat)) <<
"GridClassifier::initializeHistogramBins";
278 for (
int bin = 0; bin < m_numHistogramBins; bin++) {
284 void GridClassifier::loadPicketFence (
double picketFence [],
290 const double PEAK_HEIGHT = 1.0;
294 ENGAUGE_ASSERT (binStart >= PEAK_HALF_WIDTH);
296 count = 1 + (m_numHistogramBins - binStart - PEAK_HALF_WIDTH) / binStep;
300 int binStartMinusHalfWidth = binStart - PEAK_HALF_WIDTH;
301 int binStopPlusHalfWidth = (binStart + (count - 1) * binStep) + PEAK_HALF_WIDTH;
305 double areaUnnormalized = count * PEAK_HEIGHT * PEAK_HALF_WIDTH;
306 double normalizationOffset = -1.0 * areaUnnormalized / m_numHistogramBins;
308 for (
int bin = 0; bin < m_numHistogramBins; bin++) {
312 picketFence [bin] = normalizationOffset;
314 if ((binStartMinusHalfWidth <= bin) &&
315 (bin <= binStopPlusHalfWidth)) {
318 int ordinalClosestPeak = (int) ((bin - binStart + binStep / 2) / binStep);
319 int binClosestPeak = binStart + ordinalClosestPeak * binStep;
322 int distanceToClosestPeak = qAbs (bin - binClosestPeak);
324 if (distanceToClosestPeak < PEAK_HALF_WIDTH) {
327 picketFence [bin] = 1.0 - (double) distanceToClosestPeak / PEAK_HALF_WIDTH + normalizationOffset;
334 void GridClassifier::populateHistogramBins (
const QImage &image,
341 LOG4CPP_INFO_S ((*mainCat)) <<
"GridClassifier::populateHistogramBins";
346 for (
int x = 0; x < image.width(); x++) {
347 for (
int y = 0; y < image.height(); y++) {
349 QColor pixel = image.pixel (x, y);
362 while (posGraph.x() < xMin) {
365 while (posGraph.x() > xMax) {
370 int binX = binFromCoordinate (posGraph.x(), xMin, xMax);
371 int binY = binFromCoordinate (posGraph.y(), yMin, yMax);
373 ENGAUGE_ASSERT (0 <= binX);
374 ENGAUGE_ASSERT (0 <= binY);
375 ENGAUGE_ASSERT (binX < m_numHistogramBins);
376 ENGAUGE_ASSERT (binY < m_numHistogramBins);
379 binX = qMin (binX, m_numHistogramBins - 1);
380 binY = qMin (binY, m_numHistogramBins - 1);
389 void GridClassifier::searchCountSpace (
double bins [],
394 LOG4CPP_INFO_S ((*mainCat)) <<
"GridClassifier::searchCountSpace"
395 <<
" start=" << binStart
396 <<
" step=" << binStep;
400 double *picketFence =
new double [m_numHistogramBins];
401 double corr, corrMax;
403 int countStop = 1 + (m_numHistogramBins - binStart) / binStep;
404 for (
int count = 2; count <= countStop; count++) {
406 loadPicketFence (picketFence,
412 correlation.correlateWithoutShift (m_numHistogramBins,
416 if (isFirst || (corr > corrMax)) {
427 void GridClassifier::searchStartStepSpace (
bool isGnuplot,
429 const QString &coordinateLabel,
437 LOG4CPP_INFO_S ((*mainCat)) <<
"GridClassifier::searchStartStepSpace";
440 double *signalA =
new double [m_numHistogramBins];
441 double *signalB =
new double [m_numHistogramBins];
442 double *correlations =
new double [m_numHistogramBins];
443 double *correlationsMax =
new double [m_numHistogramBins];
447 double *picketFence =
new double [m_numHistogramBins];
449 double corr, corrMax;
456 for (
int binStep = MIN_STEP_PIXELS; binStep < m_numHistogramBins / 4; binStep++) {
458 loadPicketFence (picketFence,
464 correlation.correlateWithShift (m_numHistogramBins,
470 if (isFirst || (corr > corrMax)) {
472 binStartMax = binStart + BIN_START_UNSHIFTED + 1;
473 binStepMax = binStep;
475 copyVectorToVector (bins, signalA);
476 copyVectorToVector (picketFence, signalB);
477 copyVectorToVector (correlations, correlationsMax);
482 dumpGnuplotCoordinate(coordinateLabel,
496 start = coordinateFromBin (binStartMax,
499 double next = coordinateFromBin (binStartMax + binStepMax,
505 dumpGnuplotCorrelations (coordinateLabel,
516 free (correlationsMax);
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. ...