ADNS2051 Library Program Demonstration

Dependencies:   ADNS2051lib FatFileSystem mbed MI0283QTlib

Committer:
clemente
Date:
Mon May 28 20:50:49 2012 +0000
Revision:
0:b560d4d15292

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
clemente 0:b560d4d15292 1 #include "mbed.h"
clemente 0:b560d4d15292 2 #include "ADNS2051.h"
clemente 0:b560d4d15292 3 #include "MI0283QTlib.h"
clemente 0:b560d4d15292 4
clemente 0:b560d4d15292 5
clemente 0:b560d4d15292 6 /** Demo software for ADNS2051 optical sensor.
clemente 0:b560d4d15292 7 *
clemente 0:b560d4d15292 8 */
clemente 0:b560d4d15292 9
clemente 0:b560d4d15292 10 // masks type
clemente 0:b560d4d15292 11 #define PREWITT 1
clemente 0:b560d4d15292 12 #define KIRSCH 2
clemente 0:b560d4d15292 13 #define SOBEL 3
clemente 0:b560d4d15292 14 // gamma value
clemente 0:b560d4d15292 15 #define GAMMA_25 1 // gamma value=2.5
clemente 0:b560d4d15292 16 #define GAMMA_22 2 // gamma value=2.2
clemente 0:b560d4d15292 17 #define GAMMA_18 3 // gamma value=1.8
clemente 0:b560d4d15292 18
clemente 0:b560d4d15292 19 /** Color and Edges enhancement
clemente 0:b560d4d15292 20 * I took these two functions from the book: "Digital Media Processing DSP Algorithms Using C Hazarathaiah Malepati".
clemente 0:b560d4d15292 21 *
clemente 0:b560d4d15292 22 * From the book:
clemente 0:b560d4d15292 23 * Histogram equalization technique of color enhancement in the RGB domain.
clemente 0:b560d4d15292 24 * As we know, if the color component is represented with 8-bit precision, then the values 0 to 255 are used to represent a
clemente 0:b560d4d15292 25 * particular color component.We say that the image colors are well represented when the color components occupy
clemente 0:b560d4d15292 26 * the total range of 0 to 255. If the color components of an image do not occupy the full range (i.e., 0 to 255), then
clemente 0:b560d4d15292 27 * we have the scope to enhance the colors of that image.With the histogram equalization technique, first we find
clemente 0:b560d4d15292 28 * the minimum (Xmin) and maximum (Xmax) values of a particular color component, and then we translate that
clemente 0:b560d4d15292 29 * color component to have minimum value at zero by subtracting the Xmin from its values, and finally, multiply the
clemente 0:b560d4d15292 30 * color component by 255/(Xmax− Xmin) to obtain the maximum color component 255. This process is illustrated
clemente 0:b560d4d15292 31 * in Figure 10.1. The same process is applied for all three color components of an image. This process enhances
clemente 0:b560d4d15292 32 * image colors (green becomes greener, yellow becomes more yellow, etc.),
clemente 0:b560d4d15292 33 */
clemente 0:b560d4d15292 34 void color_enhancement( unsigned char *pixelmap);
clemente 0:b560d4d15292 35
clemente 0:b560d4d15292 36 /**
clemente 0:b560d4d15292 37 * From the book:
clemente 0:b560d4d15292 38 * With edge enhancement, we increase the contrast of the image along the edges. The edge enhancement is done by
clemente 0:b560d4d15292 39 * strengthening the high-frequency components of an image. One way of enhancing edges is by adding weighted
clemente 0:b560d4d15292 40 * high-frequency components of an image to itself.
clemente 0:b560d4d15292 41 */
clemente 0:b560d4d15292 42 void edges_enhancement( unsigned char *pixelmap);
clemente 0:b560d4d15292 43
clemente 0:b560d4d15292 44 /** From the book: Image processing in C Dwayne Phillips
clemente 0:b560d4d15292 45 * The quick edge function performs edge detection using the single 3 x 3
clemente 0:b560d4d15292 46 * quick mask. It performs convolution over the image array using the quick mask.
clemente 0:b560d4d15292 47 * It thresholds the output image if requested, and xes the edges of the output
clemente 0:b560d4d15292 48 * image.
clemente 0:b560d4d15292 49 * Geometric operations change the spatial relationships between objects in an
clemente 0:b560d4d15292 50 * image. They do this by moving objects around and changing the size and
clemente 0:b560d4d15292 51 * shape of objects. Geometric operations help rearrange an image so we can
clemente 0:b560d4d15292 52 * see what we want to see a little better.
clemente 0:b560d4d15292 53 * The three basic geometric operations are displacement, stretching, and
clemente 0:b560d4d15292 54 * rotation. A fourth operation is the cross product.
clemente 0:b560d4d15292 55 * Displacement moves or displaces an image in the vertical and horizontal
clemente 0:b560d4d15292 56 * directions. Stretching enlarges or reduces an image in the vertical and horizontal
clemente 0:b560d4d15292 57 * directions. Rotation turns or rotates an image by any angle.
clemente 0:b560d4d15292 58 */
clemente 0:b560d4d15292 59 void quick_edge(unsigned char *pixelmap, unsigned char *outmap, unsigned int threshold);
clemente 0:b560d4d15292 60 void setup_masks(unsigned int detect_type, int *mask_0, int *mask_1, int *mask_2, int *mask_3, int *mask_4, int *mask_5, int *mask_6, int *mask_7);
clemente 0:b560d4d15292 61 void perform_convolution(unsigned char *image, unsigned char *out_image, unsigned char detect_type, unsigned char threshold);
clemente 0:b560d4d15292 62 void geometry(unsigned char *the_image, unsigned char *out_image,
clemente 0:b560d4d15292 63 float x_angle,
clemente 0:b560d4d15292 64 float x_stretch, float y_stretch,
clemente 0:b560d4d15292 65 int x_displace, int y_displace,
clemente 0:b560d4d15292 66 float x_cross, float y_cross,
clemente 0:b560d4d15292 67 int bilinear,
clemente 0:b560d4d15292 68 int rows,
clemente 0:b560d4d15292 69 int cols);
clemente 0:b560d4d15292 70 unsigned char bilinear_interpolate(unsigned char *the_image, double x, double y, int rows, int cols);
clemente 0:b560d4d15292 71 /* I found these books very useful and instructive. Recommend them wholeheartedly. */
clemente 0:b560d4d15292 72
clemente 0:b560d4d15292 73
clemente 0:b560d4d15292 74 /** Draw enlarged image to the x and y coordinates.
clemente 0:b560d4d15292 75 * The image will be enlarged by 4.
clemente 0:b560d4d15292 76 *
clemente 0:b560d4d15292 77 * @param *pxlmap the array image
clemente 0:b560d4d15292 78 * @param x the x position
clemente 0:b560d4d15292 79 * @param y the y position
clemente 0:b560d4d15292 80 */
clemente 0:b560d4d15292 81 void magnify( unsigned char *pxlmap, unsigned int x, unsigned int y);
clemente 0:b560d4d15292 82 void gammacorrection( unsigned char *pixelmap, unsigned char gammaval);
clemente 0:b560d4d15292 83
clemente 0:b560d4d15292 84 //
clemente 0:b560d4d15292 85 DigitalOut myled(LED2);
clemente 0:b560d4d15292 86 DigitalOut DBG_LED(LED1);
clemente 0:b560d4d15292 87 DigitalOut TS_CS(p15);
clemente 0:b560d4d15292 88 //
clemente 0:b560d4d15292 89 Serial pc(USBTX, USBRX);
clemente 0:b560d4d15292 90 //
clemente 0:b560d4d15292 91 ADNS2051 optical( p19, p20);
clemente 0:b560d4d15292 92 //
clemente 0:b560d4d15292 93 GLCD lcd( p11, p12, p13, p14, p17, p26);
clemente 0:b560d4d15292 94
clemente 0:b560d4d15292 95 unsigned char pxlmap[256];
clemente 0:b560d4d15292 96 //unsigned char edgemap[256];
clemente 0:b560d4d15292 97 unsigned char tmpmap[256];
clemente 0:b560d4d15292 98
clemente 0:b560d4d15292 99 int new_hi=63, new_low=10;
clemente 0:b560d4d15292 100 int threshold_val=50;
clemente 0:b560d4d15292 101 float edges_val=0.5;
clemente 0:b560d4d15292 102
clemente 0:b560d4d15292 103 #define COLOR_LVL 32
clemente 0:b560d4d15292 104
clemente 0:b560d4d15292 105 /*
clemente 0:b560d4d15292 106 #define COLOR_LVL 256
clemente 0:b560d4d15292 107
clemente 0:b560d4d15292 108 gamma LUT generated using this formula:
clemente 0:b560d4d15292 109
clemente 0:b560d4d15292 110 new_pixel=(( org_pixel/COLOR_LVL)^(1/gamma))*COLOR_LVL
clemente 0:b560d4d15292 111
clemente 0:b560d4d15292 112 // set gamma value...
clemente 0:b560d4d15292 113 gammaval=2.5;
clemente 0:b560d4d15292 114 float f2=1/gammaval;
clemente 0:b560d4d15292 115 // start LUT generation...
clemente 0:b560d4d15292 116 for ( i=0; i<COLOR_LVL; i++) {
clemente 0:b560d4d15292 117 float f1=(float)i/COLOR_LVL;
clemente 0:b560d4d15292 118 gammaLUT[i] = pow( f1,f2)*COLOR_LVL;
clemente 0:b560d4d15292 119 }
clemente 0:b560d4d15292 120
clemente 0:b560d4d15292 121 */
clemente 0:b560d4d15292 122
clemente 0:b560d4d15292 123 /* LUT for gamma value: 2.5 */
clemente 0:b560d4d15292 124 unsigned char gmm25_LUT[32]={
clemente 0:b560d4d15292 125 0, 7, 10, 12, 13, 15, 16, 17, 18, 19, 20, 20, 21, 22, 22, 23, 24,
clemente 0:b560d4d15292 126 24, 25, 25, 26, 27, 27, 28, 28, 28, 29, 29, 30, 30, 31, 31,
clemente 0:b560d4d15292 127 };
clemente 0:b560d4d15292 128
clemente 0:b560d4d15292 129 /* LUT for gamma value: 2.2 */
clemente 0:b560d4d15292 130 unsigned char gmm22_LUT[32]={
clemente 0:b560d4d15292 131 0, 6, 9, 10, 12, 13, 14, 16, 17, 17, 18, 19, 20, 21, 21, 22, 23,
clemente 0:b560d4d15292 132 24, 24, 25, 25, 26, 26, 27, 28, 28, 29, 29, 30, 30, 31, 31,
clemente 0:b560d4d15292 133 };
clemente 0:b560d4d15292 134
clemente 0:b560d4d15292 135 /* LUT for gamma value: 1.8 */
clemente 0:b560d4d15292 136 unsigned char gmm18_LUT[32]={
clemente 0:b560d4d15292 137 0, 4, 6, 8, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 21,
clemente 0:b560d4d15292 138 22, 23, 23, 24, 25, 25, 26, 27, 27, 28, 29, 29, 30, 30, 31,
clemente 0:b560d4d15292 139 };
clemente 0:b560d4d15292 140
clemente 0:b560d4d15292 141 void gammacorrection( unsigned char *pixelmap, unsigned char gammaval)
clemente 0:b560d4d15292 142 {
clemente 0:b560d4d15292 143 unsigned char *pGammaLUT;
clemente 0:b560d4d15292 144 unsigned char x0, y0;
clemente 0:b560d4d15292 145 int M=16, N=16;
clemente 0:b560d4d15292 146 int j, i, p, q;
clemente 0:b560d4d15292 147
clemente 0:b560d4d15292 148 switch (gammaval) {
clemente 0:b560d4d15292 149 case GAMMA_25:
clemente 0:b560d4d15292 150 pGammaLUT=(unsigned char*)gmm25_LUT;
clemente 0:b560d4d15292 151 break;
clemente 0:b560d4d15292 152 case GAMMA_22:
clemente 0:b560d4d15292 153 pGammaLUT=(unsigned char*)gmm22_LUT;
clemente 0:b560d4d15292 154 break;
clemente 0:b560d4d15292 155 case GAMMA_18:
clemente 0:b560d4d15292 156 pGammaLUT=(unsigned char*)gmm18_LUT;
clemente 0:b560d4d15292 157 break;
clemente 0:b560d4d15292 158 }
clemente 0:b560d4d15292 159
clemente 0:b560d4d15292 160 for(j = 0;j < M;j++){
clemente 0:b560d4d15292 161 p = j*N;q = (j + 1)*N;
clemente 0:b560d4d15292 162 for(i = p;i < q; i++){
clemente 0:b560d4d15292 163 y0 = pixelmap[i];
clemente 0:b560d4d15292 164 x0 = pGammaLUT[y0];
clemente 0:b560d4d15292 165 pixelmap[i] = x0;
clemente 0:b560d4d15292 166 }
clemente 0:b560d4d15292 167 }
clemente 0:b560d4d15292 168 }
clemente 0:b560d4d15292 169
clemente 0:b560d4d15292 170 #define FILL 255
clemente 0:b560d4d15292 171
clemente 0:b560d4d15292 172 /*******************************************
clemente 0:b560d4d15292 173 *
clemente 0:b560d4d15292 174 * geometry(..
clemente 0:b560d4d15292 175 *
clemente 0:b560d4d15292 176 * This routine performs geometric
clemente 0:b560d4d15292 177 * transformations on the pixels in an
clemente 0:b560d4d15292 178 * image array. It performs basic
clemente 0:b560d4d15292 179 * displacement, stretching, and rotation.
clemente 0:b560d4d15292 180 *
clemente 0:b560d4d15292 181 * The basic equations are:
clemente 0:b560d4d15292 182 *
clemente 0:b560d4d15292 183 * new x = x.cos(a) + y.sin(a) + x_displace
clemente 0:b560d4d15292 184 * + x.x_stretch +x.y.x_cross
clemente 0:b560d4d15292 185 *
clemente 0:b560d4d15292 186 * new y = y.cos(a) - x.sin(a) + y_displace
clemente 0:b560d4d15292 187 * + y.y_stretch +x.y.y_cross
clemente 0:b560d4d15292 188 *
clemente 0:b560d4d15292 189 *******************************************/
clemente 0:b560d4d15292 190 void geometry(unsigned char *the_image, unsigned char *out_image,
clemente 0:b560d4d15292 191 float x_angle,
clemente 0:b560d4d15292 192 float x_stretch, float y_stretch,
clemente 0:b560d4d15292 193 int x_displace, int y_displace,
clemente 0:b560d4d15292 194 float x_cross, float y_cross,
clemente 0:b560d4d15292 195 int bilinear,
clemente 0:b560d4d15292 196 int rows,
clemente 0:b560d4d15292 197 int cols)
clemente 0:b560d4d15292 198 {
clemente 0:b560d4d15292 199 double cosa, sina, radian_angle, tmpx, tmpy;
clemente 0:b560d4d15292 200 float fi, fj, x_div, y_div, x_num, y_num;
clemente 0:b560d4d15292 201 int i, j, new_i, new_j;
clemente 0:b560d4d15292 202
clemente 0:b560d4d15292 203
clemente 0:b560d4d15292 204 /******************************
clemente 0:b560d4d15292 205 *
clemente 0:b560d4d15292 206 * Load the terms array with
clemente 0:b560d4d15292 207 * the correct parameters.
clemente 0:b560d4d15292 208 *
clemente 0:b560d4d15292 209 *******************************/
clemente 0:b560d4d15292 210
clemente 0:b560d4d15292 211 /* the following magic number is from
clemente 0:b560d4d15292 212 180 degrees divided by pi */
clemente 0:b560d4d15292 213 radian_angle = x_angle/57.29577951;
clemente 0:b560d4d15292 214 cosa = cos(radian_angle);
clemente 0:b560d4d15292 215 sina = sin(radian_angle);
clemente 0:b560d4d15292 216
clemente 0:b560d4d15292 217 /************************************
clemente 0:b560d4d15292 218 *
clemente 0:b560d4d15292 219 * NOTE: You divide by the
clemente 0:b560d4d15292 220 * stretching factors. Therefore, if
clemente 0:b560d4d15292 221 * they are zero, you divide by 1.
clemente 0:b560d4d15292 222 * You do this with the x_div y_div
clemente 0:b560d4d15292 223 * variables. You also need a
clemente 0:b560d4d15292 224 * numerator term to create a zero
clemente 0:b560d4d15292 225 * product. You do this with the
clemente 0:b560d4d15292 226 * x_num and y_num variables.
clemente 0:b560d4d15292 227 *
clemente 0:b560d4d15292 228 *************************************/
clemente 0:b560d4d15292 229
clemente 0:b560d4d15292 230 if(x_stretch < 0.00001){
clemente 0:b560d4d15292 231 x_div = 1.0;
clemente 0:b560d4d15292 232 x_num = 0.0;
clemente 0:b560d4d15292 233 }
clemente 0:b560d4d15292 234 else{
clemente 0:b560d4d15292 235 x_div = x_stretch;
clemente 0:b560d4d15292 236 x_num = 1.0;
clemente 0:b560d4d15292 237 }
clemente 0:b560d4d15292 238
clemente 0:b560d4d15292 239 if(y_stretch < 0.00001){
clemente 0:b560d4d15292 240 y_div = 1.0;
clemente 0:b560d4d15292 241 y_num = 0.0;
clemente 0:b560d4d15292 242 }
clemente 0:b560d4d15292 243 else{
clemente 0:b560d4d15292 244 y_div = y_stretch;
clemente 0:b560d4d15292 245 y_num = 1.0;
clemente 0:b560d4d15292 246 }
clemente 0:b560d4d15292 247
clemente 0:b560d4d15292 248 /**************************
clemente 0:b560d4d15292 249 *
clemente 0:b560d4d15292 250 * Loop over image array
clemente 0:b560d4d15292 251 *
clemente 0:b560d4d15292 252 **************************/
clemente 0:b560d4d15292 253
clemente 0:b560d4d15292 254 for(i=0; i<rows; i++){
clemente 0:b560d4d15292 255 for(j=0; j<cols; j++){
clemente 0:b560d4d15292 256
clemente 0:b560d4d15292 257 fi = i;
clemente 0:b560d4d15292 258 fj = j;
clemente 0:b560d4d15292 259
clemente 0:b560d4d15292 260 tmpx = (double)(j)*cosa +
clemente 0:b560d4d15292 261 (double)(i)*sina +
clemente 0:b560d4d15292 262 (double)(x_displace) +
clemente 0:b560d4d15292 263 (double)(x_num*fj/x_div) +
clemente 0:b560d4d15292 264 (double)(x_cross*i*j);
clemente 0:b560d4d15292 265
clemente 0:b560d4d15292 266 tmpy = (double)(i)*cosa -
clemente 0:b560d4d15292 267 (double)(j)*sina +
clemente 0:b560d4d15292 268 (double)(y_displace) +
clemente 0:b560d4d15292 269 (double)(y_num*fi/y_div) +
clemente 0:b560d4d15292 270 (double)(y_cross*i*j);
clemente 0:b560d4d15292 271
clemente 0:b560d4d15292 272 if(x_stretch != 0.0)
clemente 0:b560d4d15292 273 tmpx = tmpx - (double)(fj*cosa + fi*sina);
clemente 0:b560d4d15292 274 if(y_stretch != 0.0)
clemente 0:b560d4d15292 275 tmpy = tmpy - (double)(fi*cosa - fj*sina);
clemente 0:b560d4d15292 276
clemente 0:b560d4d15292 277 new_j = tmpx;
clemente 0:b560d4d15292 278 new_i = tmpy;
clemente 0:b560d4d15292 279
clemente 0:b560d4d15292 280 if(bilinear == 0){
clemente 0:b560d4d15292 281 if(new_j < 0 ||
clemente 0:b560d4d15292 282 new_j >= cols ||
clemente 0:b560d4d15292 283 new_i < 0 ||
clemente 0:b560d4d15292 284 new_i >= rows)
clemente 0:b560d4d15292 285 out_image[j+(i*rows)] = FILL;
clemente 0:b560d4d15292 286 else
clemente 0:b560d4d15292 287 out_image[j+(i*rows)] =
clemente 0:b560d4d15292 288 the_image[new_j+(new_i*rows)];
clemente 0:b560d4d15292 289 } /* ends if bilinear */
clemente 0:b560d4d15292 290 else{
clemente 0:b560d4d15292 291 out_image[j+(i*rows)] =
clemente 0:b560d4d15292 292 bilinear_interpolate(the_image,
clemente 0:b560d4d15292 293 tmpx, tmpy,
clemente 0:b560d4d15292 294 rows, cols);
clemente 0:b560d4d15292 295 } /* ends bilinear if */
clemente 0:b560d4d15292 296
clemente 0:b560d4d15292 297 } /* ends loop over j */
clemente 0:b560d4d15292 298 } /* ends loop over i */
clemente 0:b560d4d15292 299
clemente 0:b560d4d15292 300 } /* ends geometry */
clemente 0:b560d4d15292 301
clemente 0:b560d4d15292 302
clemente 0:b560d4d15292 303
clemente 0:b560d4d15292 304 /*******************************************
clemente 0:b560d4d15292 305 *
clemente 0:b560d4d15292 306 * bilinear_interpolate(..
clemente 0:b560d4d15292 307 *
clemente 0:b560d4d15292 308 * This routine performs bi-linear
clemente 0:b560d4d15292 309 * interpolation.
clemente 0:b560d4d15292 310 *
clemente 0:b560d4d15292 311 * If x or y is out of range, i.e. less
clemente 0:b560d4d15292 312 * than zero or greater than rows or cols,
clemente 0:b560d4d15292 313 * this routine returns a zero.
clemente 0:b560d4d15292 314 *
clemente 0:b560d4d15292 315 * If x and y are both in range, this
clemente 0:b560d4d15292 316 * routine interpolates in the horizontal
clemente 0:b560d4d15292 317 * and vertical directions and returns
clemente 0:b560d4d15292 318 * the proper gray level.
clemente 0:b560d4d15292 319 *
clemente 0:b560d4d15292 320 *******************************************/
clemente 0:b560d4d15292 321 unsigned char bilinear_interpolate(unsigned char *the_image, double x, double y, int rows, int cols)
clemente 0:b560d4d15292 322 {
clemente 0:b560d4d15292 323 double fraction_x, fraction_y,
clemente 0:b560d4d15292 324 one_minus_x, one_minus_y,
clemente 0:b560d4d15292 325 tmp_double;
clemente 0:b560d4d15292 326 int ceil_x, ceil_y, floor_x, floor_y;
clemente 0:b560d4d15292 327 short p1, p2, p3, result = FILL;
clemente 0:b560d4d15292 328
clemente 0:b560d4d15292 329 /******************************
clemente 0:b560d4d15292 330 *
clemente 0:b560d4d15292 331 * If x or y is out of range,
clemente 0:b560d4d15292 332 * return a FILL.
clemente 0:b560d4d15292 333 *
clemente 0:b560d4d15292 334 *******************************/
clemente 0:b560d4d15292 335
clemente 0:b560d4d15292 336 if(x < 0.0 ||
clemente 0:b560d4d15292 337 x >= (double)(cols-1) ||
clemente 0:b560d4d15292 338 y < 0.0 ||
clemente 0:b560d4d15292 339 y >= (double)(rows-1))
clemente 0:b560d4d15292 340 return(result);
clemente 0:b560d4d15292 341
clemente 0:b560d4d15292 342 tmp_double = floor(x);
clemente 0:b560d4d15292 343 floor_x = tmp_double;
clemente 0:b560d4d15292 344 tmp_double = floor(y);
clemente 0:b560d4d15292 345 floor_y = tmp_double;
clemente 0:b560d4d15292 346 tmp_double = ceil(x);
clemente 0:b560d4d15292 347 ceil_x = tmp_double;
clemente 0:b560d4d15292 348 tmp_double = ceil(y);
clemente 0:b560d4d15292 349 ceil_y = tmp_double;
clemente 0:b560d4d15292 350
clemente 0:b560d4d15292 351 fraction_x = x - floor(x);
clemente 0:b560d4d15292 352 fraction_y = y - floor(y);
clemente 0:b560d4d15292 353
clemente 0:b560d4d15292 354 one_minus_x = 1.0 - fraction_x;
clemente 0:b560d4d15292 355 one_minus_y = 1.0 - fraction_y;
clemente 0:b560d4d15292 356
clemente 0:b560d4d15292 357 tmp_double = one_minus_x *
clemente 0:b560d4d15292 358 (double)(the_image[floor_x+(floor_y*rows)]) +
clemente 0:b560d4d15292 359 fraction_x *
clemente 0:b560d4d15292 360 (double)(the_image[ceil_x+(floor_y*rows)]);
clemente 0:b560d4d15292 361 p1 = tmp_double;
clemente 0:b560d4d15292 362
clemente 0:b560d4d15292 363 tmp_double = one_minus_x *
clemente 0:b560d4d15292 364 (double)(the_image[floor_x+(ceil_y*rows)]) +
clemente 0:b560d4d15292 365 fraction_x *
clemente 0:b560d4d15292 366 (double)(the_image[ceil_x+(ceil_y*rows)]);
clemente 0:b560d4d15292 367 p2 = tmp_double;
clemente 0:b560d4d15292 368
clemente 0:b560d4d15292 369 tmp_double = one_minus_y * (double)(p1) +
clemente 0:b560d4d15292 370 fraction_y * (double)(p2);
clemente 0:b560d4d15292 371 p3 = tmp_double;
clemente 0:b560d4d15292 372
clemente 0:b560d4d15292 373
clemente 0:b560d4d15292 374 return(p3);
clemente 0:b560d4d15292 375
clemente 0:b560d4d15292 376 } /* ends bilinear_interpolate */
clemente 0:b560d4d15292 377
clemente 0:b560d4d15292 378
clemente 0:b560d4d15292 379
clemente 0:b560d4d15292 380 /***************************
clemente 0:b560d4d15292 381 *
clemente 0:b560d4d15292 382 * Directions for the masks
clemente 0:b560d4d15292 383 * 3 2 1
clemente 0:b560d4d15292 384 * 4 x 0
clemente 0:b560d4d15292 385 * 5 6 7
clemente 0:b560d4d15292 386 *
clemente 0:b560d4d15292 387 ****************************/
clemente 0:b560d4d15292 388 /* masks for kirsch operator */
clemente 0:b560d4d15292 389 int kirsch_mask_0[9] = {
clemente 0:b560d4d15292 390 5, 5, 5,
clemente 0:b560d4d15292 391 -3, 0, -3,
clemente 0:b560d4d15292 392 -3, -3, -3};
clemente 0:b560d4d15292 393
clemente 0:b560d4d15292 394 int kirsch_mask_1[9] = {
clemente 0:b560d4d15292 395 -3, 5, 5,
clemente 0:b560d4d15292 396 -3, 0, 5,
clemente 0:b560d4d15292 397 -3, -3, -3};
clemente 0:b560d4d15292 398
clemente 0:b560d4d15292 399 int kirsch_mask_2[9] = {
clemente 0:b560d4d15292 400 -3, -3, 5,
clemente 0:b560d4d15292 401 -3, 0, 5,
clemente 0:b560d4d15292 402 -3, -3, 5};
clemente 0:b560d4d15292 403
clemente 0:b560d4d15292 404 int kirsch_mask_3[9] = {
clemente 0:b560d4d15292 405 -3, -3, -3,
clemente 0:b560d4d15292 406 -3, 0, 5,
clemente 0:b560d4d15292 407 -3, 5, 5};
clemente 0:b560d4d15292 408
clemente 0:b560d4d15292 409 int kirsch_mask_4[9] = {
clemente 0:b560d4d15292 410 -3, -3, -3,
clemente 0:b560d4d15292 411 -3, 0, -3,
clemente 0:b560d4d15292 412 5, 5, 5};
clemente 0:b560d4d15292 413
clemente 0:b560d4d15292 414 int kirsch_mask_5[9] = {
clemente 0:b560d4d15292 415 -3, -3, -3,
clemente 0:b560d4d15292 416 5, 0, -3,
clemente 0:b560d4d15292 417 5, 5, -3};
clemente 0:b560d4d15292 418
clemente 0:b560d4d15292 419 int kirsch_mask_6[9] = {
clemente 0:b560d4d15292 420 5, -3, -3,
clemente 0:b560d4d15292 421 5, 0, -3,
clemente 0:b560d4d15292 422 5, -3, -3};
clemente 0:b560d4d15292 423
clemente 0:b560d4d15292 424 int kirsch_mask_7[9] = {
clemente 0:b560d4d15292 425 5, 5, -3,
clemente 0:b560d4d15292 426 5, 0, -3,
clemente 0:b560d4d15292 427 -3, -3, -3};
clemente 0:b560d4d15292 428
clemente 0:b560d4d15292 429
clemente 0:b560d4d15292 430 /* masks for prewitt operator */
clemente 0:b560d4d15292 431
clemente 0:b560d4d15292 432 int prewitt_mask_0[9] = {
clemente 0:b560d4d15292 433 1, 1, 1,
clemente 0:b560d4d15292 434 1, -2, 1
clemente 0:b560d4d15292 435 -1, -1, -1 };
clemente 0:b560d4d15292 436
clemente 0:b560d4d15292 437 int prewitt_mask_1[9] = {
clemente 0:b560d4d15292 438 1, 1, 1,
clemente 0:b560d4d15292 439 1, -2, -1,
clemente 0:b560d4d15292 440 1, -1, -1 };
clemente 0:b560d4d15292 441
clemente 0:b560d4d15292 442 int prewitt_mask_2[9] = {
clemente 0:b560d4d15292 443 1, 1, -1,
clemente 0:b560d4d15292 444 1, -2, -1,
clemente 0:b560d4d15292 445 1, 1, -1 };
clemente 0:b560d4d15292 446
clemente 0:b560d4d15292 447 int prewitt_mask_3[9] = {
clemente 0:b560d4d15292 448 1, -1, -1,
clemente 0:b560d4d15292 449 1, -2, -1,
clemente 0:b560d4d15292 450 1, 1, 1};
clemente 0:b560d4d15292 451
clemente 0:b560d4d15292 452 int prewitt_mask_4[9] = {
clemente 0:b560d4d15292 453 -1, -1, -1,
clemente 0:b560d4d15292 454 1, -2, 1,
clemente 0:b560d4d15292 455 1, 1, 1};
clemente 0:b560d4d15292 456
clemente 0:b560d4d15292 457 int prewitt_mask_5[9] = {
clemente 0:b560d4d15292 458 -1, -1, 1,
clemente 0:b560d4d15292 459 -1, -2, 1,
clemente 0:b560d4d15292 460 1, 1, 1};
clemente 0:b560d4d15292 461
clemente 0:b560d4d15292 462 int prewitt_mask_6[9] = {
clemente 0:b560d4d15292 463 -1, 1, 1,
clemente 0:b560d4d15292 464 -1, -2, 1,
clemente 0:b560d4d15292 465 -1, 1, 1};
clemente 0:b560d4d15292 466
clemente 0:b560d4d15292 467 int prewitt_mask_7[9] = {
clemente 0:b560d4d15292 468 1, 1, 1,
clemente 0:b560d4d15292 469 -1, -2, 1,
clemente 0:b560d4d15292 470 -1, -1, 1};
clemente 0:b560d4d15292 471
clemente 0:b560d4d15292 472
clemente 0:b560d4d15292 473 /* masks for sobel operator */
clemente 0:b560d4d15292 474
clemente 0:b560d4d15292 475 int sobel_mask_0[9] = {
clemente 0:b560d4d15292 476 1, 2, 1,
clemente 0:b560d4d15292 477 0, 0, 0,
clemente 0:b560d4d15292 478 -1, -2, -1};
clemente 0:b560d4d15292 479
clemente 0:b560d4d15292 480 int sobel_mask_1[9] = {
clemente 0:b560d4d15292 481 2, 1, 0,
clemente 0:b560d4d15292 482 1, 0, -1,
clemente 0:b560d4d15292 483 0, -1, -2 };
clemente 0:b560d4d15292 484
clemente 0:b560d4d15292 485 int sobel_mask_2[9] = {
clemente 0:b560d4d15292 486 1, 0, -1,
clemente 0:b560d4d15292 487 2, 0, -2,
clemente 0:b560d4d15292 488 1, 0, -1};
clemente 0:b560d4d15292 489 int sobel_mask_3[9] = {
clemente 0:b560d4d15292 490 0, -1, -2,
clemente 0:b560d4d15292 491 1, 0, -1,
clemente 0:b560d4d15292 492 2, 1, 0 };
clemente 0:b560d4d15292 493 int sobel_mask_4[9] = {
clemente 0:b560d4d15292 494 -1, -2, -1,
clemente 0:b560d4d15292 495 0, 0, 0,
clemente 0:b560d4d15292 496 1, 2, 1};
clemente 0:b560d4d15292 497
clemente 0:b560d4d15292 498 int sobel_mask_5[9] = {
clemente 0:b560d4d15292 499 -2, -1, 0,
clemente 0:b560d4d15292 500 -1, 0, 1,
clemente 0:b560d4d15292 501 0, 1, 2};
clemente 0:b560d4d15292 502
clemente 0:b560d4d15292 503 int sobel_mask_6[9] = {
clemente 0:b560d4d15292 504 -1, 0, 1,
clemente 0:b560d4d15292 505 -2, 0, 2,
clemente 0:b560d4d15292 506 -1, 0, 1};
clemente 0:b560d4d15292 507
clemente 0:b560d4d15292 508 int sobel_mask_7[9] = {
clemente 0:b560d4d15292 509 0, 1, 2,
clemente 0:b560d4d15292 510 -1, 0, 1,
clemente 0:b560d4d15292 511 -2, -1, 0};
clemente 0:b560d4d15292 512
clemente 0:b560d4d15292 513
clemente 0:b560d4d15292 514 /***********************************************
clemente 0:b560d4d15292 515 *
clemente 0:b560d4d15292 516 * setup_masks(...
clemente 0:b560d4d15292 517 *
clemente 0:b560d4d15292 518 * This function copies the mask values defined
clemente 0:b560d4d15292 519 * at the top of this file into the mask
clemente 0:b560d4d15292 520 * arrays mask_0 through mask_7.
clemente 0:b560d4d15292 521 *
clemente 0:b560d4d15292 522 ***********************************************/
clemente 0:b560d4d15292 523 void setup_masks(unsigned int detect_type, int *mask_0, int *mask_1, int *mask_2, int *mask_3, int *mask_4, int *mask_5, int *mask_6, int *mask_7)
clemente 0:b560d4d15292 524 {
clemente 0:b560d4d15292 525 int i;
clemente 0:b560d4d15292 526
clemente 0:b560d4d15292 527 if(detect_type == KIRSCH){
clemente 0:b560d4d15292 528 for(i=0; i<9; i++){
clemente 0:b560d4d15292 529 mask_0[i] = kirsch_mask_0[i];
clemente 0:b560d4d15292 530 mask_1[i] = kirsch_mask_1[i];
clemente 0:b560d4d15292 531 mask_2[i] = kirsch_mask_2[i];
clemente 0:b560d4d15292 532 mask_3[i] = kirsch_mask_3[i];
clemente 0:b560d4d15292 533 mask_4[i] = kirsch_mask_4[i];
clemente 0:b560d4d15292 534 mask_5[i] = kirsch_mask_5[i];
clemente 0:b560d4d15292 535 mask_6[i] = kirsch_mask_6[i];
clemente 0:b560d4d15292 536 mask_7[i] = kirsch_mask_7[i];
clemente 0:b560d4d15292 537 }
clemente 0:b560d4d15292 538 } /* ends if detect_type == KIRSCH */
clemente 0:b560d4d15292 539
clemente 0:b560d4d15292 540
clemente 0:b560d4d15292 541 if(detect_type == PREWITT){
clemente 0:b560d4d15292 542 for(i=0; i<9; i++){
clemente 0:b560d4d15292 543 mask_0[i] = prewitt_mask_0[i];
clemente 0:b560d4d15292 544 mask_1[i] = prewitt_mask_1[i];
clemente 0:b560d4d15292 545 mask_2[i] = prewitt_mask_2[i];
clemente 0:b560d4d15292 546 mask_3[i] = prewitt_mask_3[i];
clemente 0:b560d4d15292 547 mask_4[i] = prewitt_mask_4[i];
clemente 0:b560d4d15292 548 mask_5[i] = prewitt_mask_5[i];
clemente 0:b560d4d15292 549 mask_6[i] = prewitt_mask_6[i];
clemente 0:b560d4d15292 550 mask_7[i] = prewitt_mask_7[i];
clemente 0:b560d4d15292 551 }
clemente 0:b560d4d15292 552 } /* ends if detect_type == PREWITT */
clemente 0:b560d4d15292 553
clemente 0:b560d4d15292 554
clemente 0:b560d4d15292 555 if(detect_type == SOBEL){
clemente 0:b560d4d15292 556 for(i=0; i<9; i++){
clemente 0:b560d4d15292 557 mask_0[i] = sobel_mask_0[i];
clemente 0:b560d4d15292 558 mask_1[i] = sobel_mask_1[i];
clemente 0:b560d4d15292 559 mask_2[i] = sobel_mask_2[i];
clemente 0:b560d4d15292 560 mask_3[i] = sobel_mask_3[i];
clemente 0:b560d4d15292 561 mask_4[i] = sobel_mask_4[i];
clemente 0:b560d4d15292 562 mask_5[i] = sobel_mask_5[i];
clemente 0:b560d4d15292 563 mask_6[i] = sobel_mask_6[i];
clemente 0:b560d4d15292 564 mask_7[i] = sobel_mask_7[i];
clemente 0:b560d4d15292 565 }
clemente 0:b560d4d15292 566 } /* ends if detect_type == SOBEL */
clemente 0:b560d4d15292 567
clemente 0:b560d4d15292 568 } /* ends setup_masks */
clemente 0:b560d4d15292 569
clemente 0:b560d4d15292 570 /**********************************************************
clemente 0:b560d4d15292 571 *
clemente 0:b560d4d15292 572 * perform_convolution(...
clemente 0:b560d4d15292 573 *
clemente 0:b560d4d15292 574 * This function performs convolution between the input
clemente 0:b560d4d15292 575 * image and 8 3x3 masks. The result is placed in
clemente 0:b560d4d15292 576 * the out_image.
clemente 0:b560d4d15292 577 *
clemente 0:b560d4d15292 578 ********************************************************/
clemente 0:b560d4d15292 579 void perform_convolution(unsigned char *image, unsigned char *out_image, unsigned char detect_type, unsigned char threshold)
clemente 0:b560d4d15292 580 {
clemente 0:b560d4d15292 581
clemente 0:b560d4d15292 582 int b, i, j, sum, p, q, c, k;
clemente 0:b560d4d15292 583
clemente 0:b560d4d15292 584 int mask_0[9];
clemente 0:b560d4d15292 585 int mask_1[9];
clemente 0:b560d4d15292 586 int mask_2[9];
clemente 0:b560d4d15292 587 int mask_3[9];
clemente 0:b560d4d15292 588 int mask_4[9];
clemente 0:b560d4d15292 589 int mask_5[9];
clemente 0:b560d4d15292 590 int mask_6[9];
clemente 0:b560d4d15292 591 int mask_7[9];
clemente 0:b560d4d15292 592
clemente 0:b560d4d15292 593 int max,
clemente 0:b560d4d15292 594 min,
clemente 0:b560d4d15292 595 new_hi,
clemente 0:b560d4d15292 596 new_low;
clemente 0:b560d4d15292 597
clemente 0:b560d4d15292 598 int M=16, N=16;
clemente 0:b560d4d15292 599
clemente 0:b560d4d15292 600 setup_masks(detect_type, &mask_0[0], &mask_1[0],&mask_2[0], &mask_3[0], &mask_4[0], &mask_5[0],&mask_6[0], &mask_7[0]);
clemente 0:b560d4d15292 601
clemente 0:b560d4d15292 602 new_hi = 60;
clemente 0:b560d4d15292 603 new_low = 10;
clemente 0:b560d4d15292 604
clemente 0:b560d4d15292 605 min = 10;
clemente 0:b560d4d15292 606 max = 63;
clemente 0:b560d4d15292 607
clemente 0:b560d4d15292 608 /* clear output image array */
clemente 0:b560d4d15292 609 for(i=0; i<N*M; i++)
clemente 0:b560d4d15292 610 out_image[i] = 0;
clemente 0:b560d4d15292 611
clemente 0:b560d4d15292 612 for( j = 1;j < (M-1);j++){
clemente 0:b560d4d15292 613 p = j*N; q = (j+1)*N;
clemente 0:b560d4d15292 614 for( i = (p+1);i < (q-1);i++) {
clemente 0:b560d4d15292 615
clemente 0:b560d4d15292 616 /* Convolve for all 8 directions */
clemente 0:b560d4d15292 617
clemente 0:b560d4d15292 618 /* 0 direction */
clemente 0:b560d4d15292 619
clemente 0:b560d4d15292 620 sum = 0;
clemente 0:b560d4d15292 621 c=0;
clemente 0:b560d4d15292 622 for( k=(i-N); k<=(i+N); k+=N) {
clemente 0:b560d4d15292 623 for(b=-1; b<2; b++){
clemente 0:b560d4d15292 624 sum = sum + image[k+b] * mask_0[c++];
clemente 0:b560d4d15292 625 }
clemente 0:b560d4d15292 626 }
clemente 0:b560d4d15292 627 if(sum < 0) sum = 0;
clemente 0:b560d4d15292 628 if(sum > max) sum = max;
clemente 0:b560d4d15292 629 if(sum > out_image[i])
clemente 0:b560d4d15292 630 out_image[i] = sum;
clemente 0:b560d4d15292 631
clemente 0:b560d4d15292 632
clemente 0:b560d4d15292 633 /* 1 direction */
clemente 0:b560d4d15292 634
clemente 0:b560d4d15292 635 sum = 0;
clemente 0:b560d4d15292 636 c=0;
clemente 0:b560d4d15292 637 for( k=(i-N); k<=(i+N); k+=N) {
clemente 0:b560d4d15292 638 for(b=-1; b<2; b++){
clemente 0:b560d4d15292 639 sum = sum + image[k+b] * mask_1[c++];
clemente 0:b560d4d15292 640 }
clemente 0:b560d4d15292 641 }
clemente 0:b560d4d15292 642 if(sum < 0) sum = 0;
clemente 0:b560d4d15292 643 if(sum > max) sum = max;
clemente 0:b560d4d15292 644 if(sum > out_image[i])
clemente 0:b560d4d15292 645 out_image[i] = sum;
clemente 0:b560d4d15292 646
clemente 0:b560d4d15292 647
clemente 0:b560d4d15292 648 /* 2 direction */
clemente 0:b560d4d15292 649
clemente 0:b560d4d15292 650 sum = 0;
clemente 0:b560d4d15292 651 c=0;
clemente 0:b560d4d15292 652 for( k=(i-N); k<=(i+N); k+=N) {
clemente 0:b560d4d15292 653 for(b=-1; b<2; b++){
clemente 0:b560d4d15292 654 sum = sum + image[k+b] * mask_2[c++];
clemente 0:b560d4d15292 655 }
clemente 0:b560d4d15292 656 }
clemente 0:b560d4d15292 657 if(sum < 0) sum = 0;
clemente 0:b560d4d15292 658 if(sum > max) sum = max;
clemente 0:b560d4d15292 659 if(sum > out_image[i])
clemente 0:b560d4d15292 660 out_image[i] = sum;
clemente 0:b560d4d15292 661
clemente 0:b560d4d15292 662
clemente 0:b560d4d15292 663 /* 3 direction */
clemente 0:b560d4d15292 664
clemente 0:b560d4d15292 665 sum = 0;
clemente 0:b560d4d15292 666 c=0;
clemente 0:b560d4d15292 667 for( k=(i-N); k<=(i+N); k+=N) {
clemente 0:b560d4d15292 668 for(b=-1; b<2; b++){
clemente 0:b560d4d15292 669 sum = sum + image[k+b] * mask_3[c++];
clemente 0:b560d4d15292 670 }
clemente 0:b560d4d15292 671 }
clemente 0:b560d4d15292 672 if(sum < 0) sum = 0;
clemente 0:b560d4d15292 673 if(sum > max) sum = max;
clemente 0:b560d4d15292 674 if(sum > out_image[i])
clemente 0:b560d4d15292 675 out_image[i] = sum;
clemente 0:b560d4d15292 676
clemente 0:b560d4d15292 677
clemente 0:b560d4d15292 678 /* 4 direction */
clemente 0:b560d4d15292 679
clemente 0:b560d4d15292 680 sum = 0;
clemente 0:b560d4d15292 681 c=0;
clemente 0:b560d4d15292 682 for( k=(i-N); k<=(i+N); k+=N) {
clemente 0:b560d4d15292 683 for(b=-1; b<2; b++){
clemente 0:b560d4d15292 684 sum = sum + image[k+b] * mask_4[c++];
clemente 0:b560d4d15292 685 }
clemente 0:b560d4d15292 686 }
clemente 0:b560d4d15292 687 if(sum < 0) sum = 0;
clemente 0:b560d4d15292 688 if(sum > max) sum = max;
clemente 0:b560d4d15292 689 if(sum > out_image[i])
clemente 0:b560d4d15292 690 out_image[i] = sum;
clemente 0:b560d4d15292 691
clemente 0:b560d4d15292 692
clemente 0:b560d4d15292 693 /* 5 direction */
clemente 0:b560d4d15292 694
clemente 0:b560d4d15292 695 sum = 0;
clemente 0:b560d4d15292 696 c=0;
clemente 0:b560d4d15292 697 for( k=(i-N); k<=(i+N); k+=N) {
clemente 0:b560d4d15292 698 for(b=-1; b<2; b++){
clemente 0:b560d4d15292 699 sum = sum + image[k+b] * mask_5[c++];
clemente 0:b560d4d15292 700 }
clemente 0:b560d4d15292 701 }
clemente 0:b560d4d15292 702 if(sum < 0) sum = 0;
clemente 0:b560d4d15292 703 if(sum > max) sum = max;
clemente 0:b560d4d15292 704 if(sum > out_image[i])
clemente 0:b560d4d15292 705 out_image[i] = sum;
clemente 0:b560d4d15292 706
clemente 0:b560d4d15292 707
clemente 0:b560d4d15292 708 /* 6 direction */
clemente 0:b560d4d15292 709
clemente 0:b560d4d15292 710 sum = 0;
clemente 0:b560d4d15292 711 c=0;
clemente 0:b560d4d15292 712 for( k=(i-N); k<=(i+N); k+=N) {
clemente 0:b560d4d15292 713 for(b=-1; b<2; b++){
clemente 0:b560d4d15292 714 sum = sum + image[k+b] * mask_6[c++];
clemente 0:b560d4d15292 715 }
clemente 0:b560d4d15292 716 }
clemente 0:b560d4d15292 717 if(sum < 0) sum = 0;
clemente 0:b560d4d15292 718 if(sum > max) sum = max;
clemente 0:b560d4d15292 719 if(sum > out_image[i])
clemente 0:b560d4d15292 720 out_image[i] = sum;
clemente 0:b560d4d15292 721
clemente 0:b560d4d15292 722
clemente 0:b560d4d15292 723 /* 7 direction */
clemente 0:b560d4d15292 724
clemente 0:b560d4d15292 725 sum = 0;
clemente 0:b560d4d15292 726 c=0;
clemente 0:b560d4d15292 727 for( k=(i-N); k<=(i+N); k+=N) {
clemente 0:b560d4d15292 728 for(b=-1; b<2; b++){
clemente 0:b560d4d15292 729 sum = sum + image[k+b] * mask_7[c++];
clemente 0:b560d4d15292 730 }
clemente 0:b560d4d15292 731 }
clemente 0:b560d4d15292 732 if(sum < 0) sum = 0;
clemente 0:b560d4d15292 733 if(sum > max) sum = max;
clemente 0:b560d4d15292 734 if(sum > out_image[i])
clemente 0:b560d4d15292 735 out_image[i] = sum;
clemente 0:b560d4d15292 736
clemente 0:b560d4d15292 737
clemente 0:b560d4d15292 738 } /* ends loop over j */
clemente 0:b560d4d15292 739 } /* ends loop over i */
clemente 0:b560d4d15292 740
clemente 0:b560d4d15292 741 /* if desired, threshold the output image */
clemente 0:b560d4d15292 742 if(threshold == 1){
clemente 0:b560d4d15292 743 for( j = 0;j < M;j++){
clemente 0:b560d4d15292 744 p = j*N; q = (j+1)*N;
clemente 0:b560d4d15292 745 for( i = p;i < q;i++) {
clemente 0:b560d4d15292 746 if(out_image[i] > 50){
clemente 0:b560d4d15292 747 out_image[i] = new_hi;
clemente 0:b560d4d15292 748 }
clemente 0:b560d4d15292 749 else{
clemente 0:b560d4d15292 750 out_image[i] = new_low;
clemente 0:b560d4d15292 751 }
clemente 0:b560d4d15292 752 }
clemente 0:b560d4d15292 753 }
clemente 0:b560d4d15292 754 } /* ends if threshold == 1 */
clemente 0:b560d4d15292 755
clemente 0:b560d4d15292 756 } /* ends perform_convolution */
clemente 0:b560d4d15292 757
clemente 0:b560d4d15292 758
clemente 0:b560d4d15292 759 /*******************************************
clemente 0:b560d4d15292 760 *
clemente 0:b560d4d15292 761 * quick_edge(...
clemente 0:b560d4d15292 762 *
clemente 0:b560d4d15292 763 * This function finds edges by using
clemente 0:b560d4d15292 764 * a single 3x3 mask.
clemente 0:b560d4d15292 765 *
clemente 0:b560d4d15292 766 *******************************************/
clemente 0:b560d4d15292 767 void quick_edge(unsigned char *pixelmap, unsigned char *outmap, unsigned int threshold)
clemente 0:b560d4d15292 768 {
clemente 0:b560d4d15292 769 int i, j, k, c, p, q, b;
clemente 0:b560d4d15292 770 int max, sum;
clemente 0:b560d4d15292 771
clemente 0:b560d4d15292 772 int M=16, N=16;
clemente 0:b560d4d15292 773
clemente 0:b560d4d15292 774 int quick_mask[9] = {
clemente 0:b560d4d15292 775 -1, 0, -1,
clemente 0:b560d4d15292 776 0, 4, 0,
clemente 0:b560d4d15292 777 -1, 0, -1 };
clemente 0:b560d4d15292 778
clemente 0:b560d4d15292 779 max = 63;
clemente 0:b560d4d15292 780
clemente 0:b560d4d15292 781 /* Do convolution over image array */
clemente 0:b560d4d15292 782 for( j = 1;j < (M-1);j++){
clemente 0:b560d4d15292 783 p = j*N; q = (j+1)*N;
clemente 0:b560d4d15292 784 for( i = (p+1);i < (q-1);i++) {
clemente 0:b560d4d15292 785 sum = 0;
clemente 0:b560d4d15292 786 c=0;
clemente 0:b560d4d15292 787 for( k=(i-N); k<=(i+N); k+=N) {
clemente 0:b560d4d15292 788 for(b=-1; b<2; b++){
clemente 0:b560d4d15292 789 sum = sum + pixelmap[k+b] * quick_mask[c++];
clemente 0:b560d4d15292 790 }
clemente 0:b560d4d15292 791 }
clemente 0:b560d4d15292 792 if(sum < 0) sum = 0;
clemente 0:b560d4d15292 793 if(sum > max) sum = max;
clemente 0:b560d4d15292 794 outmap[i] = sum;
clemente 0:b560d4d15292 795 } /* ends loop over i */
clemente 0:b560d4d15292 796 } /* ends loop over j */
clemente 0:b560d4d15292 797
clemente 0:b560d4d15292 798 /* if desired, threshold the output image */
clemente 0:b560d4d15292 799 if(threshold == 1){
clemente 0:b560d4d15292 800 for( j = 0;j < M;j++){
clemente 0:b560d4d15292 801 p = j*N; q = (j+1)*N;
clemente 0:b560d4d15292 802 for( i = p;i < q;i++) {
clemente 0:b560d4d15292 803 if(outmap[i] > threshold_val){
clemente 0:b560d4d15292 804 outmap[i] = new_hi;
clemente 0:b560d4d15292 805 }
clemente 0:b560d4d15292 806 else{
clemente 0:b560d4d15292 807 outmap[i] = new_low;
clemente 0:b560d4d15292 808 }
clemente 0:b560d4d15292 809 }
clemente 0:b560d4d15292 810 }
clemente 0:b560d4d15292 811 } /* ends if threshold == 1 */
clemente 0:b560d4d15292 812
clemente 0:b560d4d15292 813 } /* ends quick_edge */
clemente 0:b560d4d15292 814
clemente 0:b560d4d15292 815
clemente 0:b560d4d15292 816
clemente 0:b560d4d15292 817 void edges_enhancement( unsigned char *pixelmap)
clemente 0:b560d4d15292 818 {
clemente 0:b560d4d15292 819 int i, j, N, M, p, q;
clemente 0:b560d4d15292 820 unsigned char BufX[256];
clemente 0:b560d4d15292 821 int y0, x0;
clemente 0:b560d4d15292 822
clemente 0:b560d4d15292 823 N=16;
clemente 0:b560d4d15292 824 M=16;
clemente 0:b560d4d15292 825
clemente 0:b560d4d15292 826 for(j = 0;j < 1;j++) { // copy top row
clemente 0:b560d4d15292 827 p = j*N; q = (j+1)*N;
clemente 0:b560d4d15292 828 for(i = p;i < q;i++)
clemente 0:b560d4d15292 829 BufX[i] = pixelmap[i];
clemente 0:b560d4d15292 830 }
clemente 0:b560d4d15292 831 for(j = 0;j < M;j++) { // copy left column
clemente 0:b560d4d15292 832 p = j*N;
clemente 0:b560d4d15292 833 BufX[p] = pixelmap[p];
clemente 0:b560d4d15292 834 }
clemente 0:b560d4d15292 835 for(j = 1;j < M-1;j++) {
clemente 0:b560d4d15292 836 p = j*N+1; q = (j+1)*N-1;
clemente 0:b560d4d15292 837 for(i = p;i < q;i++) {
clemente 0:b560d4d15292 838 x0 = pixelmap[i]; y0 = pixelmap[i-1];
clemente 0:b560d4d15292 839 x0 = x0 << 2;
clemente 0:b560d4d15292 840 x0 = x0 - y0; y0 = pixelmap[i+1];
clemente 0:b560d4d15292 841 x0 = x0 - y0; y0 = pixelmap[i-N-1];
clemente 0:b560d4d15292 842 x0 = x0 - y0; y0 = pixelmap[i+N+1];
clemente 0:b560d4d15292 843 x0 = x0 - y0;
clemente 0:b560d4d15292 844 x0 = (int) pixelmap[i] + (int) x0*edges_val;
clemente 0:b560d4d15292 845 if (x0 < 0) x0 = 0;
clemente 0:b560d4d15292 846 if (x0 > 63) x0 = 63;
clemente 0:b560d4d15292 847 BufX[i] = (unsigned char) x0;
clemente 0:b560d4d15292 848 }
clemente 0:b560d4d15292 849 }
clemente 0:b560d4d15292 850 //
clemente 0:b560d4d15292 851 for(j = 0;j < M;j++){
clemente 0:b560d4d15292 852 p = j*N; q = (j+1)*N;
clemente 0:b560d4d15292 853 for(i = p;i < q;i++)
clemente 0:b560d4d15292 854 pixelmap[i] = BufX[i];
clemente 0:b560d4d15292 855 }
clemente 0:b560d4d15292 856 }
clemente 0:b560d4d15292 857
clemente 0:b560d4d15292 858 void color_enhancement( unsigned char *pixelmap)
clemente 0:b560d4d15292 859 {
clemente 0:b560d4d15292 860 int i, j, N, M, p, q;
clemente 0:b560d4d15292 861 unsigned char Hist[64];
clemente 0:b560d4d15292 862 int y0, x0;
clemente 0:b560d4d15292 863 float x;
clemente 0:b560d4d15292 864
clemente 0:b560d4d15292 865 N=16;
clemente 0:b560d4d15292 866 M=16;
clemente 0:b560d4d15292 867
clemente 0:b560d4d15292 868 for(i=0; i<64; i++)
clemente 0:b560d4d15292 869 Hist[i]=0;
clemente 0:b560d4d15292 870
clemente 0:b560d4d15292 871 // Starting the color enhancement
clemente 0:b560d4d15292 872 //
clemente 0:b560d4d15292 873 for(j = 0;j < M;j++){
clemente 0:b560d4d15292 874 p = j*N;
clemente 0:b560d4d15292 875 q = (j+1)*N;
clemente 0:b560d4d15292 876 for(i = p;i < q;i++)
clemente 0:b560d4d15292 877 Hist[ pixelmap[i]] += 1;
clemente 0:b560d4d15292 878 }
clemente 0:b560d4d15292 879
clemente 0:b560d4d15292 880 y0 = 0;
clemente 0:b560d4d15292 881 for(p = 0;p < 64;p++) {
clemente 0:b560d4d15292 882 y0+= Hist[p];
clemente 0:b560d4d15292 883 if (y0 > 32)
clemente 0:b560d4d15292 884 break;
clemente 0:b560d4d15292 885 }
clemente 0:b560d4d15292 886
clemente 0:b560d4d15292 887 y0=p;
clemente 0:b560d4d15292 888 x = 0;
clemente 0:b560d4d15292 889 for(j = 0;j < M;j++) {
clemente 0:b560d4d15292 890 p = j*N; q = (j+1)*N;
clemente 0:b560d4d15292 891 for(i = p;i < q;i++) {
clemente 0:b560d4d15292 892 x0 = (int) pixelmap[i] - y0;
clemente 0:b560d4d15292 893 if (x0 < 0)
clemente 0:b560d4d15292 894 x0 = 0;
clemente 0:b560d4d15292 895 if (x0 > 63)
clemente 0:b560d4d15292 896 x0 = 63;
clemente 0:b560d4d15292 897 pixelmap[i] = x0;
clemente 0:b560d4d15292 898 }
clemente 0:b560d4d15292 899 }
clemente 0:b560d4d15292 900
clemente 0:b560d4d15292 901 for(j = 63;j > 0;j--)
clemente 0:b560d4d15292 902 if (Hist[j] > 0) break;
clemente 0:b560d4d15292 903
clemente 0:b560d4d15292 904 x = (float) 64.0/(64-y0 + 63-j);
clemente 0:b560d4d15292 905
clemente 0:b560d4d15292 906 for(j = 0;j < M;j++) {
clemente 0:b560d4d15292 907 p = j*N; q = (j+1)*N;
clemente 0:b560d4d15292 908 for(i = p;i < q;i++)
clemente 0:b560d4d15292 909 pixelmap[i] = (unsigned char) ((float) pixelmap[i]*x + 0.5);
clemente 0:b560d4d15292 910 }
clemente 0:b560d4d15292 911
clemente 0:b560d4d15292 912 }
clemente 0:b560d4d15292 913
clemente 0:b560d4d15292 914 int main() {
clemente 0:b560d4d15292 915
clemente 0:b560d4d15292 916 char buf[256], c;
clemente 0:b560d4d15292 917 int i, ii;
clemente 0:b560d4d15292 918 int thrshld=0;
clemente 0:b560d4d15292 919 int masktype=1;
clemente 0:b560d4d15292 920 int gammaval=0; // gamma OFF
clemente 0:b560d4d15292 921
clemente 0:b560d4d15292 922 myled = 0;
clemente 0:b560d4d15292 923 TS_CS=1;
clemente 0:b560d4d15292 924 //
clemente 0:b560d4d15292 925 int subidx, idx;
clemente 0:b560d4d15292 926
clemente 0:b560d4d15292 927 lcd.lcd_init();
clemente 0:b560d4d15292 928 lcd.lcd_clear( LCD_WHITE);
clemente 0:b560d4d15292 929 lcd.backlightset( 1);
clemente 0:b560d4d15292 930 lcd.lcd_drawstr( "Images from optical mouse: Init", 0, 0, lcd.lcd_RGB( 0, 255, 0));
clemente 0:b560d4d15292 931
clemente 0:b560d4d15292 932 while( optical.init() );
clemente 0:b560d4d15292 933 optical.setframerate();
clemente 0:b560d4d15292 934
clemente 0:b560d4d15292 935 sprintf(buf, "Images from optical mouse: PixelDump [Chip rev: 0x%X]", optical.get_revisionID());
clemente 0:b560d4d15292 936 lcd.lcd_drawstr( buf, 0, 0, lcd.lcd_RGB( 0, 255, 0));
clemente 0:b560d4d15292 937 wait( 1.0);
clemente 0:b560d4d15292 938
clemente 0:b560d4d15292 939 //
clemente 0:b560d4d15292 940 while( 1) {
clemente 0:b560d4d15292 941
clemente 0:b560d4d15292 942 // you can use the serial terminal to change some parameters:
clemente 0:b560d4d15292 943 // [T/t] threshold ON/OFF
clemente 0:b560d4d15292 944 // [V/v] threshold value inc/dec
clemente 0:b560d4d15292 945 // [H/h] high value inc/dec
clemente 0:b560d4d15292 946 // [E/e] edge enhancement inc/dec
clemente 0:b560d4d15292 947 // [m] change mask type
clemente 0:b560d4d15292 948 // [g] change gamma value
clemente 0:b560d4d15292 949 //
clemente 0:b560d4d15292 950 if( pc.readable()) {
clemente 0:b560d4d15292 951 c = pc.getc();
clemente 0:b560d4d15292 952 if ( c=='t') {
clemente 0:b560d4d15292 953 thrshld=0;
clemente 0:b560d4d15292 954 printf("thrshld OFF\r\n");
clemente 0:b560d4d15292 955 }
clemente 0:b560d4d15292 956 if ( c=='T') {
clemente 0:b560d4d15292 957 thrshld=1;
clemente 0:b560d4d15292 958 printf("thrshld ON\r\n");
clemente 0:b560d4d15292 959 }
clemente 0:b560d4d15292 960 // threshold_val, new_hi, new_low
clemente 0:b560d4d15292 961 if ( c=='V') {
clemente 0:b560d4d15292 962 threshold_val++;
clemente 0:b560d4d15292 963 if ( threshold_val>63)
clemente 0:b560d4d15292 964 threshold_val=63;
clemente 0:b560d4d15292 965 printf("threshold_val=%d\r\n", threshold_val);
clemente 0:b560d4d15292 966 }
clemente 0:b560d4d15292 967 if ( c=='v') {
clemente 0:b560d4d15292 968 threshold_val--;
clemente 0:b560d4d15292 969 if ( threshold_val<0)
clemente 0:b560d4d15292 970 threshold_val=0;
clemente 0:b560d4d15292 971 printf("threshold_val=%d\r\n", threshold_val);
clemente 0:b560d4d15292 972 }
clemente 0:b560d4d15292 973 if ( c=='H') {
clemente 0:b560d4d15292 974 new_hi++;
clemente 0:b560d4d15292 975 if ( new_hi>63)
clemente 0:b560d4d15292 976 new_hi=63;
clemente 0:b560d4d15292 977 printf("new_hi=%d\r\n", new_hi);
clemente 0:b560d4d15292 978 }
clemente 0:b560d4d15292 979 if ( c=='h') {
clemente 0:b560d4d15292 980 new_hi--;
clemente 0:b560d4d15292 981 if ( new_hi<0)
clemente 0:b560d4d15292 982 new_hi=0;
clemente 0:b560d4d15292 983 printf("new_hi=%d\r\n", new_hi);
clemente 0:b560d4d15292 984 }
clemente 0:b560d4d15292 985 /* edges enhancement */
clemente 0:b560d4d15292 986 if ( c=='e') {
clemente 0:b560d4d15292 987 edges_val-=0.1;
clemente 0:b560d4d15292 988 if ( edges_val<0)
clemente 0:b560d4d15292 989 edges_val=0;
clemente 0:b560d4d15292 990 printf("edges_val=%1.2f\r\n", edges_val);
clemente 0:b560d4d15292 991 }
clemente 0:b560d4d15292 992 if ( c=='E') {
clemente 0:b560d4d15292 993 edges_val+=0.1;
clemente 0:b560d4d15292 994 if ( edges_val>1)
clemente 0:b560d4d15292 995 edges_val=1;
clemente 0:b560d4d15292 996 printf("edges_val=%1.2f\r\n", edges_val);
clemente 0:b560d4d15292 997 }
clemente 0:b560d4d15292 998 //
clemente 0:b560d4d15292 999 if ( c=='m') {
clemente 0:b560d4d15292 1000 masktype+=1;
clemente 0:b560d4d15292 1001 if ( masktype>3)
clemente 0:b560d4d15292 1002 masktype=1;
clemente 0:b560d4d15292 1003 printf("masktype=%d\r\n", masktype);
clemente 0:b560d4d15292 1004 }
clemente 0:b560d4d15292 1005 //
clemente 0:b560d4d15292 1006 if ( c=='g') {
clemente 0:b560d4d15292 1007 gammaval+=1;
clemente 0:b560d4d15292 1008 if ( gammaval>3)
clemente 0:b560d4d15292 1009 gammaval=0;
clemente 0:b560d4d15292 1010 printf("gammaval=%d\r\n", gammaval);
clemente 0:b560d4d15292 1011 }
clemente 0:b560d4d15292 1012 }
clemente 0:b560d4d15292 1013
clemente 0:b560d4d15292 1014 unsigned char mv=optical.readmotion();
clemente 0:b560d4d15292 1015 sprintf(buf, "SQUAL:%d, dX:%+d, dY:%+d, Motion:0x%X ", optical.surfacequality(), optical.deltaX, optical.deltaY, mv);
clemente 0:b560d4d15292 1016 lcd.lcd_drawstr( buf, 0, 200, lcd.lcd_RGB( 0, 255, 0));
clemente 0:b560d4d15292 1017
clemente 0:b560d4d15292 1018 sprintf(buf, "AvrPxl:%d, MxPxl:%d ", optical.averagepixel(), optical.maxpixelval() );
clemente 0:b560d4d15292 1019 lcd.lcd_drawstr( buf, 0, 220, lcd.lcd_RGB( 0, 255, 0));
clemente 0:b560d4d15292 1020
clemente 0:b560d4d15292 1021 optical.pixeldump( &tmpmap[0]);
clemente 0:b560d4d15292 1022
clemente 0:b560d4d15292 1023 if ( gammaval) {
clemente 0:b560d4d15292 1024 gammacorrection( &tmpmap[0], gammaval);
clemente 0:b560d4d15292 1025 }
clemente 0:b560d4d15292 1026
clemente 0:b560d4d15292 1027 // pixelmap has the correct order: pos 0 is the left,upper image position.
clemente 0:b560d4d15292 1028 // Refer to the DS pag:35 about how to display the array
clemente 0:b560d4d15292 1029 c=0;
clemente 0:b560d4d15292 1030 subidx=0xFF;
clemente 0:b560d4d15292 1031 for( i=0;i<16;i++) {
clemente 0:b560d4d15292 1032 idx=subidx;
clemente 0:b560d4d15292 1033 for ( ii=0; ii<16; ii++) {
clemente 0:b560d4d15292 1034 pxlmap[c++]=tmpmap[idx];
clemente 0:b560d4d15292 1035 idx-=16;
clemente 0:b560d4d15292 1036 }
clemente 0:b560d4d15292 1037 subidx--;
clemente 0:b560d4d15292 1038 }
clemente 0:b560d4d15292 1039
clemente 0:b560d4d15292 1040 // Use the feature geometry only for implementing the bilinear better viewing.
clemente 0:b560d4d15292 1041 geometry( &pxlmap[0], &tmpmap[0],
clemente 0:b560d4d15292 1042 0.0, // angle
clemente 0:b560d4d15292 1043 0.0, 0.0, // streatch x, y
clemente 0:b560d4d15292 1044 0.0, 0.0, // displace x, y
clemente 0:b560d4d15292 1045 0.0, 0.0, // cross x, y
clemente 0:b560d4d15292 1046 1, // bilinear ON/OFF
clemente 0:b560d4d15292 1047 16, 16); // rows, cols
clemente 0:b560d4d15292 1048
clemente 0:b560d4d15292 1049 // I copy the correct image in the array pxlmap to use it as a basis for successive processing.
clemente 0:b560d4d15292 1050 for ( i=0; i<(16*16); i++)
clemente 0:b560d4d15292 1051 pxlmap[i] = tmpmap[i];
clemente 0:b560d4d15292 1052
clemente 0:b560d4d15292 1053 // 1
clemente 0:b560d4d15292 1054 magnify( &tmpmap[0], 20, 20);
clemente 0:b560d4d15292 1055
clemente 0:b560d4d15292 1056 //
clemente 0:b560d4d15292 1057 for( i=0;i<256;i++) {
clemente 0:b560d4d15292 1058 tmpmap[i]=pxlmap[i];
clemente 0:b560d4d15292 1059 }
clemente 0:b560d4d15292 1060
clemente 0:b560d4d15292 1061 // 2
clemente 0:b560d4d15292 1062 color_enhancement( &tmpmap[0]);
clemente 0:b560d4d15292 1063 magnify( &tmpmap[0], 120, 20);
clemente 0:b560d4d15292 1064
clemente 0:b560d4d15292 1065 //
clemente 0:b560d4d15292 1066 for( i=0;i<256;i++) {
clemente 0:b560d4d15292 1067 tmpmap[i]=pxlmap[i];
clemente 0:b560d4d15292 1068 }
clemente 0:b560d4d15292 1069
clemente 0:b560d4d15292 1070 // 3
clemente 0:b560d4d15292 1071 edges_enhancement( &tmpmap[0]);
clemente 0:b560d4d15292 1072 magnify( &tmpmap[0], 220, 20);
clemente 0:b560d4d15292 1073
clemente 0:b560d4d15292 1074 // 4
clemente 0:b560d4d15292 1075 quick_edge( &pxlmap[0], &tmpmap[0], thrshld);
clemente 0:b560d4d15292 1076 magnify( &tmpmap[0], 20, 100);
clemente 0:b560d4d15292 1077
clemente 0:b560d4d15292 1078 // 5
clemente 0:b560d4d15292 1079 perform_convolution( &pxlmap[0], &tmpmap[0], masktype, thrshld);
clemente 0:b560d4d15292 1080 magnify( &tmpmap[0], 120, 100);
clemente 0:b560d4d15292 1081
clemente 0:b560d4d15292 1082 // 6
clemente 0:b560d4d15292 1083 // visualizzo l'immagine originale...
clemente 0:b560d4d15292 1084 magnify( &pxlmap[0], 220, 100);
clemente 0:b560d4d15292 1085
clemente 0:b560d4d15292 1086 }
clemente 0:b560d4d15292 1087
clemente 0:b560d4d15292 1088 while(1) {
clemente 0:b560d4d15292 1089 myled = 1;
clemente 0:b560d4d15292 1090 wait(0.2);
clemente 0:b560d4d15292 1091 myled = 0;
clemente 0:b560d4d15292 1092 wait(0.2);
clemente 0:b560d4d15292 1093 }
clemente 0:b560d4d15292 1094 }
clemente 0:b560d4d15292 1095
clemente 0:b560d4d15292 1096 /* use the geometry function to magnify the image. */
clemente 0:b560d4d15292 1097 void magnify( unsigned char *pxlmap, unsigned int x, unsigned int y)
clemente 0:b560d4d15292 1098 {
clemente 0:b560d4d15292 1099 unsigned int r, c;
clemente 0:b560d4d15292 1100 float xy_str=(float)64/16;
clemente 0:b560d4d15292 1101 unsigned char tmpmap[256];
clemente 0:b560d4d15292 1102
clemente 0:b560d4d15292 1103 // inizio ciclo...
clemente 0:b560d4d15292 1104 for ( r=0; r<16; r+=4) {
clemente 0:b560d4d15292 1105 for ( c=0; c<16; c+=4) {
clemente 0:b560d4d15292 1106 // eseguo lo zoom sull'immagine...
clemente 0:b560d4d15292 1107 geometry( &pxlmap[0], &tmpmap[0],
clemente 0:b560d4d15292 1108 0.0, // angle
clemente 0:b560d4d15292 1109 xy_str, xy_str, // streatch x, y
clemente 0:b560d4d15292 1110 (float)c, (float)r, // displace x, y
clemente 0:b560d4d15292 1111 0.0, 0.0, // cross x, y
clemente 0:b560d4d15292 1112 1, // bilinear ON/OFF
clemente 0:b560d4d15292 1113 16, 16); // rows, cols
clemente 0:b560d4d15292 1114 // la visualizzo...
clemente 0:b560d4d15292 1115 int idx=0;
clemente 0:b560d4d15292 1116 for( int i=0;i<16;i++) {
clemente 0:b560d4d15292 1117 for ( int ii=0; ii<16; ii++) {
clemente 0:b560d4d15292 1118 lcd.lcd_drawpixel( x+((c/4)*16)+ii, y+((r/4)*16)+i, lcd.lcd_RGB( tmpmap[idx],tmpmap[idx],tmpmap[idx]) );
clemente 0:b560d4d15292 1119 idx++;
clemente 0:b560d4d15292 1120 }
clemente 0:b560d4d15292 1121 }
clemente 0:b560d4d15292 1122 }
clemente 0:b560d4d15292 1123 }
clemente 0:b560d4d15292 1124 }