Example:Hough transform/C

From Rosetta Code
Revision as of 20:05, 19 August 2010 by rosettacode>Coderjoe (Create example page for C implementation of the Hough transform)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

C

Translation of: Tcl
Library: cairo

(Tested only with the pentagon image given) <lang c>#include <stdio.h>

  1. include <stdlib.h>
  2. include <stdint.h>
  3. include <string.h>
  4. include <math.h>
  1. include <cairo.h>
  1. ifndef M_PI
  2. define M_PI 3.1415927
  3. endif
  1. define GR(X,Y) (d[(*s)*(Y)+bpp*(X)+((2)%bpp)])
  2. define GG(X,Y) (d[(*s)*(Y)+bpp*(X)+((1)%bpp)])
  3. define GB(X,Y) (d[(*s)*(Y)+bpp*(X)+((0)%bpp)])
  4. define SR(X,Y) (ht[4*tw*((Y)%th)+4*((X)%tw)+2])
  5. define SG(X,Y) (ht[4*tw*((Y)%th)+4*((X)%tw)+1])
  6. define SB(X,Y) (ht[4*tw*((Y)%th)+4*((X)%tw)+0])
  7. define RAD(A) (M_PI*((double)(A))/180.0)

uint8_t *houghtransform(uint8_t *d, int *w, int *h, int *s, int bpp) {

 int rho, theta, y, x, W = *w, H = *h;
 int th = sqrt(W*W + H*H)/2.0;
 int tw = 360;
 uint8_t *ht = malloc(th*tw*4);
 memset(ht, 0, 4*th*tw); // black bg
 
 for(rho = 0; rho < th; rho++)
 {
   for(theta = 0; theta < tw/*720*/; theta++)
   {
     double C = cos(RAD(theta));
     double S = sin(RAD(theta));
     uint32_t totalred = 0;
     uint32_t totalgreen = 0;
     uint32_t totalblue = 0;
     uint32_t totalpix = 0;
     if ( theta < 45 || (theta > 135 && theta < 225) || theta > 315) {

for(y = 0; y < H; y++) { double dx = W/2.0 + (rho - (H/2.0-y)*S)/C; if ( dx < 0 || dx >= W ) continue; x = floor(dx+.5); if (x == W) continue; totalpix++; totalred += GR(x, y); totalgreen += GG(x, y); totalblue += GB(x, y); }

     } else {

for(x = 0; x < W; x++) { double dy = H/2.0 - (rho - (x - W/2.0)*C)/S; if ( dy < 0 || dy >= H ) continue; y = floor(dy+.5); if (y == H) continue; totalpix++; totalred += GR(x, y); totalgreen += GG(x, y); totalblue += GB(x, y); }

     }
     if ( totalpix > 0 ) {

double dp = totalpix; SR(theta, rho) = (int)(totalred/dp) &0xff; SG(theta, rho) = (int)(totalgreen/dp) &0xff; SB(theta, rho) = (int)(totalblue/dp) &0xff;

     }
   }
 }
 *h = th;   // sqrt(W*W+H*H)/2
 *w = tw;   // 360
 *s = 4*tw;
 return ht;

}

int main(int argc, char **argv) {

 cairo_surface_t *inputimg = NULL;
 cairo_surface_t *houghimg = NULL;
 
 uint8_t *houghdata = NULL, *inputdata = NULL;
 int w, h, s, bpp;
 if ( argc < 3 ) return EXIT_FAILURE;
 
 inputimg = cairo_image_surface_create_from_png(argv[1]);
 
 w = cairo_image_surface_get_width(inputimg);
 h = cairo_image_surface_get_height(inputimg);
 s = cairo_image_surface_get_stride(inputimg);  
 bpp = cairo_image_surface_get_format(inputimg);
 switch(bpp)
 {
 case CAIRO_FORMAT_ARGB32: bpp = 4; break;
 case CAIRO_FORMAT_RGB24:  bpp = 3; break;
 case CAIRO_FORMAT_A8:     bpp = 1; break;
 default:
   fprintf(stderr, "unsupported\n");
   goto destroy;
 }
 inputdata = cairo_image_surface_get_data(inputimg);
 houghdata = houghtransform(inputdata, &w, &h, &s, bpp);
 
 printf("w=%d, h=%d\n", w, h);
 houghimg = cairo_image_surface_create_for_data(houghdata,

CAIRO_FORMAT_RGB24, w, h, s);

 cairo_surface_write_to_png(houghimg, argv[2]);
 

destroy:

 if (inputimg != NULL) cairo_surface_destroy(inputimg);
 if (houghimg != NULL) cairo_surface_destroy(houghimg);
 return EXIT_SUCCESS;

}</lang>

Output image (but with white background):

Output image when input is the given Pentagon.