26 #include "GradientSobel3x3.hh"
27 #include "FilterMask.hh"
35 template <
class InputStorageType,
class OutputStorageType>
void
55 template <
class InputStorageType,
class OutputStorageType>
58 :
FilterNTo2N<InputStorageType, OutputStorageType>()
66 template <
class InputStorageType,
class OutputStorageType>
71 _fwork = _fwork2 = NULL;
72 _iwork = _iwork2 = NULL;
73 _InternalMemWidth = _InternalMemHeight = 0;
76 template <
class InputStorageType,
class OutputStorageType>
84 template <
class InputStorageType,
class OutputStorageType>
88 BIASCDOUT(D_FILTERBASE_CALLSTACK,
"GradientSobel3x3::Filter(src, dst)\n");
90 int res=Filter(src, grad, gy);
95 template <
class InputStorageType,
class OutputStorageType>
100 BIASCDOUT(D_FILTERBASE_CALLSTACK,
"GradientSobel3x3::Filter(src, gx, gy)\n");
112 if (_InternalMemWidth < (
int)src.
GetWidth() ||
113 _InternalMemHeight < (int)src.
GetHeight() ) _DeleteInternalMem();
114 if (_Conv.CalculationInFloat()){
116 switch (this->_FilterBorderHandling){
118 res = Sobel3x3GreyValidFloat_(src, gx, gy);
121 res = Sobel3x3GreySameFloat_(src, gx, gy);
124 BIASERR(
"unfinished");
130 res = Sobel3x3GreyValidInt_(src, gx, gy);
134 BIASERR(
"not for multiple channel images");
157 template <
class InputStorageType,
class OutputStorageType>
162 BIASCDOUT(D_FILTERBASE_CALLSTACK,
"GradientSobel3x3::Filter(src, gx, gy, abs)\n");
169 res = Filter(src, gx, gy);
171 absres = this->VecLen(gx, gy, absg);
173 ShrinkROI_(absg.
GetROI());
175 return (res==0 && absres==0)?0:-1;
181 template <
class InputStorageType,
class OutputStorageType>
187 BIASCDOUT(D_FILTERBASE_CALLSTACK,
"GradientSobel3x3::Sobel3x3GreyValidFloat_\n");
191 const int width=(int)src.
GetWidth();
192 const int nwidth = - width;
200 BIASASSERT(_Conv.CalculationInFloat());
203 if (width>this->_InternalMemWidth || height>this->_InternalMemHeight){
204 this->_DeleteInternalMem();
205 this->_AllocInternalMem(width, height);
208 int minx, miny, maxx, maxy;
213 const InputStorageType *end, *p, *lend;
216 OutputStorageType *pgx, *pgy, *end2, *lend2;
217 CONV_FLOAT tmp, tmpx, tmpy;
218 int roiw=maxx-minx-1;
219 int step=width-maxx+minx;
224 offset=minx+miny*width;
226 ph=this->_fwork[0]+1+offset;
227 pv=this->_fwork2[0]+offset+width;
230 tmp = (CONV_FLOAT(*p))*2.0f;
231 *ph++ = CONV_FLOAT(p[-1]) + tmp + CONV_FLOAT(p[1]);
237 end=im+maxx-1+(maxy-2)*width;
239 tmp = (CONV_FLOAT(*p))*2.0f;
240 *pv++ = CONV_FLOAT(p[nwidth]) + tmp + CONV_FLOAT(p[width]);
244 tmp = (CONV_FLOAT(*p))*2.0f;
245 *ph++ = CONV_FLOAT(p[-1]) + tmp + CONV_FLOAT(p[1]);
246 *pv++ = CONV_FLOAT(p[nwidth]) + tmp + CONV_FLOAT(p[width]);
249 tmp = (CONV_FLOAT(*p))*2.0f;
250 *pv++ = CONV_FLOAT(p[nwidth]) + tmp + CONV_FLOAT(p[width]);
261 tmp = (CONV_FLOAT(*p))*2.0f;
262 *ph++ = CONV_FLOAT(p[-1]) + tmp + CONV_FLOAT(p[1]);
268 offset=minx+1+(miny+1)*width;
269 ph=this->_fwork[0]+offset;
270 pv=this->_fwork2[0]+offset;
274 end2=gx+maxx+width*(maxy-2)-1;
275 lend2=gx+maxx+width*(miny+1)-1;
278 tmpx = (pv[1] - pv[-1])/8.0f;
279 tmpy = (ph[width] - ph[nwidth])/8.0f;
280 *pgx++ = (OutputStorageType)tmpx;
281 *pgy++ = (OutputStorageType)tmpy;
294 template <
class InputStorageType,
class OutputStorageType>
300 BIASCDOUT(D_FILTERBASE_CALLSTACK,
"GradientSobel3x3::Sobel3x3GreySameFloat_\n");
302 res = Sobel3x3GreyValidFloat_(src, gWE, gNS);
304 int minx, miny, maxx, maxy;
306 register int x, y, xp, xm, yp, ym;
320 OutputStorageType((
float(srcida[ym][xp])-
float(srcida[ym][xm])+
321 2.0*(
float(srcida[y][xp])-
float(srcida[y][xm]))+
322 float(srcida[yp][xp])-
float(srcida[yp][xm]))/8.0);
324 OutputStorageType((
float(srcida[yp][xm])-
float(srcida[ym][xm])+
325 2.0*(
float(srcida[yp][x])-
float(srcida[ym][x]))+
326 float(srcida[yp][xp])-
float(srcida[ym][xp]))/8.0);
336 OutputStorageType((
float(srcida[ym][xp])-
float(srcida[ym][xm])+
337 2.0*(
float(srcida[y][xp])-
float(srcida[y][xm]))+
338 float(srcida[yp][xp])-
float(srcida[yp][xm]))/8.0);
340 OutputStorageType((
float(srcida[yp][xm])-
float(srcida[ym][xm])+
341 2.0*(
float(srcida[yp][x])-
float(srcida[ym][x]))+
342 float(srcida[yp][xp])-
float(srcida[ym][xp]))/8.0);
352 OutputStorageType((
float(srcida[ym][xp])-
float(srcida[ym][xm])+
353 2.0*(
float(srcida[y][xp])-
float(srcida[y][xm]))+
354 float(srcida[yp][xp])-
float(srcida[yp][xm]))/8.0);
356 OutputStorageType((
float(srcida[yp][xm])-
float(srcida[ym][xm])+
357 2.0*(
float(srcida[yp][x])-
float(srcida[ym][x]))+
358 float(srcida[yp][xp])-
float(srcida[ym][xp]))/8.0);
368 OutputStorageType((
float(srcida[ym][xp])-
float(srcida[ym][xm])+
369 2.0*(
float(srcida[y][xp])-
float(srcida[y][xm]))+
370 float(srcida[yp][xp])-
float(srcida[yp][xm]))/8.0);
372 OutputStorageType((
float(srcida[yp][xm])-
float(srcida[ym][xm])+
373 2.0*(
float(srcida[yp][x])-
float(srcida[ym][x]))+
374 float(srcida[yp][xp])-
float(srcida[ym][xp]))/8.0);
379 for (x=minx+1; x<maxx-1; x++){
383 OutputStorageType((2.0*(
float(srcida[y][xp])-
float(srcida[y][xm]))+
384 float(srcida[yp][xp])-
float(srcida[yp][xm]))/6.0);
386 OutputStorageType((2.0*(
float(srcida[yp][x])-
float(srcida[y][x]))+
387 float(srcida[yp][xp])+
float(srcida[yp][xm])-
388 float(srcida[y][xp])-
float(srcida[y][xm]))/8.0);
393 for (x=minx+1; x<maxx-1; x++){
397 OutputStorageType((2.0*(
float(srcida[y][xp])-
float(srcida[y][xm]))+
398 float(srcida[ym][xp])-
float(srcida[ym][xm]))/6.0);
400 OutputStorageType((2.0*(
float(srcida[y][x])-
float(srcida[ym][x]))-
401 float(srcida[ym][xp])-
float(srcida[ym][xm])+
402 float(srcida[y][xp])+
float(srcida[y][xm]))/8.0);
407 for (y=miny+1; y<maxy-1; y++){
411 OutputStorageType((2.0*(
float(srcida[y][xp])-
float(srcida[y][x]))+
412 float(srcida[ym][xp])+
float(srcida[yp][xp])-
413 float(srcida[ym][x])-
float(srcida[yp][x]))/8.0);
415 OutputStorageType((2.0*(
float(srcida[yp][x])-
float(srcida[ym][x]))+
416 float(srcida[yp][xp])-
float(srcida[ym][xp]))/6.0);
422 for (y=miny+1; y<maxy-1; y++){
426 OutputStorageType((2.0*(
float(srcida[y][x])-
float(srcida[y][xm]))-
427 float(srcida[ym][xm])-
float(srcida[yp][xm])+
428 float(srcida[ym][x])+
float(srcida[yp][x]))/8.0);
430 OutputStorageType((2.0*(
float(srcida[yp][x])-
float(srcida[ym][x]))+
431 float(srcida[yp][xm])-
float(srcida[ym][xm]))/6.0);
440 template <
class InputStorageType,
class OutputStorageType>
446 BIASCDOUT(D_FILTERBASE_CALLSTACK,
"GradientSobel3x3::Sobel3x3GreyValidInt_\n");
450 const int width=(int)src.
GetWidth();
451 const int nwidth = - width;
459 BIASASSERT(!_Conv.CalculationInFloat());
462 if (width>this->_InternalMemWidth || height>this->_InternalMemHeight){
463 this->_DeleteInternalMem();
464 this->_AllocInternalMem(width, height);
467 int minx, miny, maxx, maxy;
472 const InputStorageType *end, *p, *lend;
475 OutputStorageType *pgx, *pgy, *end2, *lend2;
476 CONV_INT tmp, tmpx, tmpy;
477 int roiw=maxx-minx-1;
478 int step=width-maxx+minx;
483 offset=minx+miny*width;
485 ph=this->_iwork[0]+1+offset;
486 pv=this->_iwork2[0]+offset+width;
489 tmp = (CONV_INT(*p))<<1;
490 *ph++ = CONV_INT(p[-1]) + tmp + CONV_INT(p[1]);
496 end=im+maxx-1+(maxy-2)*width;
498 tmp = (CONV_INT(*p))<<1;
499 *pv++ = CONV_INT(p[nwidth]) + tmp + CONV_INT(p[width]);
503 tmp = (CONV_INT(*p))<<1;
504 *ph++ = CONV_INT(p[-1]) + tmp + CONV_INT(p[1]);
505 *pv++ = CONV_INT(p[nwidth]) + tmp + CONV_INT(p[width]);
508 tmp = (CONV_INT(*p))<<1;
509 *pv++ = CONV_INT(p[nwidth]) + tmp + CONV_INT(p[width]);
520 tmp = (CONV_INT(*p))<<1;
521 *ph++ = CONV_INT(p[-1]) + tmp + CONV_INT(p[1]);
527 offset=minx+1+(miny+1)*width;
528 ph=this->_iwork[0]+offset;
529 pv=this->_iwork2[0]+offset;
533 end2=gx+maxx+width*(maxy-2)-1;
534 lend2=gx+maxx+width*(miny+1)-1;
537 tmpx = (pv[1] - pv[-1])>>3;
538 tmpy = (ph[width] - ph[nwidth])>>3;
539 *pgx++ = (OutputStorageType)tmpx;
540 *pgy++ = (OutputStorageType)tmpy;
554 template <
class InputStorageType,
class OutputStorageType>
558 if (this->_fwork!=NULL) {
559 delete[] this->_fwork[0]; this->_fwork[0]=NULL;
560 delete[] this->_fwork; this->_fwork=NULL;
563 delete[] _fwork2[0]; _fwork2[0]=NULL;
564 delete[] _fwork2; _fwork2=NULL;
566 if (this->_iwork!=NULL) {
567 delete[] this->_iwork[0]; this->_iwork[0]=NULL;
568 delete[] this->_iwork; this->_iwork=NULL;
571 delete[] _iwork2[0]; _iwork2[0]=NULL;
572 delete[] _iwork2; _iwork2=NULL;
574 this->_InternalMemWidth=this->_InternalMemHeight=0;
577 template <
class InputStorageType,
class OutputStorageType>
582 if ((this->_fwork!=NULL) || (_fwork2!=NULL) ||
583 (this->_iwork!=NULL) || (_iwork2!=NULL)){
584 BIASERR(
"memory leak, reallocating without deleting!");
588 int size=width*height;
590 if (_Conv.CalculationInFloat()){
591 this->_fwork =
new CONV_FLOAT*[height];
592 this->_fwork[0] =
new CONV_FLOAT[size];
593 _fwork2 =
new CONV_FLOAT*[height];
594 _fwork2[0] =
new CONV_FLOAT[size];
595 for (
int i=1; i<height; i++) {
596 this->_fwork[i]=this->_fwork[i-1]+width;
597 _fwork2[i]=_fwork2[i-1]+width;
600 this->_iwork =
new CONV_INT*[height];
601 this->_iwork[0] =
new CONV_INT[size];
602 _iwork2 =
new CONV_INT*[height];
603 _iwork2[0] =
new CONV_INT[size];
604 for (
int i=1; i<height; i++) {
605 this->_iwork[i]=this->_iwork[i-1]+width;
606 _iwork2[i]=_iwork2[i-1]+width;
610 this->_InternalMemWidth=width;
611 this->_InternalMemHeight=height;
614 template <
class InputStorageType,
class OutputStorageType>
618 border_x = border_y = 1;
621 template <
class InputStorageType,
class OutputStorageType>
629 unsigned UpperLeftX, UpperLeftY, LowerRightX, LowerRightY;
630 roi->
GetCorners(UpperLeftX, UpperLeftY, LowerRightX, LowerRightY);
636 BIASERR(
"should not happen"); BIASABORT;
641 BIASERR(
"should not happen"); BIASABORT;
643 roi->
SetCorners(UpperLeftX, UpperLeftY, LowerRightX, LowerRightY);
648 vector<unsigned> start, end;
649 if (!roi->
GetRows(start, end)){
650 BIASERR(
"should not happen"); BIASABORT;
652 BIASASSERT(start.size()==end.size());
653 for (
unsigned y=0; y<start.size(); y++){
654 if (start[y]!=0 || end[y]!=0){
659 BIASERR(
"should not happen"); BIASABORT;
668 BIASERR(
"GradientSobel3x3::ShrinkROI_() unhandled ROI type: "
679 #define FILTER_INSTANTIATION_CLASS GradientSobel3x3
680 #define FILTER_INSTANTIATION_NO_UNSIGNED_OUTPUT
681 #include "Filterinst.hh"
void Release()
reimplemented from ImageBase
class for handling different region of interest (ROI) representations...
enum ERoiType GetROIType() const
is the mask image valid?
void ShrinkROI_(ROI *roi) const
generic convolution class.
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
void InitKernel_()
sets the sobel kernel for the convolution object
int AppendChannel(Image< StorageType > &img)
base class for simple n->2n filter implementations
void CreateFloatFilter()
create the float filter from the int filter
void _DeleteInternalMem()
gradient calculation with sobel 3 by 3 masks
unsigned int GetWidth() const
int Sobel3x3GreyValidInt_(const Image< InputStorageType > &src, Image< OutputStorageType > &gWE, Image< OutputStorageType > &gNS)
uses CONV_INT for calculation
int Sobel3x3GreyValidFloat_(const Image< InputStorageType > &src, Image< OutputStorageType > &gWE, Image< OutputStorageType > &gNS)
uses CONV_FLOAT for calculation
ROI * GetROI()
Returns a pointer to the roi object.
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
unsigned int GetHeight() const
bool GetRows(std::vector< unsigned > &start, std::vector< unsigned > &end) const
Horizontal start and end position per image row, the length of the vectors always corresponds to the ...
bool SamePixelAndChannelCount(const ImageBase &Image) const
checks if data area has same "size" as Image of other type
int SetROI(unsigned int UpperLeftX, unsigned int UpperLeftY, unsigned int LowerRightX, unsigned int LowerRightY)
deprecated, use SetROICorners()
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
void _AllocInternalMem(const int width, const int height)
deletes _work1 and _work2 and sets _InternalMemSize
virtual void GetBordersValid_(int &border_x, int &border_y) const
virtual ~GradientSobel3x3()
virtual int Filter(const Image< InputStorageType > &src, Image< OutputStorageType > &grad)
returns a 2 channel image containing gx and gy
int Sobel3x3GreySameFloat_(const Image< InputStorageType > &src, Image< OutputStorageType > &gWE, Image< OutputStorageType > &gNS)
Repeats the border pixel infinitly in direction perpendicular to the border to achieve destination im...
A filter mask (or a kernel) used for convolution.
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase