From dca21ba0fd1bb1f8998fc39d7e218d3ebe4d636b Mon Sep 17 00:00:00 2001 From: Hamid Date: Tue, 16 Jun 2015 09:05:17 +0200 Subject: [PATCH 1/2] README.md: Typo dsp/p_conv_f32: Remove an extra element in the result, Fix a problem in involving uninitialize memory addresses in computation. image/p_conv2d_f32: Returns incorrect values as it doesn't flip the kernel in vertical and horizontal directions, Support for rectangular kernels. image/p_median3x3.c: For 3x3 median filter, I replaced it with hardwired median search described here: http:users.utcluj.ro/~baruch/resources/Image/xl23_16.pdf Extra information Signed-off-by: Hamid Ebadi Counter example for p_conv_f32 Response from FreeMat: --> x = [1, 2, 3, 4]; --> h = [5,6,7]; --> r = conv(x, h) r = 5 16 34 52 45 28 Response from pal: float x[4] = {1,2,3,4}; float h[3] = {5,6,7} ; float r[10] = {100,100,100,100,100,100, 100, 100,100, 100}; p_conv_f32( x, h , r ,4 ,3); printf ("%f, %f, %f, %f, %f, %f, %f, %f", r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7]); 100.000000, 105.000000, 116.000000, 134.000000, 152.000000, 145.000000, 128.000000, 100.000000 Counter example for p_conv2d_f32 Response from FreeMat: --> A= [17 24 1 8 15; 23 5 7 14 16; 4 6 13 20 22;10 12 19 21 3; 11 18 25 2 9] --> B=[1 3 1; 0 5 0; 2 1 2] --> E=[0 0 0; 0 1 0; 0 0 0] --> C2 = conv2(A,E,'valid') <-- works correctly since kernel is symmetric --> C1 = conv2(A,B,'valid') <-- Doesn't work correctly 120, 165, 205, 160, 200, 245, 190, 255, 235, Response from pal: 155.0, 135.0, 200.0, 145.0, 190.0, 230.0, 185.0, 225.0, 270.0, int main(int argc, char *argv[]) { int i, j; float src[5*5] = {17,24,1,8,15, 23,5,7,14,16, 4,6,13,20,22, 10,12,19,21,3, 11,18,25,2,9 }; float kernel[3*3] = { 1,3,1, 0,5,0, 2,1,2 }; float dest[3*3]; p_conv2d_f32(src, kernel, dest, 5, 5, 3); for (i = 0; i < W; i++) { for (j = 0; j < W; j++) { printf("%.1f, ", src[i*W+j]); } printf("\n"); } printf("\n"); for (i = 0; i < W2; i++) { for (j = 0; j < W2; j++) { printf("%.1f, ", dest[i*W2+j]); } printf("\n"); } } --- README.md | 2 +- include/pal_image.h | 2 +- src/dsp/p_conv.c | 12 ++++++++---- src/image/p_conv2d.c | 34 ++++++++++++++-------------------- src/image/p_median3x3.c | 40 +++++++++++++++++++++++++++++++++++++++- 5 files changed, 63 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index b073ef2..8635c03 100644 --- a/README.md +++ b/README.md @@ -229,7 +229,7 @@ FUNCTION | NOTES [p_max()](src/math/p_max.c) | finds max val [p_min()](src/math/p_min.c) | finds min val [p_mean()](src/math/p_mean.c) | mean operation -[p_median()](src/math/p_mean.c) | finds middle value +[p_median()](src/math/p_median.c) | finds middle value [p_mode()](src/math/p_mode.c) | finds most common value [p_mul()](src/math/p_mul.c) | multiplication [p_popcount()](src/math/p_popcount.c) | count the number of bits set diff --git a/include/pal_image.h b/include/pal_image.h index 6965542..9007b36 100644 --- a/include/pal_image.h +++ b/include/pal_image.h @@ -17,7 +17,7 @@ /*2d convolution */ void p_conv2d_f32(const float *x, float *m, float *r, int rows, int cols, - int msize); + int mrows, int mcols); /*2d box (i.e mean) filter(3x3) */ void p_box3x3_f32(const float *x, float *r, int rows, int cols); diff --git a/src/dsp/p_conv.c b/src/dsp/p_conv.c index 60f2a20..acde422 100644 --- a/src/dsp/p_conv.c +++ b/src/dsp/p_conv.c @@ -22,11 +22,15 @@ void p_conv_f32(const float *x, const float *h, float *r, int nx, int nh) { const float *xc = x; float *rx = r; - for ( int i = 0; i < nx; i++) { + int i,j ; + for ( i = 0; i < nx+nh-1; i++) { *(rx++) = 0; } + rx = r ; + for ( i = 0; i < nx; i++) { float xv = *xc++; - rx++; - for (int j = 0; j < nh; j++) { - *(rx + j) += xv * *(h + j); + + for (j = 0; j < nh; j++) { + *(rx + j) += xv * *(h + j); } + rx++; } } diff --git a/src/image/p_conv2d.c b/src/image/p_conv2d.c index bff439b..c60862d 100644 --- a/src/image/p_conv2d.c +++ b/src/image/p_conv2d.c @@ -19,36 +19,30 @@ */ void p_conv2d_f32(const float *x, float *m, float *r, int rows, int cols, - int msize) + int mrows, int mcols) { - int i, j, k; - float P, part; + int i, j, ki, kj; + float P; const float *px, *pm; float *pr; px = x; - pm = m; pr = r; - for (i = msize * 0.5; i < (rows - msize * 0.5); i++) { - for (j = msize * 0.5; j < (cols - msize * 0.5); j++) { + for (i = 0; i < rows - mrows+1 ; i++) { + for (j = 0; j < cols - mcols+1 ; j++) { P = 0.0f; - pm = m; - for (k = 0; k < msize; k++) { - p_dot_f32(px, pm, &part, msize); - P += part; - px += cols; - pm += msize; + pm = m+(mcols * mrows)-1; + for (ki=0 ; ki< mrows ; ki++){ + for (kj=0 ; kj< mcols ; kj++){ + P+= (*px++)* (*pm--) ; + } + px += cols - mcols; } - *pr = P; - pr++; - // move image pointer one index forward compared to - // the position from before `for` loop - px += 1 - msize * cols; + px -= (mrows * cols) -1 ; + *(pr++) = P; } - // move image pointer to the beginning of line - // beneath the current line - px += (int)(msize * 0.5) * 2; + px+=mcols-1 ; } } diff --git a/src/image/p_median3x3.c b/src/image/p_median3x3.c index b86303f..9210c01 100644 --- a/src/image/p_median3x3.c +++ b/src/image/p_median3x3.c @@ -1,5 +1,43 @@ #include +/* + * The following routines have been built from knowledge gathered + * around the Web. I am not aware of any copyright problem with + * them, so use it as you want. + * N. Devillard - 1998 + */ + +typedef float pixelvalue ; + +#define PIX_SORT(a,b) { if ((a)>(b)) PIX_SWAP((a),(b)); } +#define PIX_SWAP(a,b) { pixelvalue temp=(a);(a)=(b);(b)=temp; } +/*---------------------------------------------------------------------------- + Function : opt_med9() + In : pointer to an array of 9 pixelvalues + Out : a pixelvalue + Job : optimized search of the median of 9 pixelvalues + Notice : in theory, cannot go faster without assumptions on the + signal. + Formula from: + XILINX XCELL magazine, vol. 23 by John L. Smith + + The input array is *NOT* modified in the process + The result array is guaranteed to contain the median + value + ---------------------------------------------------------------------------*/ + +pixelvalue opt_med9(pixelvalue * pointer) +{ + pixelvalue p[9]; + memcpy(p, pointer, 9*sizeof(pixelvalue) ); + PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ; + PIX_SORT(p[0], p[1]) ; PIX_SORT(p[3], p[4]) ; PIX_SORT(p[6], p[7]) ; + PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ; + PIX_SORT(p[0], p[3]) ; PIX_SORT(p[5], p[8]) ; PIX_SORT(p[4], p[7]) ; + PIX_SORT(p[3], p[6]) ; PIX_SORT(p[1], p[4]) ; PIX_SORT(p[2], p[5]) ; + PIX_SORT(p[4], p[7]) ; PIX_SORT(p[4], p[2]) ; PIX_SORT(p[6], p[4]) ; + PIX_SORT(p[4], p[2]) ; return(p[4]) ; +} /* * A median 3x3 filter. * @@ -50,7 +88,7 @@ void p_median3x3_f32(const float *x, float *r, int rows, int cols) buffer[buffer_col + 3] = *(px + cols); buffer[buffer_col + 6] = *(px + cols + cols); - p_median_f32(buffer, pr, 9); + *pr = opt_med9(buffer); pr++; px++; } From c3508edfe32a484f5d046755e30efb5fbdf07575 Mon Sep 17 00:00:00 2001 From: Hamid Date: Tue, 16 Jun 2015 09:24:23 +0200 Subject: [PATCH 2/2] fix parametere description for p_conv2d_f32 Extra information Signed-off-by: Hamid Ebadi --- src/image/p_conv2d.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/image/p_conv2d.c b/src/image/p_conv2d.c index c60862d..808ae5a 100644 --- a/src/image/p_conv2d.c +++ b/src/image/p_conv2d.c @@ -12,7 +12,9 @@ * * @param cols Number of columns in input image * - * @param msize Size of convolution kernel + * @param mrows number of rows in convolution kernel + * + * @param mcols number of cols in convolution kernel * * @return None *