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);
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,
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;