ImageRegionFinder.cpp
Go to the documentation of this file.
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 
24 {
25 }
26 
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 // cerr << "thresh=" << thresh << ", dist=" << dist << endl;
122 
123  return (dist < thresh);
124 }
125 
bool similar(QRgb a, QRgb b) const
QRect findRegionExtents(QImage *image, QPoint origin) const