Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
GradientGaussAsymmetric.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 "GradientGaussAsymmetric.hh"
27 
28 using namespace BIAS;
29 using namespace std;
30 
31 //////////////////////////////////////////////////////////////////////////
32 // implementation
33 //////////////////////////////////////////////////////////////////////////
34 
35 template <class InputStorageType, class OutputStorageType>
38  : GradientGauss<InputStorageType, OutputStorageType>()
39 {}
40 
41 template <class InputStorageType, class OutputStorageType>
44 {}
45 
46 template <class InputStorageType, class OutputStorageType>
49 {}
50 
51 template <class InputStorageType, class OutputStorageType>
55 {
56  BIASCDOUT(D_FILTERBASE_CALLSTACK, "GradientGauss::Filter(src, gx, gy)\n");
57 
58  if ((fabs(this->_GradGaussSigma-this->_LastSigma)>=DBL_EPSILON) ||
59  (fabs(this->_GradGaussRatio-this->_LastRatio)>=DBL_EPSILON)){
60  _CalculateKernels(this->_GradGaussSigma, this->_GradGaussRatio);
61  }
62  if (!src.SamePixelAndChannelCount(gx)){
63  if (!gx.IsEmpty()) gx.Release();
64  gx.Init(src.GetWidth(), src.GetHeight(), src.GetChannelCount());
65  }
66  if (!src.SamePixelAndChannelCount(gy)){
67  if (!gy.IsEmpty()) gy.Release();
68  gy.Init(src.GetWidth(), src.GetHeight(), src.GetChannelCount());
69  }
70 
71  if (this->_Conv.Filter(src, gx)!=0) {
72  BIASERR("Error in gradient x computation...");
73  return -1;
74  }
75  FilterMask f;
76  this->_Conv.GetKernel(f);
77  f.Transpose();
78  this->_Conv.SetKernel(f);
79  int res = this->_Conv.Filter(src, gy);
80  f.Transpose();
81  this->_Conv.SetKernel(f);
82  return res;
83 }
84 
85 template <class InputStorageType, class OutputStorageType>
88 {
89  BIASCDOUT(D_FILTERBASE_CALLSTACK, "GradientGauss::Filter(src, dst)\n");
90 
92  int res = Filter(src, grad, gy);
93  grad.AppendChannel(gy);
94  return res;
95 }
96 
97 
98 template <class InputStorageType, class OutputStorageType>
104 {
105  BIASCDOUT(D_FILTERBASE_CALLSTACK,"GradientGauss::Filter(src, gx, gy, abs)\n");
106  if ((fabs(this->_GradGaussSigma-this->_LastSigma)>=DBL_EPSILON) ||
107  (fabs(this->_GradGaussRatio-this->_LastRatio)>=DBL_EPSILON)){
108  _CalculateKernels(this->_GradGaussSigma, this->_GradGaussRatio);
109  }
110  if (!src.SamePixelAndChannelCount(absg)){
111  if (!absg.IsEmpty()) absg.Release();
112  absg.Init(src.GetWidth(), src.GetHeight(), src.GetChannelCount());
113  }
114 
115  int res, absres=0;
116  res = Filter(src, gx, gy);
117  unsigned htlx, htly, hbrx, hbry, vtlx, vtly, vbrx, vbry;
118  gx.GetROI()->GetCorners(htlx, htly, hbrx, hbry);
119  gy.GetROI()->GetCorners(vtlx, vtly, vbrx, vbry);
120  const int minx=(htlx<vtlx)?vtlx:htlx;
121  const int miny=(htly<vtly)?vtly:htly;
122  const int maxx=(hbrx>vbrx)?vbrx:hbrx;
123  const int maxy=(hbry>vbry)?vbry:hbry;
124 
125  register int x, y;
126  register OutputStorageType **gxi=gx.GetImageDataArray();
127  register OutputStorageType **gyi=gy.GetImageDataArray();
128  register OutputStorageType **absi=absg.GetImageDataArray();
129 
130  int mgx, mgy;
131  for (y=miny; y<maxy; y++){
132  for (x=minx; x<maxx; x++){
133  mgx=(int)gxi[y][x];
134  mgy=(int)gyi[y][x];
135  absi[y][x]=(OutputStorageType) sqrt((double)(mgx)*(double)(mgx)+
136  (double)(mgy)*(double)(mgy));
137  }
138  }
139 
140  absg.GetROI()->SetCorners(minx, miny, maxx, maxy);
141 
142  return (res==0 && absres==0)?0:-1;
143 
144 }
145 
146 
147 template <class InputStorageType, class OutputStorageType>
149 _CalculateKernels(double Sigma, double Ratio)
150 {
151  /// \todo check if this is a proper filter mask in the
152  /// sense of convolution -> reflection at center. We
153  /// might have introduced an inconsistency here when switching
154  /// to generic convolution.
155  const double inv_max_gauss_deriv=1.0/(Sigma*expf(-0.5f));
156  BIASCDOUT(D_GRADGAUSS_KERNEL, "max_gauss_deriv = "
157  <<1.0/inv_max_gauss_deriv<<endl);
158  const double fac=1.0/(2.0*Sigma*Sigma);
159  const int vhws=(int)(floor(sqrt(-2.0*Sigma*Sigma*log(Ratio))));
160  int k;
161  for (k=vhws; k*expf((float)(-k*k*fac))*(float)inv_max_gauss_deriv>=Ratio; k++);
162  const int hhws=k-1;
163  const int vsize=(vhws<<1)+1;
164  const int hsize=(hhws<<1)+1;
165 
166  Vector<FM_FLOAT> H(hsize), V(vsize);
167 
168  BIASCDOUT(D_GRADGAUSS_KERNEL, "Sigma = "<<Sigma<<"\tRatio = "<<Ratio<<endl);
169  BIASCDOUT(D_GRADGAUSS_KERNEL, "vsize = "<<vsize<<"\tvhws = "<<vhws<<endl);
170  BIASCDOUT(D_GRADGAUSS_KERNEL, "hsize = "<<hsize<<"\thhws = "<<hhws<<endl);
171 
172  int i, ip, im;
173  register double g;
174  double sum=0.0, dsum=0.0;
175  // calculate the filter coefficients as gauss function
176  for (i=0; i<=vhws; i++){
177  ip=vhws+i;
178  im=vhws-i;
179  g=expf((float)(-(double)(i*i)*fac));
180  V[ip] = V[im] = (FM_FLOAT)g;
181  //BIASCDOUT(D_GRADGAUSS_KERNEL, i<<"v:"<<_VVec[im]<<" "<<endl);
182  sum+=g*2.0;
183  g=double(i)*g;
184  H[im] = (FM_FLOAT)g;
185  H[ip] = (FM_FLOAT)-g;
186  dsum += fabs(2.0*double(i)*g);
187  //BIASCDOUT(D_GRADGAUSS_KERNEL, i<<"h:"<<_HVec[im]<<" "<<endl);
188  }
189  for (i=vhws+1; i<=hhws; i++){
190  ip=hhws+i;
191  im=hhws-i;
192  g=double(i)*expf((float)(-(double)(i*i)*fac));
193  H[im]=(FM_FLOAT)g;
194  H[ip]=(FM_FLOAT)-g;
195  dsum+=fabs(2.0*double(i)*g);
196  //BIASCDOUT(D_GRADGAUSS_KERNEL, i<<"h:"<<_HVec[im]<<" "<<endl);
197  }
198 
199  sum-=1.0;
200  //BIASCDOUT(D_GRADGAUSS_KERNEL, "sum = "<<sum<<"\tdsum = "<<dsum<<endl);
201 
202  // normalize filter, so that the sum is 1.0
203  sum = 1.0/sum;
204  dsum = 1.0/dsum;
205  //BIASCDOUT(D_GRADGAUSS_KERNEL, "sum = "<<sum<<"\tdsum = "<<dsum<<endl);
206  for (i=0; i<=vhws; i++){
207  ip=vhws+i;
208  im=vhws-i;
209  H[ip]*=(float)dsum;
210  H[im]*=(float)dsum;
211  V[ip] = V[im] = V[im]*(float)sum;
212  }
213  for (i=vhws+1; i<=hhws; i++){
214  ip=hhws+i;
215  im=hhws-i;
216  H[ip] *= (float)dsum;
217  H[im] *= (float)dsum;
218  }
219  this->_LastSigma=Sigma;
220  this->_LastRatio=Ratio;
221  FilterMask F(H,V);
222  // compute the int approximation
223  int thebits = F.ComputeIntPrecisionBits(sizeof(InputStorageType)*8,
224  sizeof(CONV_INT)*8-1);
225  F.CreateIntFilter(thebits,thebits,thebits);
226  this->_Conv.SetKernel(F);
227 
228 #ifdef BIAS_DEBUG
229  sum=dsum=0.0;
230  for (i=-hhws; i<=hhws; i++){
231  sum += H[i+hhws];
232  BIASCDOUT(D_GRADGAUSS_KERNEL,H[i+hhws]<<" ");
233  }
234  BIASCDOUT(D_GRADGAUSS_KERNEL, " sum = "<<sum<<endl);
235  for (i=-vhws; i<=vhws; i++){
236  dsum += V[i+vhws];
237  BIASCDOUT(D_GRADGAUSS_KERNEL, V[i+vhws]<<" ");
238  }
239  BIASCDOUT(D_GRADGAUSS_KERNEL, " sum = "<<dsum<<endl);
240 #endif
241 
242  //#define COMPARE
243 #ifdef COMPARE
244  fprintf(stdout, "gauss: \n");
245  for (i=-hhws; i<=hhws; i++){
246  fprintf(stdout, "%f ",H[i+hhws]);
247  }
248  fprintf(stdout, "\n");
249  fprintf(stdout, "gaussderiv: \n");
250  for (i=-vhws; i<=vhws; i++){
251  fprintf(stdout, "%f ",V[i+vhws]);
252  }
253  fprintf(stdout, "\n");
254 #endif
255 
256 }
257 
258 //////////////////////////////////////////////////////////////////////////
259 // instantiation
260 //////////////////////////////////////////////////////////////////////////
261 namespace BIAS{
262 #define FILTER_INSTANTIATION_CLASS GradientGaussAsymmetric
263 #define FILTER_INSTANTIATION_NO_UNSIGNED_OUTPUT
264 #include "Filterinst.hh"
265 }
void Release()
reimplemented from ImageBase
Definition: Image.cpp:1579
gradient calculation with separated gauss masks
void CreateIntFilter(int rshift, int rshifth, int rshiftv)
create the int filter from the float filter
Definition: FilterMask.cpp:113
void _CalculateKernels(double Sigma, double Ratio)
Fills _HVec with gaussian function and _VVec with derivative of gaussian function with standard devia...
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
virtual int Filter(const Image< InputStorageType > &src, Image< OutputStorageType > &grad)
returns a 2 channel image containing gx and gy
void Transpose()
transposes the kernel (and adapts all dependent data)
Definition: FilterMask.cpp:197
int AppendChannel(Image< StorageType > &img)
Definition: Image.cpp:1457
unsigned int GetWidth() const
Definition: ImageBase.hh:312
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
unsigned int GetHeight() const
Definition: ImageBase.hh:319
int ComputeIntPrecisionBits(int NumberOfBitsInInputData, int NumberOfBitsInTempData)
compute the number of shiftable bits for int-from-float mask
Definition: FilterMask.cpp:211
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
gradient calculation with separated gauss masks
A filter mask (or a kernel) used for convolution.
Definition: FilterMask.hh:61
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase
Definition: Image.hh:153