/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /*$Id: db_feature_detection.cpp,v 1.4 2011/06/17 14:03:30 mbansal Exp $*/ /***************************************************************** * Lean and mean begins here * *****************************************************************/ #include "db_utilities.h" #include "db_feature_detection.h" #ifdef _VERBOSE_ #include #endif #include #define DB_SUB_PIXEL #define BORDER 10 // 5 float** db_AllocStrengthImage_f(float **im,int w,int h) { int i,n,aw; long c,size; float **img,*aim,*p; /*Determine number of 124 element chunks needed*/ n=(db_maxi(1,w-6)+123)/124; /*Determine the total allocation width aw*/ aw=n*124+8; /*Allocate*/ size=aw*h+16; *im=new float [size]; /*Clean up*/ p=(*im); for(c=0;c>1; Iy=(img[i-1][j+c]-img[i+1][j+c])>>1; dxx[c]=Ix*Ix; dxx[c+128]=Ix*Iy; dxx[c+256]=Iy*Iy; } #endif /*DB_USE_MMX*/ } /*Filter vertically five rows of derivatives of length chunk_width into gxx,gxy,gyy*/ inline void db_gxx_gxy_gyy_row_f(float *gxx,float *gxy,float *gyy,int chunk_width, float *Ix0,float *Ix1,float *Ix2,float *Ix3,float *Ix4, float *Iy0,float *Iy1,float *Iy2,float *Iy3,float *Iy4) { int c; float dx,dy; float Ixx0,Ixy0,Iyy0,Ixx1,Ixy1,Iyy1,Ixx2,Ixy2,Iyy2,Ixx3,Ixy3,Iyy3,Ixx4,Ixy4,Iyy4; for(c=0;clast) right=last; /*Compute the Harris strength of a chunk*/ db_HarrisStrengthChunk_f(s,img,x,3,right,h-4,temp); } } /*Compute Harris corner strength of img. Strength is returned for the region with (3,3) as upper left and (w-4,h-4) as lower right, positioned in the same place in s. In other words,image should be at least 7 pixels wide and 7 pixels high for a meaningful result.Moreover, the image should be overallocated by 256 bytes. s[i][3] should by 16 byte aligned for any i*/ void db_HarrisStrength_u(float **s, const unsigned char * const *img,int w,int h, /*temp should point to at least 18*128 of allocated memory*/ int *temp) { int x,next_x,last; int nc; last=w-4; for(x=3;x<=last;x=next_x) { next_x=x+124; // mayban: to revert to the original full chunks state, change the line below to: nc = 128; nc = db_mini(128,last-x+1); //nc = 128; /*Compute the Harris strength of a chunk*/ db_HarrisStrengthChunk_u(s,img,x,3,h-4,temp,nc); } } inline float db_Max_128Aligned16_f(float *v) { #ifdef DB_USE_SIMD float back; _asm { mov eax,v /*Chunk1*/ movaps xmm0,[eax] movaps xmm1,[eax+16] movaps xmm2,[eax+32] movaps xmm3,[eax+48] movaps xmm4,[eax+64] movaps xmm5,[eax+80] movaps xmm6,[eax+96] movaps xmm7,[eax+112] /*Chunk2*/ maxps xmm0,[eax+128] maxps xmm1,[eax+144] maxps xmm2,[eax+160] maxps xmm3,[eax+176] maxps xmm4,[eax+192] maxps xmm5,[eax+208] maxps xmm6,[eax+224] maxps xmm7,[eax+240] /*Chunk3*/ maxps xmm0,[eax+256] maxps xmm1,[eax+272] maxps xmm2,[eax+288] maxps xmm3,[eax+304] maxps xmm4,[eax+320] maxps xmm5,[eax+336] maxps xmm6,[eax+352] maxps xmm7,[eax+368] /*Chunk4*/ maxps xmm0,[eax+384] maxps xmm1,[eax+400] maxps xmm2,[eax+416] maxps xmm3,[eax+432] maxps xmm4,[eax+448] maxps xmm5,[eax+464] maxps xmm6,[eax+480] maxps xmm7,[eax+496] /*Collect*/ maxps xmm0,xmm1 maxps xmm2,xmm3 maxps xmm4,xmm5 maxps xmm6,xmm7 maxps xmm0,xmm2 maxps xmm4,xmm6 maxps xmm0,xmm4 movhlps xmm1,xmm0 maxps xmm0,xmm1 shufps xmm1,xmm0,1 maxps xmm0,xmm1 movss back,xmm0 } return(back); #else float val,max_val; float *p,*stop_p; max_val=v[0]; for(p=v+1,stop_p=v+128;p!=stop_p;) { val= *p++; if(val>max_val) max_val=val; } return(max_val); #endif /*DB_USE_SIMD*/ } inline float db_Max_64Aligned16_f(float *v) { #ifdef DB_USE_SIMD float back; _asm { mov eax,v /*Chunk1*/ movaps xmm0,[eax] movaps xmm1,[eax+16] movaps xmm2,[eax+32] movaps xmm3,[eax+48] movaps xmm4,[eax+64] movaps xmm5,[eax+80] movaps xmm6,[eax+96] movaps xmm7,[eax+112] /*Chunk2*/ maxps xmm0,[eax+128] maxps xmm1,[eax+144] maxps xmm2,[eax+160] maxps xmm3,[eax+176] maxps xmm4,[eax+192] maxps xmm5,[eax+208] maxps xmm6,[eax+224] maxps xmm7,[eax+240] /*Collect*/ maxps xmm0,xmm1 maxps xmm2,xmm3 maxps xmm4,xmm5 maxps xmm6,xmm7 maxps xmm0,xmm2 maxps xmm4,xmm6 maxps xmm0,xmm4 movhlps xmm1,xmm0 maxps xmm0,xmm1 shufps xmm1,xmm0,1 maxps xmm0,xmm1 movss back,xmm0 } return(back); #else float val,max_val; float *p,*stop_p; max_val=v[0]; for(p=v+1,stop_p=v+64;p!=stop_p;) { val= *p++; if(val>max_val) max_val=val; } return(max_val); #endif /*DB_USE_SIMD*/ } inline float db_Max_32Aligned16_f(float *v) { #ifdef DB_USE_SIMD float back; _asm { mov eax,v /*Chunk1*/ movaps xmm0,[eax] movaps xmm1,[eax+16] movaps xmm2,[eax+32] movaps xmm3,[eax+48] movaps xmm4,[eax+64] movaps xmm5,[eax+80] movaps xmm6,[eax+96] movaps xmm7,[eax+112] /*Collect*/ maxps xmm0,xmm1 maxps xmm2,xmm3 maxps xmm4,xmm5 maxps xmm6,xmm7 maxps xmm0,xmm2 maxps xmm4,xmm6 maxps xmm0,xmm4 movhlps xmm1,xmm0 maxps xmm0,xmm1 shufps xmm1,xmm0,1 maxps xmm0,xmm1 movss back,xmm0 } return(back); #else float val,max_val; float *p,*stop_p; max_val=v[0]; for(p=v+1,stop_p=v+32;p!=stop_p;) { val= *p++; if(val>max_val) max_val=val; } return(max_val); #endif /*DB_USE_SIMD*/ } inline float db_Max_16Aligned16_f(float *v) { #ifdef DB_USE_SIMD float back; _asm { mov eax,v /*Chunk1*/ movaps xmm0,[eax] movaps xmm1,[eax+16] movaps xmm2,[eax+32] movaps xmm3,[eax+48] /*Collect*/ maxps xmm0,xmm1 maxps xmm2,xmm3 maxps xmm0,xmm2 movhlps xmm1,xmm0 maxps xmm0,xmm1 shufps xmm1,xmm0,1 maxps xmm0,xmm1 movss back,xmm0 } return(back); #else float val,max_val; float *p,*stop_p; max_val=v[0]; for(p=v+1,stop_p=v+16;p!=stop_p;) { val= *p++; if(val>max_val) max_val=val; } return(max_val); #endif /*DB_USE_SIMD*/ } inline float db_Max_8Aligned16_f(float *v) { #ifdef DB_USE_SIMD float back; _asm { mov eax,v /*Chunk1*/ movaps xmm0,[eax] movaps xmm1,[eax+16] /*Collect*/ maxps xmm0,xmm1 movhlps xmm1,xmm0 maxps xmm0,xmm1 shufps xmm1,xmm0,1 maxps xmm0,xmm1 movss back,xmm0 } return(back); #else float val,max_val; float *p,*stop_p; max_val=v[0]; for(p=v+1,stop_p=v+8;p!=stop_p;) { val= *p++; if(val>max_val) max_val=val; } return(max_val); #endif /*DB_USE_SIMD*/ } inline float db_Max_Aligned16_f(float *v,int size) { float val,max_val; float *stop_v; max_val=v[0]; for(;size>=128;size-=128) { val=db_Max_128Aligned16_f(v); v+=128; if(val>max_val) max_val=val; } if(size&64) { val=db_Max_64Aligned16_f(v); v+=64; if(val>max_val) max_val=val; } if(size&32) { val=db_Max_32Aligned16_f(v); v+=32; if(val>max_val) max_val=val; } if(size&16) { val=db_Max_16Aligned16_f(v); v+=16; if(val>max_val) max_val=val; } if(size&8) { val=db_Max_8Aligned16_f(v); v+=8; if(val>max_val) max_val=val; } if(size&7) { for(stop_v=v+(size&7);v!=stop_v;) { val= *v++; if(val>max_val) max_val=val; } } return(max_val); } /*Find maximum value of img in the region starting at (left,top) and with width w and height h. img[left] should be 16 byte aligned*/ float db_MaxImage_Aligned16_f(float **img,int left,int top,int w,int h) { float val,max_val; int i,stop_i; if(w && h) { stop_i=top+h; max_val=img[top][left]; for(i=top;imax_val) max_val=val; } return(max_val); } return(0.0); } inline void db_MaxVector_128_Aligned16_f(float *m,float *v1,float *v2) { #ifdef DB_USE_SIMD _asm { mov eax,v1 mov ebx,v2 mov ecx,m /*Chunk1*/ movaps xmm0,[eax] movaps xmm1,[eax+16] movaps xmm2,[eax+32] movaps xmm3,[eax+48] movaps xmm4,[eax+64] movaps xmm5,[eax+80] movaps xmm6,[eax+96] movaps xmm7,[eax+112] maxps xmm0,[ebx] maxps xmm1,[ebx+16] maxps xmm2,[ebx+32] maxps xmm3,[ebx+48] maxps xmm4,[ebx+64] maxps xmm5,[ebx+80] maxps xmm6,[ebx+96] maxps xmm7,[ebx+112] movaps [ecx],xmm0 movaps [ecx+16],xmm1 movaps [ecx+32],xmm2 movaps [ecx+48],xmm3 movaps [ecx+64],xmm4 movaps [ecx+80],xmm5 movaps [ecx+96],xmm6 movaps [ecx+112],xmm7 /*Chunk2*/ movaps xmm0,[eax+128] movaps xmm1,[eax+144] movaps xmm2,[eax+160] movaps xmm3,[eax+176] movaps xmm4,[eax+192] movaps xmm5,[eax+208] movaps xmm6,[eax+224] movaps xmm7,[eax+240] maxps xmm0,[ebx+128] maxps xmm1,[ebx+144] maxps xmm2,[ebx+160] maxps xmm3,[ebx+176] maxps xmm4,[ebx+192] maxps xmm5,[ebx+208] maxps xmm6,[ebx+224] maxps xmm7,[ebx+240] movaps [ecx+128],xmm0 movaps [ecx+144],xmm1 movaps [ecx+160],xmm2 movaps [ecx+176],xmm3 movaps [ecx+192],xmm4 movaps [ecx+208],xmm5 movaps [ecx+224],xmm6 movaps [ecx+240],xmm7 /*Chunk3*/ movaps xmm0,[eax+256] movaps xmm1,[eax+272] movaps xmm2,[eax+288] movaps xmm3,[eax+304] movaps xmm4,[eax+320] movaps xmm5,[eax+336] movaps xmm6,[eax+352] movaps xmm7,[eax+368] maxps xmm0,[ebx+256] maxps xmm1,[ebx+272] maxps xmm2,[ebx+288] maxps xmm3,[ebx+304] maxps xmm4,[ebx+320] maxps xmm5,[ebx+336] maxps xmm6,[ebx+352] maxps xmm7,[ebx+368] movaps [ecx+256],xmm0 movaps [ecx+272],xmm1 movaps [ecx+288],xmm2 movaps [ecx+304],xmm3 movaps [ecx+320],xmm4 movaps [ecx+336],xmm5 movaps [ecx+352],xmm6 movaps [ecx+368],xmm7 /*Chunk4*/ movaps xmm0,[eax+384] movaps xmm1,[eax+400] movaps xmm2,[eax+416] movaps xmm3,[eax+432] movaps xmm4,[eax+448] movaps xmm5,[eax+464] movaps xmm6,[eax+480] movaps xmm7,[eax+496] maxps xmm0,[ebx+384] maxps xmm1,[ebx+400] maxps xmm2,[ebx+416] maxps xmm3,[ebx+432] maxps xmm4,[ebx+448] maxps xmm5,[ebx+464] maxps xmm6,[ebx+480] maxps xmm7,[ebx+496] movaps [ecx+384],xmm0 movaps [ecx+400],xmm1 movaps [ecx+416],xmm2 movaps [ecx+432],xmm3 movaps [ecx+448],xmm4 movaps [ecx+464],xmm5 movaps [ecx+480],xmm6 movaps [ecx+496],xmm7 } #else int i; float a,b; for(i=0;i<128;i++) { a=v1[i]; b=v2[i]; if(a>=b) m[i]=a; else m[i]=b; } #endif /*DB_USE_SIMD*/ } inline void db_MaxVector_128_SecondSourceDestAligned16_f(float *m,float *v1,float *v2) { #ifdef DB_USE_SIMD _asm { mov eax,v1 mov ebx,v2 mov ecx,m /*Chunk1*/ movups xmm0,[eax] movups xmm1,[eax+16] movups xmm2,[eax+32] movups xmm3,[eax+48] movups xmm4,[eax+64] movups xmm5,[eax+80] movups xmm6,[eax+96] movups xmm7,[eax+112] maxps xmm0,[ebx] maxps xmm1,[ebx+16] maxps xmm2,[ebx+32] maxps xmm3,[ebx+48] maxps xmm4,[ebx+64] maxps xmm5,[ebx+80] maxps xmm6,[ebx+96] maxps xmm7,[ebx+112] movaps [ecx],xmm0 movaps [ecx+16],xmm1 movaps [ecx+32],xmm2 movaps [ecx+48],xmm3 movaps [ecx+64],xmm4 movaps [ecx+80],xmm5 movaps [ecx+96],xmm6 movaps [ecx+112],xmm7 /*Chunk2*/ movups xmm0,[eax+128] movups xmm1,[eax+144] movups xmm2,[eax+160] movups xmm3,[eax+176] movups xmm4,[eax+192] movups xmm5,[eax+208] movups xmm6,[eax+224] movups xmm7,[eax+240] maxps xmm0,[ebx+128] maxps xmm1,[ebx+144] maxps xmm2,[ebx+160] maxps xmm3,[ebx+176] maxps xmm4,[ebx+192] maxps xmm5,[ebx+208] maxps xmm6,[ebx+224] maxps xmm7,[ebx+240] movaps [ecx+128],xmm0 movaps [ecx+144],xmm1 movaps [ecx+160],xmm2 movaps [ecx+176],xmm3 movaps [ecx+192],xmm4 movaps [ecx+208],xmm5 movaps [ecx+224],xmm6 movaps [ecx+240],xmm7 /*Chunk3*/ movups xmm0,[eax+256] movups xmm1,[eax+272] movups xmm2,[eax+288] movups xmm3,[eax+304] movups xmm4,[eax+320] movups xmm5,[eax+336] movups xmm6,[eax+352] movups xmm7,[eax+368] maxps xmm0,[ebx+256] maxps xmm1,[ebx+272] maxps xmm2,[ebx+288] maxps xmm3,[ebx+304] maxps xmm4,[ebx+320] maxps xmm5,[ebx+336] maxps xmm6,[ebx+352] maxps xmm7,[ebx+368] movaps [ecx+256],xmm0 movaps [ecx+272],xmm1 movaps [ecx+288],xmm2 movaps [ecx+304],xmm3 movaps [ecx+320],xmm4 movaps [ecx+336],xmm5 movaps [ecx+352],xmm6 movaps [ecx+368],xmm7 /*Chunk4*/ movups xmm0,[eax+384] movups xmm1,[eax+400] movups xmm2,[eax+416] movups xmm3,[eax+432] movups xmm4,[eax+448] movups xmm5,[eax+464] movups xmm6,[eax+480] movups xmm7,[eax+496] maxps xmm0,[ebx+384] maxps xmm1,[ebx+400] maxps xmm2,[ebx+416] maxps xmm3,[ebx+432] maxps xmm4,[ebx+448] maxps xmm5,[ebx+464] maxps xmm6,[ebx+480] maxps xmm7,[ebx+496] movaps [ecx+384],xmm0 movaps [ecx+400],xmm1 movaps [ecx+416],xmm2 movaps [ecx+432],xmm3 movaps [ecx+448],xmm4 movaps [ecx+464],xmm5 movaps [ecx+480],xmm6 movaps [ecx+496],xmm7 } #else int i; float a,b; for(i=0;i<128;i++) { a=v1[i]; b=v2[i]; if(a>=b) m[i]=a; else m[i]=b; } #endif /*DB_USE_SIMD*/ } /*Compute Max-suppression-filtered image for a chunk of sf starting at (left,top), of width 124 and stopping at bottom. The output is shifted two steps left and overwrites 128 elements for each row. The input s should be of width at least 128, and exist for 2 pixels outside the specified region. s[i][left-2] and sf[i][left-2] should be 16 byte aligned. Top must be at least 3*/ inline void db_MaxSuppressFilterChunk_5x5_Aligned16_f(float **sf,float **s,int left,int top,int bottom, /*temp should point to at least 6*132 floats of 16-byte-aligned allocated memory*/ float *temp) { #ifdef DB_USE_SIMD int i,lm2; float *two[4]; float *four,*five; lm2=left-2; /*Set pointers to pre-allocated memory*/ four=temp; five=four+132; for(i=0;i<4;i++) { two[i]=five+(i+1)*132; } /*Set rests of four and five to zero to avoid floating point exceptions*/ for(i=129;i<132;i++) { four[i]=0.0; five[i]=0.0; } /*Fill three rows of the wrap-around max buffers*/ for(i=top-3;is[i-2][j-2] && sv>s[i-2][j-1] && sv>s[i-2][j] && sv>s[i-2][j+1] && sv>s[i-2][j+2] && sv>s[i-1][j-2] && sv>s[i-1][j-1] && sv>s[i-1][j] && sv>s[i-1][j+1] && sv>s[i-1][j+2] && sv>s[ i][j-2] && sv>s[ i][j-1] && sv>s[ i][j+1] && sv>s[ i][j+2] && sv>s[i+1][j-2] && sv>s[i+1][j-1] && sv>s[i+1][j] && sv>s[i+1][j+1] && sv>s[i+1][j+2] && sv>s[i+2][j-2] && sv>s[i+2][j-1] && sv>s[i+2][j] && sv>s[i+2][j+1] && sv>s[i+2][j+2]) { sf[i][j-2]=0.0; } else sf[i][j-2]=sv; } #endif /*DB_USE_SIMD*/ } /*Compute Max-suppression-filtered image for a chunk of sf starting at (left,top) and stopping at bottom. The output is shifted two steps left. The input s should exist for 2 pixels outside the specified region. s[i][left-2] and sf[i][left-2] should be 16 byte aligned. Top must be at least 3. Reading and writing from and to the input and output images is done as if the region had a width equal to a multiple of 124. If this is not the case, the images should be over-allocated and the input cleared for a sufficient region*/ void db_MaxSuppressFilter_5x5_Aligned16_f(float **sf,float **s,int left,int top,int right,int bottom, /*temp should point to at least 6*132 floats of 16-byte-aligned allocated memory*/ float *temp) { int x,next_x; for(x=left;x<=right;x=next_x) { next_x=x+124; db_MaxSuppressFilterChunk_5x5_Aligned16_f(sf,s,x,top,bottom,temp); } } /*Extract corners from the chunk (left,top) to (right,bottom). Store in x_temp,y_temp and s_temp which should point to space of at least as many positions as there are pixels in the chunk*/ inline int db_CornersFromChunk(float **strength,int left,int top,int right,int bottom,float threshold,double *x_temp,double *y_temp,double *s_temp) { int i,j,nr; float s; nr=0; for(i=top;i<=bottom;i++) for(j=left;j<=right;j++) { s=strength[i][j]; if(s>=threshold && s>strength[i-2][j-2] && s>strength[i-2][j-1] && s>strength[i-2][j] && s>strength[i-2][j+1] && s>strength[i-2][j+2] && s>strength[i-1][j-2] && s>strength[i-1][j-1] && s>strength[i-1][j] && s>strength[i-1][j+1] && s>strength[i-1][j+2] && s>strength[ i][j-2] && s>strength[ i][j-1] && s>strength[ i][j+1] && s>strength[ i][j+2] && s>strength[i+1][j-2] && s>strength[i+1][j-1] && s>strength[i+1][j] && s>strength[i+1][j+1] && s>strength[i+1][j+2] && s>strength[i+2][j-2] && s>strength[i+2][j-1] && s>strength[i+2][j] && s>strength[i+2][j+1] && s>strength[i+2][j+2]) { x_temp[nr]=(double) j; y_temp[nr]=(double) i; s_temp[nr]=(double) s; nr++; } } return(nr); } //Sub-pixel accuracy using 2D quadratic interpolation.(YCJ) inline void db_SubPixel(float **strength, const double xd, const double yd, double &xs, double &ys) { int x = (int) xd; int y = (int) yd; float fxx = strength[y][x-1] - strength[y][x] - strength[y][x] + strength[y][x+1]; float fyy = strength[y-1][x] - strength[y][x] - strength[y][x] + strength[y+1][x]; float fxy = (strength[y-1][x-1] - strength[y-1][x+1] - strength[y+1][x-1] + strength[y+1][x+1])/(float)4.0; float denom = (fxx * fyy - fxy * fxy) * (float) 2.0; xs = xd; ys = yd; if ( db_absf(denom) <= FLT_EPSILON ) { return; } else { float fx = strength[y][x+1] - strength[y][x-1]; float fy = strength[y+1][x] - strength[y-1][x]; float dx = (fyy * fx - fxy * fy) / denom; float dy = (fxx * fy - fxy * fx) / denom; if ( db_absf(dx) > 1.0 || db_absf(dy) > 1.0 ) { return; } else { xs -= dx; ys -= dy; } } return; } /*Extract corners from the image part from (left,top) to (right,bottom). Store in x and y, extracting at most satnr corners in each block of size (bw,bh). The pointer temp_d should point to at least 5*bw*bh positions. area_factor holds how many corners max to extract per 10000 pixels*/ void db_ExtractCornersSaturated(float **strength,int left,int top,int right,int bottom, int bw,int bh,unsigned long area_factor, float threshold,double *temp_d, double *x_coord,double *y_coord,int *nr_corners) { double *x_temp,*y_temp,*s_temp,*select_temp; double loc_thresh; unsigned long bwbh,area,saturation; int x,next_x,last_x; int y,next_y,last_y; int nr,nr_points,i,stop; bwbh=bw*bh; x_temp=temp_d; y_temp=x_temp+bwbh; s_temp=y_temp+bwbh; select_temp=s_temp+bwbh; #ifdef DB_SUB_PIXEL // subpixel processing may sometimes push the corner ourside the real border // increasing border size: left++; top++; bottom--; right--; #endif /*DB_SUB_PIXEL*/ nr_points=0; for(y=top;y<=bottom;y=next_y) { next_y=y+bh; last_y=next_y-1; if(last_y>bottom) last_y=bottom; for(x=left;x<=right;x=next_x) { next_x=x+bw; last_x=next_x-1; if(last_x>right) last_x=right; area=(last_x-x+1)*(last_y-y+1); saturation=(area*area_factor)/10000; nr=db_CornersFromChunk(strength,x,y,last_x,last_y,threshold,x_temp,y_temp,s_temp); if(nr) { if(((unsigned long)nr)>saturation) loc_thresh=db_LeanQuickSelect(s_temp,nr,nr-saturation,select_temp); else loc_thresh=threshold; stop=nr_points+saturation; for(i=0;(i=loc_thresh) { #ifdef DB_SUB_PIXEL db_SubPixel(strength, x_temp[i], y_temp[i], x_coord[nr_points], y_coord[nr_points]); #else x_coord[nr_points]=x_temp[i]; y_coord[nr_points]=y_temp[i]; #endif nr_points++; } } } } } *nr_corners=nr_points; } db_CornerDetector_f::db_CornerDetector_f() { m_w=0; m_h=0; } db_CornerDetector_f::~db_CornerDetector_f() { Clean(); } void db_CornerDetector_f::Clean() { if(m_w!=0) { delete [] m_temp_f; delete [] m_temp_d; db_FreeStrengthImage_f(m_strength_mem,m_strength,m_h); } m_w=0; m_h=0; } unsigned long db_CornerDetector_f::Init(int im_width,int im_height,int target_nr_corners, int nr_horizontal_blocks,int nr_vertical_blocks, double absolute_threshold,double relative_threshold) { int chunkwidth=208; int block_width,block_height; unsigned long area_factor; int active_width,active_height; active_width=db_maxi(1,im_width-10); active_height=db_maxi(1,im_height-10); block_width=db_maxi(1,active_width/nr_horizontal_blocks); block_height=db_maxi(1,active_height/nr_vertical_blocks); area_factor=db_minl(1000,db_maxl(1,(long)(10000.0*((double)target_nr_corners)/ (((double)active_width)*((double)active_height))))); return(Start(im_width,im_height,block_width,block_height,area_factor, absolute_threshold,relative_threshold,chunkwidth)); } unsigned long db_CornerDetector_f::Start(int im_width,int im_height, int block_width,int block_height,unsigned long area_factor, double absolute_threshold,double relative_threshold,int chunkwidth) { Clean(); m_w=im_width; m_h=im_height; m_cw=chunkwidth; m_bw=block_width; m_bh=block_height; m_area_factor=area_factor; m_r_thresh=relative_threshold; m_a_thresh=absolute_threshold; m_max_nr=db_maxl(1,1+(m_w*m_h*m_area_factor)/10000); m_temp_f=new float[13*(m_cw+4)]; m_temp_d=new double[5*m_bw*m_bh]; m_strength=db_AllocStrengthImage_f(&m_strength_mem,m_w,m_h); return(m_max_nr); } void db_CornerDetector_f::DetectCorners(const float * const *img,double *x_coord,double *y_coord,int *nr_corners) const { float max_val,threshold; db_HarrisStrength_f(m_strength,img,m_w,m_h,m_temp_f,m_cw); if(m_r_thresh) { max_val=db_MaxImage_Aligned16_f(m_strength,3,3,m_w-6,m_h-6); threshold= (float) db_maxd(m_a_thresh,max_val*m_r_thresh); } else threshold= (float) m_a_thresh; db_ExtractCornersSaturated(m_strength,BORDER,BORDER,m_w-BORDER-1,m_h-BORDER-1,m_bw,m_bh,m_area_factor,threshold, m_temp_d,x_coord,y_coord,nr_corners); } db_CornerDetector_u::db_CornerDetector_u() { m_w=0; m_h=0; } db_CornerDetector_u::~db_CornerDetector_u() { Clean(); } db_CornerDetector_u::db_CornerDetector_u(const db_CornerDetector_u& cd) { Start(cd.m_w, cd.m_h, cd.m_bw, cd.m_bh, cd.m_area_factor, cd.m_a_thresh, cd.m_r_thresh); } db_CornerDetector_u& db_CornerDetector_u::operator=(const db_CornerDetector_u& cd) { if ( this == &cd ) return *this; Clean(); Start(cd.m_w, cd.m_h, cd.m_bw, cd.m_bh, cd.m_area_factor, cd.m_a_thresh, cd.m_r_thresh); return *this; } void db_CornerDetector_u::Clean() { if(m_w!=0) { delete [] m_temp_i; delete [] m_temp_d; db_FreeStrengthImage_f(m_strength_mem,m_strength,m_h); } m_w=0; m_h=0; } unsigned long db_CornerDetector_u::Init(int im_width,int im_height,int target_nr_corners, int nr_horizontal_blocks,int nr_vertical_blocks, double absolute_threshold,double relative_threshold) { int block_width,block_height; unsigned long area_factor; int active_width,active_height; active_width=db_maxi(1,im_width-10); active_height=db_maxi(1,im_height-10); block_width=db_maxi(1,active_width/nr_horizontal_blocks); block_height=db_maxi(1,active_height/nr_vertical_blocks); area_factor=db_minl(1000,db_maxl(1,(long)(10000.0*((double)target_nr_corners)/ (((double)active_width)*((double)active_height))))); return(Start(im_width,im_height,block_width,block_height,area_factor, 16.0*absolute_threshold,relative_threshold)); } unsigned long db_CornerDetector_u::Start(int im_width,int im_height, int block_width,int block_height,unsigned long area_factor, double absolute_threshold,double relative_threshold) { Clean(); m_w=im_width; m_h=im_height; m_bw=block_width; m_bh=block_height; m_area_factor=area_factor; m_r_thresh=relative_threshold; m_a_thresh=absolute_threshold; m_max_nr=db_maxl(1,1+(m_w*m_h*m_area_factor)/10000); m_temp_i=new int[18*128]; m_temp_d=new double[5*m_bw*m_bh]; m_strength=db_AllocStrengthImage_f(&m_strength_mem,m_w,m_h); return(m_max_nr); } void db_CornerDetector_u::DetectCorners(const unsigned char * const *img,double *x_coord,double *y_coord,int *nr_corners, const unsigned char * const *msk, unsigned char fgnd) const { float max_val,threshold; db_HarrisStrength_u(m_strength,img,m_w,m_h,m_temp_i); if(m_r_thresh) { max_val=db_MaxImage_Aligned16_f(m_strength,3,3,m_w-6,m_h-6); threshold= (float) db_maxd(m_a_thresh,max_val*m_r_thresh); } else threshold= (float) m_a_thresh; db_ExtractCornersSaturated(m_strength,BORDER,BORDER,m_w-BORDER-1,m_h-BORDER-1,m_bw,m_bh,m_area_factor,threshold, m_temp_d,x_coord,y_coord,nr_corners); if ( msk ) { int nr_corners_mask=0; for ( int i = 0; i < *nr_corners; ++i) { int cor_x = db_roundi(*(x_coord+i)); int cor_y = db_roundi(*(y_coord+i)); if ( msk[cor_y][cor_x] == fgnd ) { x_coord[nr_corners_mask] = x_coord[i]; y_coord[nr_corners_mask] = y_coord[i]; nr_corners_mask++; } } *nr_corners = nr_corners_mask; } } void db_CornerDetector_u::ExtractCorners(float ** strength, double *x_coord, double *y_coord, int *nr_corners) { if ( m_w!=0 ) db_ExtractCornersSaturated(strength,BORDER,BORDER,m_w-BORDER-1,m_h-BORDER-1,m_bw,m_bh,m_area_factor,float(m_a_thresh), m_temp_d,x_coord,y_coord,nr_corners); }