svgui
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2007 QMUL. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 00014 */ 00015 00016 #include "ImageRegionFinder.h" 00017 00018 #include <QImage> 00019 #include <cmath> 00020 #include <stack> 00021 #include <iostream> 00022 00023 ImageRegionFinder::ImageRegionFinder() 00024 { 00025 } 00026 00027 ImageRegionFinder::~ImageRegionFinder() 00028 { 00029 } 00030 00031 QRect 00032 ImageRegionFinder::findRegionExtents(QImage *image, QPoint origin) const 00033 { 00034 int w = image->width(), h = image->height(); 00035 00036 QImage visited(w, h, QImage::Format_Mono); 00037 visited.fill(0); 00038 00039 std::stack<QPoint> s; 00040 s.push(origin); 00041 00042 int xmin = origin.x(); 00043 int xmax = xmin; 00044 int ymin = origin.y(); 00045 int ymax = ymin; 00046 00047 QRgb opix = image->pixel(origin); 00048 00049 while (!s.empty()) { 00050 00051 QPoint p = s.top(); 00052 s.pop(); 00053 00054 visited.setPixel(p, 1); 00055 00056 int x = p.x(), y = p.y(); 00057 00058 if (x < xmin) xmin = x; 00059 if (x > xmax) xmax = x; 00060 00061 if (y < ymin) ymin = y; 00062 if (y > ymax) ymax = y; 00063 00064 std::stack<QPoint> neighbours; 00065 00066 int similarNeighbourCount = 0; 00067 00068 for (int dx = -1; dx <= 1; ++dx) { 00069 for (int dy = -1; dy <= 1; ++dy) { 00070 00071 if ((dx != 0 && dy != 0) || 00072 (dx == 0 && dy == 0)) 00073 continue; 00074 00075 if (x + dx < 0 || x + dx >= w || 00076 y + dy < 0 || y + dy >= h) 00077 continue; 00078 00079 if (visited.pixelIndex(x + dx, y + dy) != 0) 00080 continue; 00081 00082 if (!similar(opix, image->pixel(x + dx, y + dy))) 00083 continue; 00084 00085 neighbours.push(QPoint(x + dx, y + dy)); 00086 ++similarNeighbourCount; 00087 } 00088 } 00089 00090 if (similarNeighbourCount >= 2) { 00091 while (!neighbours.empty()) { 00092 s.push(neighbours.top()); 00093 neighbours.pop(); 00094 } 00095 } 00096 } 00097 00098 return QRect(xmin, ymin, xmax - xmin, ymax - ymin); 00099 } 00100 00101 bool 00102 ImageRegionFinder::similar(QRgb a, QRgb b) const 00103 { 00104 if (b == qRgb(0, 0, 0) || b == qRgb(255, 255, 255)) { 00105 // black and white are boundary cases, don't compare similar 00106 // to anything -- not even themselves 00107 return false; 00108 } 00109 00110 float ar = float(qRed(a) / 255.f); 00111 float ag = float(qGreen(a) / 255.f); 00112 float ab = float(qBlue(a) / 255.f); 00113 float amag = sqrtf(ar * ar + ag * ag + ab * ab); 00114 float thresh = amag / 2; 00115 00116 float dr = float(qRed(a) - qRed(b)) / 255.f; 00117 float dg = float(qGreen(a) - qGreen(b)) / 255.f; 00118 float db = float(qBlue(a) - qBlue(b)) / 255.f; 00119 float dist = sqrtf(dr * dr + dg * dg + db * db); 00120 00121 // cerr << "thresh=" << thresh << ", dist=" << dist << endl; 00122 00123 return (dist < thresh); 00124 } 00125