25 #include "Binomial.hh"
28 #include <Base/Image/ImageIO.hh>
31 #include <Base/Common/BIASpragma.hh>
40 template <
class InputStorageType,
class OutputStorageType>
43 :
Convolution<InputStorageType, OutputStorageType>()
52 template <
class InputStorageType,
class OutputStorageType>
55 : _HalfWinSize(other._HalfWinSize),
56 _LastHalfWinSize(other._LastHalfWinSize)
60 template <
class StorageType,
class KernelType>
67 template <
class InputStorageType,
class OutputStorageType>
71 BIASCDOUT(D_FILTERBASE_CALLSTACK,
"Binomial::Filter\n");
75 switch (_HalfWinSize){
77 res = Filter3x3(src, dst);
80 res = Filter5x5(src, dst);
83 if ((_HalfWinSize != _LastHalfWinSize))
84 _CalculateKernel(_HalfWinSize);
92 template <
class InputStorageType,
class OutputStorageType>
95 BIASERR(
"Unsupported interface, use Filter");
96 return Filter(src, dst);
99 template <
class InputStorageType,
class OutputStorageType>
102 BIASERR(
"Unsupported interface, use Filter");
103 return Filter(src, dst);
107 template <
class InputStorageType,
class OutputStorageType>
111 BIASCDOUT(D_FILTERBASE_CALLSTACK,
"Binomial::Filter3x3\n");
118 if (this->CalculationInFloat()){
119 switch (_FilterBorderHandling){
121 res = Filter3x3ValidGreyFloat(src, dst);
124 res = Filter3x3SameGreyFloat(src, dst);
127 BIASERR(
"unfinished");
142 template <
class InputStorageType,
class OutputStorageType>
146 BIASCDOUT(D_FILTERBASE_CALLSTACK,
"Binomial::Filter5x5\n");
153 if (this->CalculationInFloat()){
154 switch (_FilterBorderHandling){
156 res = Filter5x5ValidGreyFloat(src, dst);
159 BIASERR(
"Binomial::Filter5x5: border handling unfinished, "
161 res = Filter5x5ValidGreyFloat(src, dst);
165 BIASASSERT(
"unfinished");
176 template <
class InputStorageType,
class OutputStorageType>
181 BIASCDOUT(D_FILTERBASE_CALLSTACK,
"Binomial::Filter3x3ValidGreyFloat\n");
187 const unsigned width=src.
GetWidth();
188 int nwidth = - int(width);
191 unsigned minx, miny, maxx, maxy;
195 if (width>_tmpFloat.GetWidth() ||
196 height>_tmpFloat.GetHeight()){
197 if (!_tmpFloat.IsEmpty()) _tmpFloat.Release();
202 const InputStorageType *p, *end, *lend;
203 OutputStorageType *pg, *oend, *olend;
208 offset=(int)minx+(
int)miny*(int)width+1;
210 ph=_tmpFloat.GetImageData()+offset;
211 step=width-(int)maxx+(
int)minx+2;
212 end=im+(int)maxx+((
int)maxy-1)*(
int)width-1;
213 lend=im+(int)maxx+((
int)miny*(int)width)-1;
217 *ph++ = (CONV_FLOAT)(p[-1]) +(CONV_FLOAT)(*p) * 2.0f + (CONV_FLOAT)(p[1]);
226 if (this->DebugLevelIsSet(D_BINOMIAL_WRITE_IM)){
235 offset=(int)minx+((
int)miny+1)*(
int)width+1;
236 ph=_tmpFloat.GetImageData()+offset;
239 oend=s+(int)maxx+((
int)maxy-2)*(
int)width-1;
240 olend=s+(int)maxx+((
int)miny+1)*(
int)width-1;
241 CONV_FLOAT div = 1.0 / 16.0;
245 tmp = ph[nwidth] + *ph * 2.0f + ph[width];
246 *pg++ = (OutputStorageType)(tmp * div);
254 if (this->DebugLevelIsSet(D_BINOMIAL_WRITE_IM)){
263 template <
class InputStorageType,
class OutputStorageType>
268 BIASCDOUT(D_FILTERBASE_CALLSTACK,
"Binomial::Filter3x3SameGreyFloat\n");
271 res = Filter3x3ValidGreyFloat(src, dst);
277 int minx, miny, maxx, maxy;
279 register int x, y, xp, xm, yp, ym;
290 OutputStorageType((4.0*
float(srcida[y][x])+
291 2.0*(
float(srcida[y][xp])+
float(srcida[yp][x]))+
292 float(srcida[yp][xp]))/9.0);
300 OutputStorageType((4.0*
float(srcida[y][x])+
301 2.0*(
float(srcida[y][xm])+
float(srcida[yp][x]))+
302 float(srcida[yp][xm]))/9.0);
310 OutputStorageType((4.0*
float(srcida[y][x])+
311 2.0*(
float(srcida[y][xm])+
float(srcida[ym][x]))+
312 float(srcida[ym][xm]))/9.0);
320 OutputStorageType((4.0*
float(srcida[y][x])+
321 2.0*(
float(srcida[y][xp])+
float(srcida[ym][x]))+
322 float(srcida[ym][xp]))/9.0);
329 for (x=minx+1; x<maxx-1; x++){
333 OutputStorageType((4.0*
float(srcida[y][x])+
334 2.0*(
float(srcida[y][xm])+
float(srcida[y][xp])+
335 float(srcida[yp][x]))+
336 float(srcida[yp][xp])+
float(srcida[yp][xm]))/12.0);
341 for (x=minx+1; x<maxx-1; x++){
345 OutputStorageType((4.0*
float(srcida[y][x])+
346 2.0*(
float(srcida[y][xm])+
float(srcida[y][xp])+
347 float(srcida[ym][x]))+
348 float(srcida[ym][xp])+
float(srcida[ym][xm]))/12.0);
353 for (y=miny+1; y<maxy-1; y++){
357 OutputStorageType((4.0*
float(srcida[y][x])+
358 2.0*(
float(srcida[ym][x])+
float(srcida[yp][x])+
359 float(srcida[y][xp]))+
360 float(srcida[ym][xp])+
float(srcida[yp][xp]))/12.0);
366 for (y=miny+1; y<maxy-1; y++){
370 OutputStorageType((4.0*
float(srcida[y][x])+
371 2.0*(
float(srcida[ym][x])+
float(srcida[yp][x])+
372 float(srcida[y][xm]))+
373 float(srcida[ym][xm])+
float(srcida[yp][xm]))/12.0);
381 template <
class InputStorageType,
class OutputStorageType>
386 BIASCDOUT(D_FILTERBASE_CALLSTACK,
"Binomial::Filter5x5ValidGrey\n");
392 const unsigned width=src.
GetWidth();
393 int nwidth = - int(width);
396 unsigned minx, miny, maxx, maxy;
401 if (width>_tmpFloat.GetWidth() ||
402 height>_tmpFloat.GetHeight()){
403 if (!_tmpFloat.IsEmpty()) _tmpFloat.Release();
408 const InputStorageType *p, *end, *lend;
409 OutputStorageType *pg, *oend, *olend;
413 offset=(int)minx+(
int)miny*(int)width+2;
415 ph=_tmpFloat.GetImageData()+offset;
416 step=width-(int)maxx+(
int)minx+4;
417 end=im+(int)maxx+((
int)maxy-1)*(
int)width-2;
418 lend=im+(int)maxx+((
int)miny*(int)width)-2;
422 *ph++ = (CONV_FLOAT)(p[-2]) + (CONV_FLOAT)(p[-1])*4.0f + (CONV_FLOAT)(*p)
423 * 6.0f + (CONV_FLOAT)(p[+1])*4.0f + (CONV_FLOAT)(p[2]);
432 if (this->DebugLevelIsSet(D_BINOMIAL_WRITE_IM)){
441 offset=(int)minx+((
int)miny+2)*(
int)width+2;
442 ph=_tmpFloat.GetImageData()+offset;
445 oend=s+(int)maxx+((
int)maxy-3)*(
int)width-2;
446 olend=s+(int)maxx+((
int)miny+2)*(
int)width-2;
448 CONV_FLOAT div = 1.0 / 256.0;
452 tmp = ph[-dw] + ph[dw] + ph[nwidth]*4.0f + ph[width]*4.0f + (*ph)*6.0f;
453 *pg++ = (OutputStorageType)(tmp * div);
462 if (this->DebugLevelIsSet(D_BINOMIAL_WRITE_IM)){
473 template <
class StorageType,
class KernelType>
479 const int size=(HalfWinSize<<1)+1;
481 vec[0]=vec[size-1]=1;
483 int numerator=size-1, denominator=1;
484 for (
int i=1; i<=HalfWinSize; i++){
485 vec[i]=vec[size-i-1]=(numerator/denominator);
486 BIASCDOUT(D_BINOMIAL_KERNEL,
"num "<<numerator<<
" denom "<<denominator
487 <<
" = "<<vec[i]<<endl);
489 numerator*=(size-i-1);
491 shift=(HalfWinSize<<1);
493 BIASCDOUT(D_BINOMIAL_KERNEL,
"size "<<size<<
" : "<< vec <<
" shift "
494 <<shift<<endl<<
"-------------\n");
496 _fm.Init(vec, vec, 0, shift*shift,
true);
497 BIASCDOUT(D_BINOMIAL_KERNEL,
"filter mask (int): "<<_fm<<endl);
498 _fm.CreateFloatFilter();
499 BIASCDOUT(D_BINOMIAL_KERNEL,
"filter mask (float): "<<_fm<<endl);
500 _LastHalfWinSize = HalfWinSize;
503 template <
class StorageType,
class KernelType>
507 border_x = border_y = _HalfWinSize;
515 #define FILTER_INSTANTIATION_CLASS Binomial
516 #include "Filterinst.hh"
void Release()
reimplemented from ImageBase
generic convolution class.
virtual int FilterFloat(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
no implementation, calls Filter
int SetCorners(unsigned UpperLeftX, unsigned UpperLeftY, unsigned LowerRightX, unsigned LowerRightY)
Sets a rectangular region of interest.
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...
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
int Filter3x3SameGreyFloat(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
specialized function for convolution with 3x3 binomial filter.
virtual int Filter(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
decides on the image types which FilterFunction should be called
int Filter3x3ValidGreyFloat(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
specialized function for convolution with 3x3 binomial filter.
int Filter5x5(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
unsigned int GetWidth() const
Vector< T > & newsize(Subscript N)
ROI * GetROI()
Returns a pointer to the roi object.
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
virtual int FilterInt(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
no implementation, calls Filter
unsigned int GetHeight() const
bool SamePixelAndChannelCount(const ImageBase &Image) const
checks if data area has same "size" as Image of other type
static int Save(const std::string &filename, const ImageBase &img, const enum TFileFormat FileFormat=FF_auto, const bool sync=BIAS_DEFAULT_SYNC, const int c_jpeg_quality=BIAS_DEFAULT_IMAGE_QUALITY, const bool forceNewID=BIAS_DEFAULT_FORCENEWID, const bool &writeMetaData=true)
Export image as file using extrnal libs.
int Filter3x3(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
virtual int Filter(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
sets kernel if params changed and calls convolution
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
const StorageType * GetImageData() const
overloaded GetImageData() from ImageBase
virtual void GetBordersValid_(int &border_x, int &border_y) const
binomial low pass filter class
int Filter5x5ValidGreyFloat(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
specialized function for convolution with 5x5 binomial filter.
int _HalfWinSize
the parameter
void _CalculateKernel(int HalfWinSize)
calculates the kernel
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase