22 int GridClassifier::NUM_PIXELS_PER_HISTOGRAM_BINS = 1;
23 double GridClassifier::PEAK_HALF_WIDTH = 4;
24 int GridClassifier::MIN_STEP_PIXELS = qFloor (4 * GridClassifier::PEAK_HALF_WIDTH);
29 int GridClassifier::BIN_START_UNSHIFTED = qFloor (GridClassifier::PEAK_HALF_WIDTH);
37 int 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,
117 void 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());
158 double GridClassifier::coordinateFromBin (
int bin,
160 double coordMax)
const
165 return coordMin + (coordMax - coordMin) *
double (bin) / (double (m_numHistogramBins) - 1.0);
168 void GridClassifier::copyVectorToVector (
const double from [],
171 for (
int bin = 0; bin < m_numHistogramBins; bin++) {
172 to [bin] = from [bin];
176 void 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);
230 << GNUPLOT_DELIMITER << coordinate
231 << GNUPLOT_DELIMITER << bins [bin]
232 << GNUPLOT_DELIMITER << binCountMax * startStepValue
233 << GNUPLOT_DELIMITER << binCountMax * picketFence [bin] <<
"\n";
236 delete [] picketFence;
239 void 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,
285 << GNUPLOT_DELIMITER << signalA [bin] / signalAMax
286 << GNUPLOT_DELIMITER << signalB [bin] / signalBMax
287 << GNUPLOT_DELIMITER << correlations [bin] / correlationsMax <<
"\n";
291 void GridClassifier::initializeHistogramBins ()
295 for (
int bin = 0; bin < m_numHistogramBins; bin++) {
301 void 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;
352 void 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);
407 void GridClassifier::searchCountSpace (
double bins [],
413 <<
" start=" << binStart
414 <<
" step=" << binStep;
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;
445 void 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)];
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;
double originRadius() const
Get method for origin radius in polar mode.
#define LOG4CPP_INFO_S(logger)
Fast cross correlation between two functions.
Class for filtering image to remove unimportant information.
const QString GNUPLOT_FILE_MESSAGE
const QString GNUPLOT_DELIMITER("\t")
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.
log4cpp::Category * mainCat
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 ENGAUGE_ASSERT(cond)
Drop in replacement for Q_ASSERT if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS) define ENGAUGE...