Templates -- Meow  1.2.10
A C++ template contains kinds of interesting classes and functions
FeaturePointsDetector_Harris.h
Go to the documentation of this file.
1 #ifndef gra_FeaturePointsDetector_Harris
2 #define gra_FeaturePointsDetector_Harris
3 
5 
6 #include "Bitmap.h"
7 #include "FeaturePoint.h"
9 
10 #include "../dsa/DisjointSet.h"
11 #include "../math/utility.h"
12 
13 #include "../Self.h"
14 
15 #include <vector>
16 #include <algorithm>
17 
18 namespace meow {
19 
25 template <class Pixel, class MyFP = FeaturePoint<double, double> >
27 # define FPD_Harris FeaturePointsDetector_Harris
28 private:
29  struct Myself {
30  double ratioK_;
31  double thresholdR_;
32  double sizeW_;
33  double noiseN_;
34  double lightL_;
35  double featureG_;
36  size_t boundB_;
37  size_t angleA_;
38 
39  Myself():
40  ratioK_(0.03),
41  thresholdR_(0.001),
42  sizeW_(2.0),
43  noiseN_(3.0),
44  lightL_(30.0),
45  featureG_(3.0),
46  boundB_(10u),
47  angleA_(8) {
48  }
49  Myself(Myself const& m):
50  ratioK_(m.ratioK_),
51  thresholdR_(m.thresholdR_),
52  sizeW_(m.sizeW_),
53  noiseN_(m.noiseN_),
54  lightL_(m.lightL_),
55  featureG_(m.featureG_),
56  boundB_(m.boundB_){
57  }
58  ~Myself() {
59  }
60  };
61 
62  Self<Myself> const self;
63 public:
65  FPD_Harris(): self() {
66  }
67 
69  FPD_Harris(FPD_Harris const& fps): self(fps.self, Self<Myself>::COPY_FROM) {
70  }
71 
74  }
75 
78  self().copyFrom(fps.self);
79  return *this;
80  }
81 
84  self().referenceFrom(fps.self);
85  return *this;
86  }
87 
89  double paramK() const {
90  return self->ratioK_;
91  }
92 
94  double paramR() const {
95  return self->thresholdR_;
96  }
97 
99  double paramW() const {
100  return self->sizeW_;
101  }
102 
104  double paramN() const {
105  return self->noiseN_;
106  }
107 
109  double paramG() const {
110  return self->featureG_;
111  }
112 
114  double paramL() const {
115  return self->lightL_;
116  }
117 
119  size_t paramB() const {
120  return self->boundB_;
121  }
122 
124  size_t paramA() const {
125  return self->angleA_;
126  }
127 
129  double paramK(double k) {
130  self()->ratioK_ = k;
131  return paramK();
132  }
133 
135  double paramR(double r) {
136  self()->thresholdR_ = r;
137  return paramR();
138  }
139 
141  double paramW(double w) {
142  self()->sizeW_ = w;
143  return paramW();
144  }
145 
147  double paramN(double n){
148  self()->noiseN_ = n;
149  return paramN();
150  }
151 
153  double paramL(double l) {
154  self()->lightL_ = l;
155  return paramL();
156  }
157 
159  double paramG(double g) {
160  self()->featureG_ = g;
161  return paramG();
162  }
163 
165  size_t paramB(size_t b) {
166  self()->boundB_ = b;
167  return paramB();
168  }
169 
171  size_t paramA(size_t a) {
172  self()->angleA_ = a;
173  return paramA();
174  }
175 
176  size_t descriptionDimension() const {
177  return (paramA() + 1) * squ(paramB() * 2 + 1);
178  //return (squ(self->boundB_ * 2 + 1) - 1) * 2;
179  }
180 
186  std::vector<MyFP> detect(Bitmap<Pixel> const& bmp) const {
187  // blur for feature, gradiance
188  Bitmap<Pixel> input (bmp.gaussian (self->featureG_, self->featureG_));
189  Bitmap<Pixel> input_gx(bmp.gradianceX(0 , self->noiseN_ ));
190  Bitmap<Pixel> input_gy(bmp.gradianceY(self->noiseN_ , 0 ));
191 
192  // get Matrix Ixx, Iyy, Ixy for each pixel
193  Bitmap<Vector3D<double> > Ixys(input.height(), input.width(),
194  Vector3D<double>(0.0));
195  for (ssize_t y = 0, Y = input.height(); y < Y; y++)
196  for (ssize_t x = 0, X = input.width(); x < X; x++) {
197  Pixel gx(input_gx(y, x));
198  Pixel gy(input_gy(y, x));
199  Ixys.pixel(y, x, Vector3D<double>(gx * gx, gy * gy, gx * gy));
200  }
201 
202  // blur for window size
203  Ixys.gaussianed(self->sizeW_, self->sizeW_);
204  //input_gx.clear();
205  //input_gy.clear();
206 
207  // filter too flat or on edge
208  Bitmap<double> R(input.height(), input.width(), 0.0);
209  Bitmap<bool> good(input.height(), input.width(), false);
210  for (ssize_t y = 0, Y = input.height(); y < Y; y++)
211  for (ssize_t x = 0, X = input.width(); x < X; x++) {
212  double det = Ixys(y, x)(0) * Ixys(y, x)(1) - squ(Ixys(y, x)(2));
213  double tra = Ixys(y, x)(0) + Ixys(y, x)(1);
214  double r = det - self->ratioK_ * squ(tra);
215  R.pixel(y, x, r);
216  good.pixel(y, x, (r >= self->thresholdR_));
217  }
218  Ixys.clear();
219 
220  // find union neighbor
221  DisjointSet dsj(input.size());
222  ssize_t dy[2] = {0, 1};
223  ssize_t dx[2] = {1, 0};
224  for (ssize_t y = 0, Y = input.height(); y + 1 < Y; y++)
225  for (ssize_t x = 0, X = input.width(); x + 1 < X; x++)
226  if(good.pixel((size_t)y, (size_t)x))
227  for (size_t k = 0; k < 2u; k++)
228  if (good.pixel((size_t)(y + dy[k]), (size_t)(x + dx[k])))
229  dsj.merge( y * input.width() + x,
230  (y + dy[k]) * input.width() + (x + dx[k]));
231 
232  // find local maximum
233  std::vector<size_t> max_i(input.size());
234  for (size_t i = 0, I = input.size(); i < I; i++)
235  max_i[i] = i;
236 
237  for (size_t i = 0, I = input.size(); i < I; i++) {
238  size_t ri = dsj.root(i);
239  if (R.pixel( i / input.width(), i % input.width()) >
240  R.pixel(max_i[ri] / input.width(), max_i[ri] % input.width()))
241  max_i[ri] = i;
242  }
243 
244  // Ignore side
245  ssize_t b = std::max<int>(std::max<int>(self->boundB_,
246  2 * self->sizeW_),
247  2 * self->noiseN_);
248  std::vector<MyFP> ret;
249  Vector<double> desc(descriptionDimension(), 0.0); // description
250  for (ssize_t y = b, Y = -b + input.height(); y < Y; y++)
251  for (ssize_t x = b, X = -b + input.width(); x < X; x++) {
252  if (!good.pixel((size_t)y, (size_t)x)) continue;
253  size_t i = y * input.width() + x;
254  if (max_i[dsj.root(i)] != i) continue;
255  int B = paramB();
256  size_t ct = 0;
257  for (ssize_t dx = -B; dx <= B; ++dx)
258  for (ssize_t dy = -B; dy <= B; ++dy) {
259  double gx = input_gx.pixel(y+dy, x+dx) * input_gx.pixel(y+dy, x+dx);
260  double gy = input_gy.pixel(y+dy, x+dx) * input_gy.pixel(y+dy, x+dx);
261  double light = sqrt(gx + gy);
262  double angle = circle(atan2(sqrt(gy), sqrt(gx)));
263  int a = angle / (2 * PI / paramA());
264  for (size_t k = 0; k < paramA(); ++k) {
265  desc.scalar(ct++, (a + k) % paramA());
266  }
267  desc.scalar(ct++, light * paramL());
268  }
269  /*
270  ssize_t dx[4] = {1, 0, -1, 0};
271  ssize_t dy[4] = {0, 1, 0, -1};
272  size_t ct = 0;
273  for (ssize_t d = 1; d <= (ssize_t)self->boundB_; ++d) {
274  std::vector<double> light;
275  size_t max_id = 0, x0 = x - d, y0 = y - d;
276  for (size_t k = 0; k < 4; k++)
277  for (ssize_t n = 0; n < (ssize_t)d * 2; n++,
278  x0 += dx[k], y0 += dy[k]) {
279  Pixel diff = input.pixel(y0, x0) - input.pixel(y, x) * 0.2;
280  light.push_back(diff * diff * self->lightL_);
281  if (light[max_id] < light[(ssize_t)light.size() - 1])
282  max_id = (ssize_t)light.size() - 1;
283  }
284  double W = squ(light.size()) * 0.5;
285  for (ssize_t n = 0, N = light.size(); n < N; n++) {
286  desc.scalar(ct++, (max_id + n) % N * 1.0 / W);
287  desc.scalar(ct++, light[(max_id + n) % N] / N);
288  }
289  }
290  // */
291  ret.push_back(MyFP(Vector2D<double>(1.0 * x, 1.0 * y).matrix(), desc));
292  }
293  return ret;
294  }
295 
298  return copyFrom(fps);
299  }
300 
302  std::vector<MyFP> operator()(Bitmap<Pixel> const& bmp) const {
303  return detect(bmp);
304  }
305 
310  bool write(FILE* f, bool bin, unsigned int fg) const {
311  // TODO
312  return false;
313  }
314 
319  bool read (FILE* f, bool bin, unsigned int fg) {
320  // TODO
321  return false;
322  }
323 
328  ObjBase* create() const {
329  return (ObjBase*)new FPD_Harris<Pixel>();
330  }
331 
341  ObjBase* copyFrom(ObjBase const* b) {
342  return &(copyFrom(*(FPD_Harris const*)b));
343  }
344 
349  char const* ctype() const {
350  return typeid(*this).name();
351  }
352 
357  std::string type() const {
358  return std::string(ctype());
359  }
360 # undef FPD_Harris
361 };
362 
363 } // meow
364 
365 #endif // gra_FeaturePointsDetector_Harris
Bitmap< Pixel > gradianceY(double radiusY, double radiusX) const
回傳對y偏微分
Definition: Bitmap.h:321
bool write(FILE *f, bool bin, unsigned int fg) const
寫到檔案裡
ObjBase * create() const
new一個自己
ObjBase * copyFrom(ObjBase const *b)
複製資料
Bitmap gaussian(double radiusY, double radiusX) const
回傳高斯模糊
Definition: Bitmap.h:275
bool read(FILE *f, bool bin, unsigned int fg)
將資料讀入
用來維護一堆互斥集的資訊
Definition: DisjointSet.h:25
二維點陣資料
Definition: Bitmap.h:25
std::vector< MyFP > operator()(Bitmap< Pixel > const &bmp) const
same as detect(bmp)
Pixel pixel(size_t y, size_t x) const
取得 (y, x) 的pixel
Definition: Bitmap.h:212
一切物件的Base, 並要求每個物件都要有read, write, create, ... 等功能
Definition: ObjBase.h:15
vector
Definition: Vector.h:19
size_t merge(size_t a, size_t b)
合併
Definition: DisjointSet.h:128
FPD_Harris & operator=(FPD_Harris const &fps)
same as copyFrom(fps)
FPD_Harris & copyFrom(FPD_Harris const &fps)
複製
FPD_Harris()
constructor 使用預設參數
Bitmap gradianceX(double radiusY, double radiusX) const
回傳對x偏微分
Definition: Bitmap.h:298
std::vector< MyFP > detect(Bitmap< Pixel > const &bmp) const
找出特徵點
Scalar scalar(size_t i) const
return i -th scalar
Definition: Vector.h:125
std::string type() const
回傳class的type
T circle(T x)
將角度調整於0~2PI
Definition: utility.h:18
static const double PI
圓周率...
Definition: utility.h:12
Harris-Corner-Detect algorithm for finding feature points.
For developer to pack the attributes of a class.
Definition: self.h:110
char const * ctype() const
回傳class的type
FPD_Harris(FPD_Harris const &fps)
constructor 參數複製自另一個 FeaturePointsDetector_Harris
T squ(T const &x)
x*x
Definition: utility.h:77
FPD_Harris & referenceFrom(FPD_Harris const &fps)
參照