22int GridClassifier::NUM_PIXELS_PER_HISTOGRAM_BINS = 1;
23double GridClassifier::PEAK_HALF_WIDTH = 4;
24int GridClassifier::MIN_STEP_PIXELS = qFloor (4 * GridClassifier::PEAK_HALF_WIDTH);
29int GridClassifier::BIN_START_UNSHIFTED = qFloor (GridClassifier::PEAK_HALF_WIDTH);
37int GridClassifier::binFromCoordinate (
double coord,
39 double coordMax)
const
45 int bin = qFloor (0.5 + (m_numHistogramBins - 1.0) * (coord - coordMin) / (coordMax - coordMin));
51 const QPixmap &originalPixmap,
62 QImage image = originalPixmap.toImage ();
64 m_numHistogramBins = image.width() / NUM_PIXELS_PER_HISTOGRAM_BINS;
67 double xMin, xMax, yMin, yMax;
68 double binStartX, binStepX, binStartY, binStepY;
70 m_binsX =
new double [unsigned (m_numHistogramBins)];
71 m_binsY =
new double [unsigned (m_numHistogramBins)];
73 computeGraphCoordinateLimits (image,
79 initializeHistogramBins ();
80 populateHistogramBins (image,
86 searchStartStepSpace (isGnuplot,
95 searchStartStepSpace (isGnuplot,
104 searchCountSpace (m_binsX,
108 searchCountSpace (m_binsY,
117void GridClassifier::computeGraphCoordinateLimits (
const QImage &image,
129 QPointF posGraphTL, posGraphTR, posGraphBL, posGraphBR;
139 xMin = qMin (qMin (qMin (posGraphTL.x(), posGraphTR.x()), posGraphBL.x()), posGraphBR.x());
140 xMax = qMax (qMax (qMax (posGraphTL.x(), posGraphTR.x()), posGraphBL.x()), posGraphBR.x());
141 yMin = qMin (qMin (qMin (posGraphTL.y(), posGraphTR.y()), posGraphBL.y()), posGraphBR.y());
142 yMax = qMax (qMax (qMax (posGraphTL.y(), posGraphTR.y()), posGraphBL.y()), posGraphBR.y());
150 yMax = qMax (qMax (qMax (posGraphTL.y(), posGraphTR.y()), posGraphBL.y()), posGraphBR.y());
158double GridClassifier::coordinateFromBin (
int bin,
160 double coordMax)
const
165 return coordMin + (coordMax - coordMin) *
double (bin) / (double (m_numHistogramBins) - 1.0);
168void GridClassifier::copyVectorToVector (
const double from [],
171 for (
int bin = 0; bin < m_numHistogramBins; bin++) {
172 to [bin] = from [bin];
176void GridClassifier::dumpGnuplotCoordinate (
const QString &coordinateLabel,
179 double coordinateMin,
180 double coordinateMax,
184 QString filename = QString (
"gridclassifier_%1_corr%2_startMax%3_stepMax%4.gnuplot")
185 .arg (coordinateLabel)
186 .arg (corr, 8,
'f', 3,
'0')
192 QFile fileDump (filename);
193 fileDump.open (QIODevice::WriteOnly | QIODevice::Text);
194 QTextStream strDump (&fileDump);
200 for (bin = 0; bin < m_numHistogramBins; bin++) {
201 if (bins [bin] > binCountMax) {
202 binCountMax = qMax (
signed (binCountMax),
203 signed (bins [bin]));
208 double *picketFence =
new double [unsigned (m_numHistogramBins)];
209 loadPicketFence (picketFence,
223 for (bin = 0; bin < m_numHistogramBins; bin++) {
225 double coordinate = coordinateFromBin (bin,
228 double startStepValue (((bin - binStart) % binStep == 0) ? 1 : 0);
236 delete [] picketFence;
239void GridClassifier::dumpGnuplotCorrelations (
const QString &coordinateLabel,
242 const double signalA [],
243 const double signalB [],
244 const double correlations [])
246 QString filename = QString (
"gridclassifier_%1_correlations.gnuplot")
247 .arg (coordinateLabel);
251 QFile fileDump (filename);
252 fileDump.open (QIODevice::WriteOnly | QIODevice::Text);
253 QTextStream strDump (&fileDump);
258 double signalAMax = 1, signalBMax = 1, correlationsMax = 1;
259 for (bin = 0; bin < m_numHistogramBins; bin++) {
260 if (bin == 0 || signalA [bin] > signalAMax) {
261 signalAMax = signalA [bin];
263 if (bin == 0 || signalB [bin] > signalBMax) {
264 signalBMax = signalB [bin];
266 if (bin == 0 || correlations [bin] > correlationsMax) {
267 correlationsMax = correlations [bin];
272 if (qAbs (signalAMax) <= 0) {
275 if (qAbs (signalBMax) <= 0) {
280 for (
int bin = 0; bin < m_numHistogramBins; bin++) {
282 strDump << coordinateFromBin (bin,
291void GridClassifier::initializeHistogramBins ()
295 for (
int bin = 0; bin < m_numHistogramBins; bin++) {
301void GridClassifier::loadPicketFence (
double picketFence [],
307 const double PEAK_HEIGHT = 1.0;
314 count = qFloor (1 + (m_numHistogramBins - binStart - PEAK_HALF_WIDTH) / binStep);
318 int binStartMinusHalfWidth = qFloor (binStart - PEAK_HALF_WIDTH);
319 int binStopPlusHalfWidth = qFloor ((binStart + (count - 1) * binStep) + PEAK_HALF_WIDTH);
323 double areaUnnormalized = count * PEAK_HEIGHT * PEAK_HALF_WIDTH;
324 double normalizationOffset = -1.0 * areaUnnormalized / m_numHistogramBins;
326 for (
int bin = 0; bin < m_numHistogramBins; bin++) {
330 picketFence [bin] = normalizationOffset;
332 if ((binStartMinusHalfWidth <= bin) &&
333 (bin <= binStopPlusHalfWidth)) {
336 int ordinalClosestPeak = qFloor ((bin - binStart + binStep / 2) / binStep);
337 int binClosestPeak = binStart + ordinalClosestPeak * binStep;
340 int distanceToClosestPeak = qAbs (bin - binClosestPeak);
342 if (distanceToClosestPeak < PEAK_HALF_WIDTH) {
345 picketFence [bin] = 1.0 - double (distanceToClosestPeak) / PEAK_HALF_WIDTH + normalizationOffset;
352void GridClassifier::populateHistogramBins (
const QImage &image,
364 for (
int x = 0; x < image.width(); x++) {
365 for (
int y = 0; y < image.height(); y++) {
367 QColor pixel = image.pixel (x, y);
380 while (posGraph.x() < xMin) {
383 while (posGraph.x() > xMax) {
388 int binX = binFromCoordinate (posGraph.x(), xMin, xMax);
389 int binY = binFromCoordinate (posGraph.y(), yMin, yMax);
397 binX = qMin (binX, m_numHistogramBins - 1);
398 binY = qMin (binY, m_numHistogramBins - 1);
407void GridClassifier::searchCountSpace (
double bins [],
413 <<
" start=" << binStart
414 <<
" step=" << binStep;
417 Correlation correlation (m_numHistogramBins);
418 double *picketFence =
new double [unsigned (m_numHistogramBins)];
419 double corr, corrMax = 0;
421 int countStop = qFloor (1 + (m_numHistogramBins - binStart) / binStep);
422 for (
int count = 2; count <= countStop; count++) {
424 loadPicketFence (picketFence,
430 correlation.correlateWithoutShift (m_numHistogramBins,
434 if (isFirst || (corr > corrMax)) {
442 delete [] picketFence;
445void GridClassifier::searchStartStepSpace (
bool isGnuplot,
447 const QString &coordinateLabel,
458 double *signalA =
new double [unsigned (m_numHistogramBins)];
459 double *signalB =
new double [unsigned (m_numHistogramBins)];
460 double *correlations =
new double [unsigned (m_numHistogramBins)];
461 double *correlationsMax =
new double [unsigned (m_numHistogramBins)];
464 Correlation correlation (m_numHistogramBins);
465 double *picketFence =
new double [unsigned (m_numHistogramBins)];
467 double corr = 0, corrMax = 0;
475 binStartMax = BIN_START_UNSHIFTED + 1;
476 binStepMax = qMin (MIN_STEP_PIXELS, m_numHistogramBins / 8);
477 for (
int binStep = qMin (MIN_STEP_PIXELS, m_numHistogramBins / 8); binStep < m_numHistogramBins / 4; binStep++) {
479 loadPicketFence (picketFence,
482 qFloor (PEAK_HALF_WIDTH),
485 correlation.correlateWithShift (m_numHistogramBins,
491 if (isFirst || (corr > corrMax)) {
493 int binStartMaxNext = binStart + BIN_START_UNSHIFTED + 1;
496 if (binStartMaxNext < m_numHistogramBins) {
498 binStartMax = binStartMaxNext;
499 binStepMax = binStep;
501 copyVectorToVector (bins, signalA);
502 copyVectorToVector (picketFence, signalB);
503 copyVectorToVector (correlations, correlationsMax);
508 dumpGnuplotCoordinate(coordinateLabel,
523 start = coordinateFromBin (qFloor (binStartMax),
526 if (binStartMax + binStepMax < m_numHistogramBins) {
529 double next = coordinateFromBin (qFloor (binStartMax + binStepMax),
536 double next = coordinateFromBin (m_numHistogramBins - 1,
543 dumpGnuplotCorrelations (coordinateLabel,
553 delete [] correlations;
554 delete [] correlationsMax;
555 delete [] picketFence;
#define ENGAUGE_ASSERT(cond)
Drop in replacement for Q_ASSERT.
const QString GNUPLOT_DELIMITER("\t")
log4cpp::Category * mainCat
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.
CoordsType coordsType() const
Get method for coordinates type.
double originRadius() const
Get method for origin radius in polar mode.
GridClassifier()
Single constructor.
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.
#define LOG4CPP_INFO_S(logger)
const QString GNUPLOT_FILE_MESSAGE