Mercurial > hg > svgui
comparison layer/ImageRegionFinder.cpp @ 283:86a112b5b319
* Make it possible to "measure" a feature on the spectrogram by double-
clicking in measure mode
* Make shift-click-drag (for zoom to region) work in measure mode as well
as navigate mode. It would be nice to be able to shift-doubleclick to
zoom on a feature directly using a combination of these last two features,
but that isn't possible yet.
* Make Del delete the measurement under the mouse pointer.
author | Chris Cannam |
---|---|
date | Thu, 05 Jul 2007 15:36:37 +0000 |
parents | |
children | 1a0dfcbffaf1 |
comparison
equal
deleted
inserted
replaced
282:4edaff85875d | 283:86a112b5b319 |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Sonic Visualiser | |
5 An audio file viewer and annotation editor. | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 This file copyright 2007 QMUL. | |
8 | |
9 This program is free software; you can redistribute it and/or | |
10 modify it under the terms of the GNU General Public License as | |
11 published by the Free Software Foundation; either version 2 of the | |
12 License, or (at your option) any later version. See the file | |
13 COPYING included with this distribution for more information. | |
14 */ | |
15 | |
16 #include "ImageRegionFinder.h" | |
17 | |
18 #include <QImage> | |
19 #include <cmath> | |
20 #include <stack> | |
21 #include <iostream> | |
22 | |
23 ImageRegionFinder::ImageRegionFinder() | |
24 { | |
25 } | |
26 | |
27 ImageRegionFinder::~ImageRegionFinder() | |
28 { | |
29 } | |
30 | |
31 QRect | |
32 ImageRegionFinder::findRegionExtents(QImage *image, QPoint origin) const | |
33 { | |
34 int w = image->width(), h = image->height(); | |
35 | |
36 QImage visited(w, h, QImage::Format_Mono); | |
37 visited.fill(0); | |
38 | |
39 std::stack<QPoint> s; | |
40 s.push(origin); | |
41 | |
42 int xmin = origin.x(); | |
43 int xmax = xmin; | |
44 int ymin = origin.y(); | |
45 int ymax = ymin; | |
46 | |
47 QRgb opix = image->pixel(origin); | |
48 | |
49 while (!s.empty()) { | |
50 | |
51 QPoint p = s.top(); | |
52 s.pop(); | |
53 | |
54 visited.setPixel(p, 1); | |
55 | |
56 int x = p.x(), y = p.y(); | |
57 | |
58 if (x < xmin) xmin = x; | |
59 if (x > xmax) xmax = x; | |
60 | |
61 if (y < ymin) ymin = y; | |
62 if (y > ymax) ymax = y; | |
63 | |
64 std::stack<QPoint> neighbours; | |
65 | |
66 int similarNeighbourCount = 0; | |
67 | |
68 for (int dx = -1; dx <= 1; ++dx) { | |
69 for (int dy = -1; dy <= 1; ++dy) { | |
70 | |
71 if ((dx != 0 && dy != 0) || | |
72 (dx == 0 && dy == 0)) | |
73 continue; | |
74 | |
75 if (x + dx < 0 || x + dx >= w || | |
76 y + dy < 0 || y + dy >= h) | |
77 continue; | |
78 | |
79 if (visited.pixelIndex(x + dx, y + dy) != 0) | |
80 continue; | |
81 | |
82 if (!similar(opix, image->pixel(x + dx, y + dy))) | |
83 continue; | |
84 | |
85 neighbours.push(QPoint(x + dx, y + dy)); | |
86 ++similarNeighbourCount; | |
87 } | |
88 } | |
89 | |
90 if (similarNeighbourCount >= 2) { | |
91 while (!neighbours.empty()) { | |
92 s.push(neighbours.top()); | |
93 neighbours.pop(); | |
94 } | |
95 } | |
96 } | |
97 | |
98 return QRect(xmin, ymin, xmax - xmin, ymax - ymin); | |
99 } | |
100 | |
101 bool | |
102 ImageRegionFinder::similar(QRgb a, QRgb b) const | |
103 { | |
104 if (b == qRgb(0, 0, 0) || b == qRgb(255, 255, 255)) { | |
105 // black and white are boundary cases, don't compare similar | |
106 // to anything -- not even themselves | |
107 return false; | |
108 } | |
109 | |
110 float ar = float(qRed(a) / 255.f); | |
111 float ag = float(qGreen(a) / 255.f); | |
112 float ab = float(qBlue(a) / 255.f); | |
113 float amag = sqrtf(ar * ar + ag * ag + ab * ab); | |
114 float thresh = amag / 2; | |
115 | |
116 float dr = float(qRed(a) - qRed(b)) / 255.f; | |
117 float dg = float(qGreen(a) - qGreen(b)) / 255.f; | |
118 float db = float(qBlue(a) - qBlue(b)) / 255.f; | |
119 float dist = sqrtf(dr * dr + dg * dg + db * db); | |
120 | |
121 // std::cerr << "thresh=" << thresh << ", dist=" << dist << std::endl; | |
122 | |
123 return (dist < thresh); | |
124 } | |
125 |