annotate layer/ImageRegionFinder.cpp @ 1081:cbc7c8675706 spectrogram-minor-refactor

Comments
author Chris Cannam
date Thu, 30 Jun 2016 18:21:11 +0100
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