00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <cvd/image.h>
00021 #include <cvd/convolution.h>
00022 #include <gvars3/instances.h>
00023 #include <vector>
00024
00025 #include "harrislike.h"
00026
00027 using namespace std;
00028 using namespace CVD;
00029 using namespace GVars3;
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 template<class C> inline C sq(const C& c)
00040 {
00041 return c*c;
00042 }
00043
00044
00045 struct HarrisScore
00046 {
00047 static float Compute(float xx, float xy, float yy)
00048 {
00049 return (xx * yy - xy * xy) - 0.04 * sq(xx + yy);
00050 }
00051 };
00052
00053 struct ShiTomasiScore
00054 {
00055 static float Compute(float xx, float xy, float yy)
00056 {
00057 float l1 = xx + yy + sqrt(sq(xx - yy)+4.0*xy*xy);
00058 float l2 = xx + yy - sqrt(sq(xx - yy)+4.0*xy*xy);
00059 return min(abs(l1), abs(l2));
00060 }
00061 };
00062
00063 struct PosInserter
00064 {
00065 static void insert(vector<ImageRef>& i, const pair<float, ImageRef>& p)
00066 {
00067 i.push_back(p.second);
00068 }
00069 };
00070
00071 struct PairInserter
00072 {
00073 static void insert(vector<pair<float, ImageRef> >& i, const pair<float, ImageRef>& p)
00074 {
00075 i.push_back(p);
00076 }
00077 };
00078
00079
00080 template<class Score, class Inserter, class C, class B> void harris_like(const Image<B>& i, C& c, unsigned int N, float blur, float sigmas)
00081 {
00082
00083 Image<float> xx(i.size()), xy(i.size()), yy(i.size());
00084
00085 zeroBorders(xx);
00086 zeroBorders(xy);
00087 zeroBorders(yy);
00088
00089 typedef typename Pixel::traits<B>::wider_type gType;
00090
00091
00092 for(int y=1; y < i.size().y - 1; y++)
00093 for(int x=1; x < i.size().x - 1; x++)
00094 {
00095 gType gx = (gType)i[y][x-1] - i[y][x+1];
00096 gType gy = (gType)i[y-1][x] - i[y+1][x];
00097
00098
00099 xx[y][x] = gx * gx;
00100 xy[y][x] = gx * gy;
00101 yy[y][x] = gy * gy;
00102 }
00103
00104 convolveGaussian_fir(xx, xx, blur, sigmas);
00105 convolveGaussian_fir(xy, xy, blur, sigmas);
00106 convolveGaussian_fir(yy, yy, blur, sigmas);
00107
00108
00109
00110 int kspread = (int)ceil(sigmas * blur);
00111
00112
00113 for(int y=kspread; y < i.size().y-kspread; y++)
00114 for(int x=kspread; x <i.size().x-kspread; x++)
00115 xx[y][x] = Score::Compute(xx[y][x], xy[y][x], yy[y][x]);
00116
00117 vector<pair<float, ImageRef> > corners;
00118 corners.reserve(10000);
00119
00120
00121 for(int y=kspread; y < i.size().y-kspread; y++)
00122 for(int x=kspread; x <i.size().x-kspread; x++)
00123 {
00124 float c = xx[y][x];
00125
00126 if( c > xx[y-1][x-1] &&
00127 c > xx[y-1][x+0] &&
00128 c > xx[y-1][x+1] &&
00129 c > xx[y-0][x-1] &&
00130 c > xx[y-0][x+1] &&
00131 c > xx[y+1][x-1] &&
00132 c > xx[y+1][x+0] &&
00133 c > xx[y+1][x+1])
00134 {
00135 corners.push_back(make_pair(-c, ImageRef(x, y)));
00136 }
00137 }
00138
00139 if(corners.size() > N)
00140 {
00141 nth_element(corners.begin(), corners.begin() + N, corners.end());
00142 corners.resize(N);
00143 }
00144
00145
00146 for(unsigned int i=0; i < corners.size(); i++)
00147 Inserter::insert(c, corners[i]);
00148 }
00149
00150
00151 void HarrisDetector(const Image<float>& i, vector<pair<float, ImageRef> >& c, unsigned int N, float blur, float sigmas)
00152 {
00153 harris_like<HarrisScore, PairInserter>(i, c, N, blur, sigmas);
00154 }
00155
00156
00157 void HarrisDetect::operator()(const CVD::Image<CVD::byte>& i, std::vector<CVD::ImageRef>& c, unsigned int N) const
00158 {
00159 float blur = GV3::get<float>("harris.blur", 2.5, 1);
00160 float sigmas = GV3::get<float>("harris.sigmas", 2.0, 1);
00161 harris_like<HarrisScore,PosInserter>(i, c, N, blur, sigmas);
00162 }
00163
00164 void ShiTomasiDetect::operator()(const CVD::Image<CVD::byte>& i, std::vector<CVD::ImageRef>& c, unsigned int N) const
00165 {
00166 float blur = GV3::get<float>("shitomasi.blur", 2.5, 1);
00167 float sigmas = GV3::get<float>("shitomasi.sigmas", 2.0, 1);
00168 harris_like<ShiTomasiScore, PosInserter>(i, c, N, blur, sigmas);
00169 }