Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
GradientSimple.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 
26 #include "GradientSimple.hh"
27 #include "FilterMask.hh"
28 
29 using namespace BIAS;
30 using namespace std;
31 
32 namespace BIAS {
33 
34 #define POLAR_TABLE_OFFSET 128
35 #define POLAR_TABLE_SIZE 257
36 //////////////////////////////////////////////////////////////////////////
37 // implementation
38 //////////////////////////////////////////////////////////////////////////
39 template <class InputStorageType, class OutputStorageType> void
42 {
43  // this is a filtermask in the sense of convolution
44  // it is reflected at its symmetry center before being "dropped"
45  // onto the image !
46  Vector<FM_INT> h(3), v(1);
47  if (useDirectNeighbors_) {
48  h[0] = 0;
49  h[1] = 1;
50  h[2] = -1;
51  } else {
52  h[0] = 1;
53  h[1] = 0;
54  h[2] = -1;
55  }
56  v[0] = 1;
57  FilterMask f(h, v, useDirectNeighbors_?0:1, 0);
59  _Conv.SetKernel(f);
60 }
61 
62 template <class InputStorageType, class OutputStorageType>
64 GradientSimple(bool BuildPCM)
65  : FilterNTo2N<InputStorageType, OutputStorageType>() ,
66  pRadius_(NULL), pAngle_(NULL), useDirectNeighbors_(false)
67 {
68  InitKernel_();
69  if (BuildPCM) BuildPolarCoordinateMap_();
70 }
71 
72 template <class InputStorageType, class OutputStorageType>
75  : _Conv(other._Conv),
76  useDirectNeighbors_(other.useDirectNeighbors_)
77 {
78  InitKernel_();
79 }
80 
81 template <class InputStorageType, class OutputStorageType>
84 {
85  if (pRadius_ != NULL) {
86  pRadius_ -= POLAR_TABLE_OFFSET;
87  for (int i=0; i<POLAR_TABLE_SIZE; i++)
88  delete [] (pRadius_[i]-POLAR_TABLE_OFFSET);
89  delete [] pRadius_;
90  pRadius_ = NULL;
91  }
92  if (pAngle_ != NULL) {
93  pAngle_ -= POLAR_TABLE_OFFSET;
94  for (int i=0; i<POLAR_TABLE_SIZE; i++)
95  delete [] (pAngle_[i]-POLAR_TABLE_OFFSET);
96  delete [] pAngle_;
97  pAngle_ = NULL;
98  }
99 }
100 
101 
102 template <class InputStorageType, class OutputStorageType>
105 {
106  BIASCDOUT(D_FILTERBASE_CALLSTACK, "GradientSimple::Filter(src, dst)\n");
108  int res=Filter(src, grad, gy);
109  grad.AppendChannel(gy);
110  return res;
111 }
112 
113 template <class InputStorageType, class OutputStorageType>
117 {
118  BIASCDOUT(D_FILTERBASE_CALLSTACK, "GradientSimple::Filter(src, gx, gy)\n");
119  int res=0;
120  if (!gx.SamePixelAndChannelCount(src)){
121  gx.Release();
122  gx.Init(src.GetWidth(), src.GetHeight(), src.GetChannelCount());
123  }
124  if (!gy.SamePixelAndChannelCount(src)){
125  gy.Release();
126  gy.Init(src.GetWidth(), src.GetHeight(), src.GetChannelCount());
127  }
128 
129  if (src.GetChannelCount()==1) {
130  if (_Conv.CalculationInFloat()){
131  if (useDirectNeighbors_)
132  res = DirectNeighborsGreyValidFloat_(src, gx, gy);
133  else
134  res = SimpleGreyValidFloat_(src, gx, gy);
135  } else {
136  if (useDirectNeighbors_)
137  res = DirectNeighborsGreyValidInt_(src, gx, gy);
138  else
139  res = SimpleGreyValidInt_(src, gx, gy);
140  }
141  } else {
142  // grest
143  BIASERR("not for multiple channel images");
144  return -5;
145  }
146  return res;
147 }
148 
149 template <class InputStorageType, class OutputStorageType>
153 {
154  BIASCDOUT(D_FILTERBASE_CALLSTACK,
155  "GradientSimple::Filter(src, gx, gy, abs)\n");
156  if (!src.SamePixelAndChannelCount(absg)){
157  if (!absg.IsEmpty()) absg.Release();
158  absg.Init(src.GetWidth(), src.GetHeight(), src.GetChannelCount());
159  }
160 
161  int res, absres=0;
162  res = Filter(src, gx, gy);
163 
164  absres = this->VecLen(gx, gy, absg);
165 
166  return (res==0 && absres==0)?0:-1;
167 }
168 
169 
170 
171 
172 template <class InputStorageType, class OutputStorageType>
177 {
178  BIASCDOUT(D_FILTERBASE_CALLSTACK, "GradientSimple::SimpleGreyValidFloat_\n");
179 
180  OutputStorageType *gx=gWE.GetImageData();
181  OutputStorageType *gy=gNS.GetImageData();
182  const int width=(int)src.GetWidth();
183  const int nwidth = - width;
184 
185 #ifdef BIAS_DEBUG
186  BIASASSERT(src.GetChannelCount()==1);
187  BIASASSERT(src.SamePixelAndChannelCount(gWE));
188  BIASASSERT(src.SamePixelAndChannelCount(gNS));
189  BIASASSERT(gx!=gy);
190  BIASASSERT(_Conv.CalculationInFloat());
191 #endif
192 
193  int minx, miny, maxx, maxy;
194  src.GetROI()->GetCorners(minx, miny, maxx, maxy);
195  gWE.GetROI()->SetCorners(minx+1, miny+1, maxx-1, maxy-1);
196  gNS.GetROI()->SetCorners(minx+1, miny+1, maxx-1, maxy-1);
197 
198  const InputStorageType *ph;
199 
200  int offset;
201  OutputStorageType *pgx, *pgy, *end2, *lend2;
202 
203 
204  int step=width-maxx+minx;
205 
206  offset=minx+1+(miny+1)*width;
207  ph = src.GetImageData() + offset;
208  pgx=gx+offset;
209  pgy=gy+offset;
210  step+=2;
211  end2=gx+maxx+width*(maxy-2)-1;
212  lend2=gx+maxx+width*(miny+1)-1;
213  while (pgx<end2){
214  while (pgx<lend2){
215  *pgx++ = (OutputStorageType)(ph[1] - ph[-1])/
216  (OutputStorageType)2;
217  *pgy++ = (OutputStorageType)(ph[width] - ph[nwidth])/
218  (OutputStorageType)2;
219  ph++;
220  }
221  ph+=step;
222  pgx+=step;
223  pgy+=step;
224  lend2+=width;
225  }
226  return 0;
227 }
228 
229 
230 template <class InputStorageType, class OutputStorageType>
235 {
236  BIASCDOUT(D_FILTERBASE_CALLSTACK, "GradientSimple::SimpleGreyValidInt_\n");
237 
238  OutputStorageType *gx=gWE.GetImageData();
239  OutputStorageType *gy=gNS.GetImageData();
240  const int width=(int)src.GetWidth();
241  const int nwidth = - width;
242 
243 #ifdef BIAS_DEBUG
244  BIASASSERT(src.GetChannelCount()==1);
245  BIASASSERT(src.SamePixelAndChannelCount(gWE));
246  BIASASSERT(src.SamePixelAndChannelCount(gNS));
247  BIASASSERT(gx!=gy);
248  BIASASSERT(!_Conv.CalculationInFloat());
249 #endif
250 
251 
252 
253  int minx, miny, maxx, maxy;
254  src.GetROI()->GetCorners(minx, miny, maxx, maxy);
255  gWE.GetROI()->SetCorners(minx+1, miny+1, maxx-1, maxy-1);
256  gNS.GetROI()->SetCorners(minx+1, miny+1, maxx-1, maxy-1);
257 
258  const InputStorageType *ph;
259 
260  int offset;
261  OutputStorageType *pgx, *pgy, *end2, *lend2;
262 
263 
264  int step=width-maxx+minx;
265 
266  offset=minx+1+(miny+1)*width;
267  ph = src.GetImageData()+offset;
268 
269  pgx=gx+offset;
270  pgy=gy+offset;
271  step+=2;
272  end2=gx+maxx+width*(maxy-2)-1;
273  lend2=gx+maxx+width*(miny+1)-1;
274  while (pgx<end2){
275  while (pgx<lend2){
276  *pgx++ = (OutputStorageType)(ph[1] - ph[-1])/
277  (OutputStorageType)2;
278  *pgy++ = (OutputStorageType)(ph[width] - ph[nwidth])/
279  (OutputStorageType)2;
280  ph++;
281  }
282  ph+=step;
283  pgx+=step;
284  pgy+=step;
285  lend2+=width;
286  }
287 
288  return 0;
289 }
290 
291 
292 template <class InputStorageType, class OutputStorageType>
297 {
298  BIASCDOUT(D_FILTERBASE_CALLSTACK, "GradientSimple::SimpleGreyValidFloat_\n");
299 
300  OutputStorageType *gx=gWE.GetImageData();
301  OutputStorageType *gy=gNS.GetImageData();
302  const int width=(int)src.GetWidth();
303 
304 #ifdef BIAS_DEBUG
305  BIASASSERT(src.GetChannelCount()==1);
306  BIASASSERT(src.SamePixelAndChannelCount(gWE));
307  BIASASSERT(src.SamePixelAndChannelCount(gNS));
308  BIASASSERT(gx!=gy);
309  BIASASSERT(_Conv.CalculationInFloat());
310 #endif
311 
312  int minx, miny, maxx, maxy;
313  src.GetROI()->GetCorners(minx, miny, maxx, maxy);
314  gWE.GetROI()->SetCorners(minx+1, miny+1, maxx-1, maxy-1);
315  gNS.GetROI()->SetCorners(minx+1, miny+1, maxx-1, maxy-1);
316 
317  const InputStorageType *ph;
318 
319  int offset;
320  OutputStorageType *pgx, *pgy, *end2, *lend2;
321 
322 
323  int step=width-maxx+minx;
324 
325  offset=minx+1+(miny+1)*width;
326  ph = src.GetImageData() + offset;
327  pgx=gx+offset;
328  pgy=gy+offset;
329  step+=2;
330  end2=gx+maxx+width*(maxy-2)-1;
331  lend2=gx+maxx+width*(miny+1)-1;
332  while (pgx<end2){
333  while (pgx<lend2){
334  *pgx++ = (OutputStorageType)(ph[1] - ph[0]);
335  *pgy++ = (OutputStorageType)(ph[width] - ph[0]);
336  ph++;
337  }
338  ph+=step;
339  pgx+=step;
340  pgy+=step;
341  lend2+=width;
342  }
343  return 0;
344 }
345 
346 
347 
348 
349 template <class InputStorageType, class OutputStorageType>
354 {
355  BIASCDOUT(D_FILTERBASE_CALLSTACK, "GradientSimple::SimpleGreyValidInt_\n");
356 
357  OutputStorageType *gx=gWE.GetImageData();
358  OutputStorageType *gy=gNS.GetImageData();
359  const int width=(int)src.GetWidth();
360 
361 #ifdef BIAS_DEBUG
362  BIASASSERT(src.GetChannelCount()==1);
363  BIASASSERT(src.SamePixelAndChannelCount(gWE));
364  BIASASSERT(src.SamePixelAndChannelCount(gNS));
365  BIASASSERT(gx!=gy);
366  BIASASSERT(!_Conv.CalculationInFloat());
367 #endif
368 
369 
370 
371  int minx, miny, maxx, maxy;
372  src.GetROI()->GetCorners(minx, miny, maxx, maxy);
373  gWE.GetROI()->SetCorners(minx+1, miny+1, maxx-1, maxy-1);
374  gNS.GetROI()->SetCorners(minx+1, miny+1, maxx-1, maxy-1);
375 
376  const InputStorageType *ph;
377 
378  int offset;
379  OutputStorageType *pgx, *pgy, *end2, *lend2;
380 
381 
382  int step=width-maxx+minx;
383 
384  offset = minx+1+(miny+1)*width;
385  ph = src.GetImageData()+offset;
386 
387  // can compute one or two lines more at the border, not yet implemented
388  pgx = gx+offset;
389  pgy = gy+offset;
390  step += 2;
391  end2 = gx + maxx + width*(maxy-2)-1;
392  lend2 = gx + maxx + width*(miny+1)-1;
393  while (pgx<end2){
394  while (pgx<lend2){
395  *pgx++ = (OutputStorageType)(ph[1] - ph[0]);
396  *pgy++ = (OutputStorageType)(ph[width] - ph[0]);
397  ph++;
398  }
399  ph += step;
400  pgx += step;
401  pgy += step;
402  lend2+= width;
403  }
404 
405  return 0;
406 }
407 
408 
409 
410 
411 
412 
413 
414 
415 
416 
417 
418 template <class InputStorageType, class OutputStorageType>
421 {
422  BIASASSERT(pRadius_ == NULL);
423  BIASASSERT(pAngle_ == NULL);
424 
425  pRadius_ = new float* [POLAR_TABLE_SIZE];
426  for (int i=0; i<POLAR_TABLE_SIZE; i++)
427  pRadius_[i] = new float [POLAR_TABLE_SIZE] + POLAR_TABLE_OFFSET;
428  pRadius_ += POLAR_TABLE_OFFSET;
429 
430  pAngle_ = new float* [POLAR_TABLE_SIZE];
431  for (int i=0; i<POLAR_TABLE_SIZE; i++)
432  pAngle_[i] = new float [POLAR_TABLE_SIZE] + POLAR_TABLE_OFFSET;
433  pAngle_ += POLAR_TABLE_OFFSET;
434 
435  for (int x=-POLAR_TABLE_OFFSET; x<=128; x++) {
436  for (int y=-POLAR_TABLE_OFFSET; y<=128; y++) {
437  pRadius_[x][y] = sqrtf(float(x*x+y*y));
438 
439  pAngle_[x][y] = -atan2f( float(y), float(x) );
440  if (pAngle_[x][y] < 0.0f)
441  (pAngle_[x][y]) += 2.0f * (float)M_PI;
442  }
443  }
444 }
445 
446 template<>
449  Image<float>& magnitude, Image<float>& phase) {
450  if (pRadius_ == NULL) BuildPolarCoordinateMap_();
451  BIASASSERT(pRadius_ != NULL);
452  if (!magnitude.SamePixelAndChannelCount(gx)) {
453  if (!magnitude.IsEmpty()) magnitude.Release();
454  magnitude.Init(gx.GetWidth(), gx.GetHeight(), 1);
455  }
456  if (!phase.SamePixelAndChannelCount(gx) ) {
457  if (!phase.IsEmpty()) phase.Release();
458  phase.Init(gx.GetWidth(), gx.GetHeight(), 1);
459  }
460  char *pgx = gx.GetImageData(), *pgy = gy.GetImageData();
461  float *pm = magnitude.GetImageData(), *pp = phase.GetImageData();
462  char* const pEnd = pgx + gx.GetPixelCount();
463  while (pgx<pEnd) {
464  *pp++ = pAngle_[(unsigned int)*pgx][(unsigned int)*pgy];
465  *pm++ = pRadius_[(unsigned int)*pgx++][(unsigned int)*pgy++];
466  }
467 }
468 
469 template <class InputStorageType, class OutputStorageType>
472  Image<float>& magnitude, Image<float>& phase) {
473  if (!magnitude.SamePixelAndChannelCount(gx)) {
474  if (!magnitude.IsEmpty()) magnitude.Release();
475  magnitude.Init(gx.GetWidth(), gx.GetHeight(), 1);
476  }
477  if (!phase.SamePixelAndChannelCount(gx) ) {
478  if (!phase.IsEmpty()) phase.Release();
479  phase.Init(gx.GetWidth(), gx.GetHeight(), 1);
480  }
481 
482  int minx, miny, maxx, maxy;
483  gx.GetROI()->GetCorners(minx, miny, maxx, maxy);
484  magnitude.GetROI()->SetCorners(minx, miny, maxx, maxy);
485  phase.GetROI()->SetCorners(minx, miny, maxx, maxy);
486 
487  OutputStorageType *pgx = gx.GetImageData(), *pgy = gy.GetImageData();
488  float *pm = magnitude.GetImageData(), *pp = phase.GetImageData();
489  OutputStorageType* const pEnd = pgx + gx.GetPixelCount();
490  while (pgx<pEnd) {
491  if ((*pp = -atan2f( float(*pgy), float(*pgx) ))<0.0f) {
492  *pp += float(2.0*M_PI);
493  }
494  pp++;
495  *pm++ = sqrtf(float(*pgx) * float(*pgx) + float(*pgy) * float(*pgy));
496  pgx++;
497  pgy++;
498  }
499 }
500 
501 
502 template <class InputStorageType, class OutputStorageType>
504 GetBordersValid_(int &border_x, int &border_y) const
505 {
506  _Conv.GetBorders(border_x, border_y);
507 }
508 
509 //////////////////////////////////////////////////////////////////////////
510 // instantiation
511 //////////////////////////////////////////////////////////////////////////
512 #define FILTER_INSTANTIATION_CLASS GradientSimple
513 #define FILTER_INSTANTIATION_NO_UNSIGNED_OUTPUT
514 #include "Filterinst.hh"
515 
516 } // namespace BIAS
void Release()
reimplemented from ImageBase
Definition: Image.cpp:1579
int SetCorners(unsigned UpperLeftX, unsigned UpperLeftY, unsigned LowerRightX, unsigned LowerRightY)
Sets a rectangular region of interest.
Definition: ROI.cpp:287
void GetCorners(unsigned &UpperLeftX, unsigned &UpperLeftY, unsigned &LowerRightX, unsigned &LowerRightY) const
Return the region of interest, by saving the coordinates within the variables defined by the paramete...
Definition: ROI.hh:443
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
Definition: ImageBase.hh:245
int AppendChannel(Image< StorageType > &img)
Definition: Image.cpp:1457
base class for simple n-&gt;2n filter implementations
Definition: FilterNTo2N.hh:44
void PolarTransform(Image< OutputStorageType > &gx, Image< OutputStorageType > &gy, Image< float > &magnitude, Image< float > &phase)
void InitKernel_()
sets the sobel kernel for the convolution object
void CreateFloatFilter()
create the float filter from the int filter
Definition: FilterMask.cpp:91
int SimpleGreyValidInt_(const Image< InputStorageType > &src, Image< OutputStorageType > &gWE, Image< OutputStorageType > &gNS)
loop unrolled fast int version [1 0 -1]
GradientSimple(bool BuildPCM=false)
unsigned int GetWidth() const
Definition: ImageBase.hh:312
simple gradient calculation gx(x,y) = I(x+1,y) - I(x-1,y) gy(x,y) = I(x,y+1) - I(x,y-1)
int DirectNeighborsGreyValidInt_(const Image< InputStorageType > &src, Image< OutputStorageType > &gWE, Image< OutputStorageType > &gNS)
loop unrolled fast int version [1 -1]
ROI * GetROI()
Returns a pointer to the roi object.
Definition: ImageBase.hh:615
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Definition: ImageBase.hh:382
int SimpleGreyValidFloat_(const Image< InputStorageType > &src, Image< OutputStorageType > &gWE, Image< OutputStorageType > &gNS)
loop unrolled fast float version for [1 0 -1]
unsigned int GetHeight() const
Definition: ImageBase.hh:319
bool SamePixelAndChannelCount(const ImageBase &Image) const
checks if data area has same &quot;size&quot; as Image of other type
Definition: ImageBase.hh:73
void Init(unsigned int Width, unsigned int Height, unsigned int channels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
calls Init from ImageBase storageType is ignored, just dummy argument
Definition: Image.cpp:421
const StorageType * GetImageData() const
overloaded GetImageData() from ImageBase
Definition: Image.hh:137
void BuildPolarCoordinateMap_()
set up pRadius and pAngle for polar coordinate transformation
int DirectNeighborsGreyValidFloat_(const Image< InputStorageType > &src, Image< OutputStorageType > &gWE, Image< OutputStorageType > &gNS)
loop unrolled fast float version [1 -1]
virtual void GetBordersValid_(int &border_x, int &border_y) const
unsigned long int GetPixelCount() const
returns number of pixels in image
Definition: ImageBase.hh:422
A filter mask (or a kernel) used for convolution.
Definition: FilterMask.hh:61
virtual int Filter(const Image< InputStorageType > &src, Image< OutputStorageType > &grad)
returns a 2 channel image containing gx and gy