7 #include "ColorFilter.h" 8 #include "Correlation.h" 9 #include "DocumentModelCoords.h" 10 #include "EngaugeAssert.h" 11 #include "GridClassifier.h" 17 #include "QtToString.h" 18 #include "Transformation.h" 20 int GridClassifier::NUM_PIXELS_PER_HISTOGRAM_BINS = 1;
21 double GridClassifier::PEAK_HALF_WIDTH = 4;
22 int GridClassifier::MIN_STEP_PIXELS = 4 * GridClassifier::PEAK_HALF_WIDTH;
23 const QString GNUPLOT_DELIMITER (
"\t");
27 int GridClassifier::BIN_START_UNSHIFTED = GridClassifier::PEAK_HALF_WIDTH;
35 int GridClassifier::binFromCoordinate (
double coord,
37 double coordMax)
const 39 ENGAUGE_ASSERT (coordMin < coordMax);
40 ENGAUGE_ASSERT (coordMin <= coord);
41 ENGAUGE_ASSERT (coord <= coordMax);
43 int bin = 0.5 + (m_numHistogramBins - 1.0) * (coord - coordMin) / (coordMax - coordMin);
49 const QPixmap &originalPixmap,
58 LOG4CPP_INFO_S ((*mainCat)) <<
"GridClassifier::classify";
60 QImage image = originalPixmap.toImage ();
62 m_numHistogramBins = image.width() / NUM_PIXELS_PER_HISTOGRAM_BINS;
64 double xMin, xMax, yMin, yMax;
65 double binStartX, binStepX, binStartY, binStepY;
67 m_binsX =
new double [m_numHistogramBins];
68 m_binsY =
new double [m_numHistogramBins];
70 computeGraphCoordinateLimits (image,
76 initializeHistogramBins ();
77 populateHistogramBins (image,
83 searchStartStepSpace (isGnuplot,
92 searchStartStepSpace (isGnuplot,
101 searchCountSpace (m_binsX,
105 searchCountSpace (m_binsY,
114 void GridClassifier::computeGraphCoordinateLimits (
const QImage &image,
121 LOG4CPP_INFO_S ((*mainCat)) <<
"GridClassifier::computeGraphCoordinateLimits";
126 QPointF posGraphTL, posGraphTR, posGraphBL, posGraphBR;
136 xMin = qMin (qMin (qMin (posGraphTL.x(), posGraphTR.x()), posGraphBL.x()), posGraphBR.x());
137 xMax = qMax (qMax (qMax (posGraphTL.x(), posGraphTR.x()), posGraphBL.x()), posGraphBR.x());
138 yMin = qMin (qMin (qMin (posGraphTL.y(), posGraphTR.y()), posGraphBL.y()), posGraphBR.y());
139 yMax = qMax (qMax (qMax (posGraphTL.y(), posGraphTR.y()), posGraphBL.y()), posGraphBR.y());
147 yMax = qMax (qMax (qMax (posGraphTL.y(), posGraphTR.y()), posGraphBL.y()), posGraphBR.y());
151 ENGAUGE_ASSERT (xMin < xMax);
152 ENGAUGE_ASSERT (yMin < yMax);
155 double GridClassifier::coordinateFromBin (
int bin,
157 double coordMax)
const 159 ENGAUGE_ASSERT (bin < m_numHistogramBins);
160 ENGAUGE_ASSERT (coordMin < coordMax);
162 return coordMin + (coordMax - coordMin) * (
double) bin / ((double) m_numHistogramBins - 1.0);
165 void GridClassifier::copyVectorToVector (
const double from [],
168 for (
int bin = 0; bin < m_numHistogramBins; bin++) {
169 to [bin] = from [bin];
173 void GridClassifier::dumpGnuplotCoordinate (
const QString &coordinateLabel,
176 double coordinateMin,
177 double coordinateMax,
181 QString filename = QString (
"gridclassifier_%1_corr%2_startMax%3_stepMax%4.gnuplot")
182 .arg (coordinateLabel)
183 .arg (corr, 8,
'f', 3,
'0')
187 cout <<
"Writing gnuplot file: " << filename.toLatin1().data() <<
"\n";
189 QFile fileDump (filename);
190 fileDump.open (QIODevice::WriteOnly | QIODevice::Text);
191 QTextStream strDump (&fileDump);
197 for (bin = 0; bin < m_numHistogramBins; bin++) {
198 if (bins [bin] > binCountMax) {
199 binCountMax = qMax ((
double) binCountMax,
205 double *picketFence =
new double [m_numHistogramBins];
206 loadPicketFence (picketFence,
214 << GNUPLOT_DELIMITER <<
"coordinate" 215 << GNUPLOT_DELIMITER <<
"binCount" 216 << GNUPLOT_DELIMITER <<
"startStep" 217 << GNUPLOT_DELIMITER <<
"picketFence" <<
"\n";
220 for (bin = 0; bin < m_numHistogramBins; bin++) {
222 double coordinate = coordinateFromBin (bin,
225 double startStepValue (((bin - binStart) % binStep == 0) ? 1 : 0);
227 << GNUPLOT_DELIMITER << coordinate
228 << GNUPLOT_DELIMITER << bins [bin]
229 << GNUPLOT_DELIMITER << binCountMax * startStepValue
230 << GNUPLOT_DELIMITER << binCountMax * picketFence [bin] <<
"\n";
233 delete [] picketFence;
236 void GridClassifier::dumpGnuplotCorrelations (
const QString &coordinateLabel,
239 const double signalA [],
240 const double signalB [],
241 const double correlations [])
243 QString filename = QString (
"gridclassifier_%1_correlations.gnuplot")
244 .arg (coordinateLabel);
246 cout <<
"Writing gnuplot file: " << filename.toLatin1().data() <<
"\n";
248 QFile fileDump (filename);
249 fileDump.open (QIODevice::WriteOnly | QIODevice::Text);
250 QTextStream strDump (&fileDump);
255 double signalAMax = 1, signalBMax = 1, correlationsMax = 1;
256 for (bin = 0; bin < m_numHistogramBins; bin++) {
257 if (bin == 0 || signalA [bin] > signalAMax) {
258 signalAMax = signalA [bin];
260 if (bin == 0 || signalB [bin] > signalBMax) {
261 signalBMax = signalB [bin];
263 if (bin == 0 || correlations [bin] > correlationsMax) {
264 correlationsMax = correlations [bin];
269 for (
int bin = 0; bin < m_numHistogramBins; bin++) {
271 strDump << coordinateFromBin (bin,
274 << GNUPLOT_DELIMITER << signalA [bin] / signalAMax
275 << GNUPLOT_DELIMITER << signalB [bin] / signalBMax
276 << GNUPLOT_DELIMITER << correlations [bin] / correlationsMax <<
"\n";
280 void GridClassifier::initializeHistogramBins ()
282 LOG4CPP_INFO_S ((*mainCat)) <<
"GridClassifier::initializeHistogramBins";
284 for (
int bin = 0; bin < m_numHistogramBins; bin++) {
290 void GridClassifier::loadPicketFence (
double picketFence [],
296 const double PEAK_HEIGHT = 1.0;
300 ENGAUGE_ASSERT (binStart >= PEAK_HALF_WIDTH);
302 count = 1 + (m_numHistogramBins - binStart - PEAK_HALF_WIDTH) / binStep;
306 int binStartMinusHalfWidth = binStart - PEAK_HALF_WIDTH;
307 int binStopPlusHalfWidth = (binStart + (count - 1) * binStep) + PEAK_HALF_WIDTH;
311 double areaUnnormalized = count * PEAK_HEIGHT * PEAK_HALF_WIDTH;
312 double normalizationOffset = -1.0 * areaUnnormalized / m_numHistogramBins;
314 for (
int bin = 0; bin < m_numHistogramBins; bin++) {
318 picketFence [bin] = normalizationOffset;
320 if ((binStartMinusHalfWidth <= bin) &&
321 (bin <= binStopPlusHalfWidth)) {
324 int ordinalClosestPeak = (int) ((bin - binStart + binStep / 2) / binStep);
325 int binClosestPeak = binStart + ordinalClosestPeak * binStep;
328 int distanceToClosestPeak = qAbs (bin - binClosestPeak);
330 if (distanceToClosestPeak < PEAK_HALF_WIDTH) {
333 picketFence [bin] = 1.0 - (double) distanceToClosestPeak / PEAK_HALF_WIDTH + normalizationOffset;
340 void GridClassifier::populateHistogramBins (
const QImage &image,
347 LOG4CPP_INFO_S ((*mainCat)) <<
"GridClassifier::populateHistogramBins";
352 for (
int x = 0; x < image.width(); x++) {
353 for (
int y = 0; y < image.height(); y++) {
355 QColor pixel = image.pixel (x, y);
368 while (posGraph.x() < xMin) {
371 while (posGraph.x() > xMax) {
376 int binX = binFromCoordinate (posGraph.x(), xMin, xMax);
377 int binY = binFromCoordinate (posGraph.y(), yMin, yMax);
379 ENGAUGE_ASSERT (0 <= binX);
380 ENGAUGE_ASSERT (0 <= binY);
381 ENGAUGE_ASSERT (binX < m_numHistogramBins);
382 ENGAUGE_ASSERT (binY < m_numHistogramBins);
385 binX = qMin (binX, m_numHistogramBins - 1);
386 binY = qMin (binY, m_numHistogramBins - 1);
395 void GridClassifier::searchCountSpace (
double bins [],
400 LOG4CPP_INFO_S ((*mainCat)) <<
"GridClassifier::searchCountSpace" 401 <<
" start=" << binStart
402 <<
" step=" << binStep;
406 double *picketFence =
new double [m_numHistogramBins];
407 double corr, corrMax;
409 int countStop = 1 + (m_numHistogramBins - binStart) / binStep;
410 for (
int count = 2; count <= countStop; count++) {
412 loadPicketFence (picketFence,
422 if (isFirst || (corr > corrMax)) {
430 delete [] picketFence;
433 void GridClassifier::searchStartStepSpace (
bool isGnuplot,
435 const QString &coordinateLabel,
443 LOG4CPP_INFO_S ((*mainCat)) <<
"GridClassifier::searchStartStepSpace";
446 double *signalA =
new double [m_numHistogramBins];
447 double *signalB =
new double [m_numHistogramBins];
448 double *correlations =
new double [m_numHistogramBins];
449 double *correlationsMax =
new double [m_numHistogramBins];
453 double *picketFence =
new double [m_numHistogramBins];
455 double corr = 0, corrMax = 0;
463 binStartMax = BIN_START_UNSHIFTED + 1;
464 binStepMax = qMin (MIN_STEP_PIXELS, m_numHistogramBins / 8);
465 for (
int binStep = qMin (MIN_STEP_PIXELS, m_numHistogramBins / 8); binStep < m_numHistogramBins / 4; binStep++) {
467 loadPicketFence (picketFence,
479 if (isFirst || (corr > corrMax)) {
481 int binStartMaxNext = binStart + BIN_START_UNSHIFTED + 1;
484 if (binStartMaxNext < m_numHistogramBins) {
486 binStartMax = binStartMaxNext;
487 binStepMax = binStep;
489 copyVectorToVector (bins, signalA);
490 copyVectorToVector (picketFence, signalB);
491 copyVectorToVector (correlations, correlationsMax);
496 dumpGnuplotCoordinate(coordinateLabel,
511 start = coordinateFromBin (binStartMax,
514 if (binStartMax + binStepMax < m_numHistogramBins) {
517 double next = coordinateFromBin (binStartMax + binStepMax,
524 double next = coordinateFromBin (m_numHistogramBins - 1,
531 dumpGnuplotCorrelations (coordinateLabel,
541 delete [] correlations;
542 delete [] correlationsMax;
543 delete [] picketFence;
void correlateWithoutShift(int N, const double function1 [], const double function2 [], double &corrMax) const
Return the correlation of the two functions, without any shift.
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...
bool colorCompare(QRgb rgb1, QRgb rgb2) const
See if the two color values are close enough to be considered to be the same.
double thetaPeriod() const
Return the period of the theta value for polar coordinates, consistent with CoordThetaUnits.
Fast cross correlation between two functions.
Class for filtering image to remove unimportant information.
GridClassifier()
Single constructor.
CoordsType coordsType() const
Get method for coordinates type.
double originRadius() const
Get method for origin radius in polar mode.
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. ...
void correlateWithShift(int N, const double function1 [], const double function2 [], int &binStartMax, double &corrMax, double correlations []) const
Return the shift in function1 that best aligns that function with function2.