annotate layer/ImageRegionFinder.cpp @ 1431:af824022bffd single-point

Begin fixing the various snap operations. Also remove SnapNearest, which is never used and seems to consume more lines of code than the rest!
author Chris Cannam
date Wed, 20 Mar 2019 14:59:34 +0000
parents b66fb15de477
children
rev   line source
Chris@283 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@283 2
Chris@283 3 /*
Chris@283 4 Sonic Visualiser
Chris@283 5 An audio file viewer and annotation editor.
Chris@283 6 Centre for Digital Music, Queen Mary, University of London.
Chris@283 7 This file copyright 2007 QMUL.
Chris@283 8
Chris@283 9 This program is free software; you can redistribute it and/or
Chris@283 10 modify it under the terms of the GNU General Public License as
Chris@283 11 published by the Free Software Foundation; either version 2 of the
Chris@283 12 License, or (at your option) any later version. See the file
Chris@283 13 COPYING included with this distribution for more information.
Chris@283 14 */
Chris@283 15
Chris@283 16 #include "ImageRegionFinder.h"
Chris@283 17
Chris@283 18 #include <QImage>
Chris@283 19 #include <cmath>
Chris@283 20 #include <stack>
Chris@283 21 #include <iostream>
Chris@283 22
Chris@283 23 ImageRegionFinder::ImageRegionFinder()
Chris@283 24 {
Chris@283 25 }
Chris@283 26
Chris@283 27 ImageRegionFinder::~ImageRegionFinder()
Chris@283 28 {
Chris@283 29 }
Chris@283 30
Chris@283 31 QRect
Chris@283 32 ImageRegionFinder::findRegionExtents(QImage *image, QPoint origin) const
Chris@283 33 {
Chris@283 34 int w = image->width(), h = image->height();
Chris@283 35
Chris@283 36 QImage visited(w, h, QImage::Format_Mono);
Chris@283 37 visited.fill(0);
Chris@283 38
Chris@283 39 std::stack<QPoint> s;
Chris@283 40 s.push(origin);
Chris@283 41
Chris@283 42 int xmin = origin.x();
Chris@283 43 int xmax = xmin;
Chris@283 44 int ymin = origin.y();
Chris@283 45 int ymax = ymin;
Chris@283 46
Chris@283 47 QRgb opix = image->pixel(origin);
Chris@283 48
Chris@283 49 while (!s.empty()) {
Chris@283 50
Chris@283 51 QPoint p = s.top();
Chris@283 52 s.pop();
Chris@283 53
Chris@283 54 visited.setPixel(p, 1);
Chris@283 55
Chris@283 56 int x = p.x(), y = p.y();
Chris@283 57
Chris@283 58 if (x < xmin) xmin = x;
Chris@283 59 if (x > xmax) xmax = x;
Chris@283 60
Chris@283 61 if (y < ymin) ymin = y;
Chris@283 62 if (y > ymax) ymax = y;
Chris@283 63
Chris@283 64 std::stack<QPoint> neighbours;
Chris@283 65
Chris@283 66 int similarNeighbourCount = 0;
Chris@283 67
Chris@283 68 for (int dx = -1; dx <= 1; ++dx) {
Chris@283 69 for (int dy = -1; dy <= 1; ++dy) {
Chris@283 70
Chris@283 71 if ((dx != 0 && dy != 0) ||
Chris@283 72 (dx == 0 && dy == 0))
Chris@283 73 continue;
Chris@283 74
Chris@283 75 if (x + dx < 0 || x + dx >= w ||
Chris@283 76 y + dy < 0 || y + dy >= h)
Chris@283 77 continue;
Chris@283 78
Chris@283 79 if (visited.pixelIndex(x + dx, y + dy) != 0)
Chris@283 80 continue;
Chris@283 81
Chris@283 82 if (!similar(opix, image->pixel(x + dx, y + dy)))
Chris@283 83 continue;
Chris@283 84
Chris@283 85 neighbours.push(QPoint(x + dx, y + dy));
Chris@283 86 ++similarNeighbourCount;
Chris@283 87 }
Chris@283 88 }
Chris@283 89
Chris@283 90 if (similarNeighbourCount >= 2) {
Chris@283 91 while (!neighbours.empty()) {
Chris@283 92 s.push(neighbours.top());
Chris@283 93 neighbours.pop();
Chris@283 94 }
Chris@283 95 }
Chris@283 96 }
Chris@283 97
Chris@283 98 return QRect(xmin, ymin, xmax - xmin, ymax - ymin);
Chris@283 99 }
Chris@283 100
Chris@283 101 bool
Chris@283 102 ImageRegionFinder::similar(QRgb a, QRgb b) const
Chris@283 103 {
Chris@283 104 if (b == qRgb(0, 0, 0) || b == qRgb(255, 255, 255)) {
Chris@283 105 // black and white are boundary cases, don't compare similar
Chris@283 106 // to anything -- not even themselves
Chris@283 107 return false;
Chris@283 108 }
Chris@283 109
Chris@905 110 float ar = float(qRed(a)) / 255.f;
Chris@905 111 float ag = float(qGreen(a)) / 255.f;
Chris@905 112 float ab = float(qBlue(a)) / 255.f;
Chris@283 113 float amag = sqrtf(ar * ar + ag * ag + ab * ab);
Chris@283 114 float thresh = amag / 2;
Chris@283 115
Chris@283 116 float dr = float(qRed(a) - qRed(b)) / 255.f;
Chris@283 117 float dg = float(qGreen(a) - qGreen(b)) / 255.f;
Chris@283 118 float db = float(qBlue(a) - qBlue(b)) / 255.f;
Chris@283 119 float dist = sqrtf(dr * dr + dg * dg + db * db);
Chris@283 120
Chris@682 121 // cerr << "thresh=" << thresh << ", dist=" << dist << endl;
Chris@283 122
Chris@283 123 return (dist < thresh);
Chris@283 124 }
Chris@283 125