/* hough-cor.c - Edouard Thiel - 3/06/2001 Compilation : cc bsutil.c hough-cor.c -o hough-cor \ `~/helium/helium-cfg --cflags --libs` -lm Exécution : hough-cor traits1.pgm But du TP : - Programmer la transformée de Hough pour détecter des segments. - L'interface du programme est entièrement fournie. - Les fonctions à compléter sont toutes dans la partie "Algorithmes". */ #include #include #include "bsutil.h" He_node *princ, *panel1, *canvas1, *text1, *text2, *text3, *sub2, *panel2, *canvas2, *panel3, *mess2; int c_gris, c_rouge, c_vert, c_bleu, c_jaune, c_cyan, c_magenta; BsMap *bm_orig = NULL, *bm_res1 = NULL; XImage *xi_orig = NULL, *xi_res1 = NULL; int max_ro; /*--------------------------- A F F I C H A G E ------------------------------*/ int c_gris, c_rouge, c_vert, c_bleu, c_jaune, c_cyan, c_magenta; void init_couleurs () { c_gris = HeAllocRgb (150, 150, 150, he_white); c_rouge = HeAllocRgb (255, 0, 0, he_black); c_vert = HeAllocRgb (0, 255, 0, he_black); c_bleu = HeAllocRgb (0, 0, 255, he_black); c_jaune = HeAllocRgb (255, 255, 0, he_black); c_cyan = HeAllocRgb (0, 255, 255, he_black); c_magenta = HeAllocRgb (255, 0, 255, he_black); } /* * Dessins de base */ void couleur (int coul) { XSetForeground (he_display, he_gc, coul); } void dessin_ligne (Window win, int x1, int y1, int x2, int y2) { XDrawLine (he_display, win, he_gc, x1, y1, x2, y2); } /*-------------------------- A L G O R I T H M E S ---------------------------*/ /* * Calcule le points d'intersection IA et IB d'une droite polaire avec un * rectangle. * * Le rectangle a pour sommets 0,0 et larg-1,haut-1 ; La droite est définie * par rho et theta (en degrés), qui sont donnés par rapport au centre * (xC,yC) du rectangle. Les points d'intersection avec la boîte seront * stockés dans *xia,*yia et *xib,*yib. * * Rappel : l'équation de la droite polaire par rapport à (xC,yC) est : * * rho = (x-xC)*cos(theta) +(y-yC)*sin(theta) * * Eliminer d'abord les cas particuliers (cos = 0 ou sin = 0) ; calculer * ensuite les intersections avec les bords horizontaux (c'est-à-dire * calculer *xia et *xib en fixant *yia = 0 et *yib = haut-1); enfin, si * *xia est en dehors de la boîte, calculer l'intersection avec le bord * vertical en 0 ou en larg-1 ; procéder de même avec *xib. */ void intersection_boite (int larg, int haut, double rho, double theta, double *xia, double *yia, double *xib, double *yib) { double a = theta * M_PI / 180, c = cos(a), s = sin(a), xC = larg/2, yC = haut/2; /* Cas particuliers */ if (c == 0) { *xia = 0; *xib = larg-1; *yia = *yib = rho/s + yC; } else if (s == 0) { *yia = 0; *yib = haut-1; *xia = *xib = rho/c + xC; } else { /* Intersections avec bords horizontaux */ *yia = 0; *xia = (rho - (*yia - yC)*s)/c + xC; *yib = haut-1; *xib = (rho - (*yib - yC)*s)/c + xC; /* Intersection avec bords verticaux */ if (*xia < 0) { *xia = 0; *yia = (rho - (*xia - xC)*c)/s + yC; } else if (*xia >= larg) { *xia = larg-1; *yia = (rho - (*xia - xC)*c)/s + yC; } if (*xib < 0) { *xib = 0; *yib = (rho - (*xib - xC)*c)/s + yC; } else if (*xib >= larg) { *xib = larg-1; *yib = (rho - (*xib - xC)*c)/s + yC; } } } void trace_droite_polaire (Window win, int larg, int haut, double rho, double theta) { double xia, yia, xib, yib; intersection_boite (larg, haut, rho, theta, &xia, &yia, &xib, &yib); dessin_ligne (win, xia+0.5, yia+0.5, xib+0.5, yib+0.5); } /* * Calcule la transformée de Hough de bm_orig dans bm_res1. * * On considère les points > 0 dans bm_orig. * On initalise bm_res1 à 0, puis on met à 255 les points transformés. * La fenêtre de balayage autour d'un point x,y est * [x-d2..x+d2][y-d2..y+d2] moins les points de ]x-d1..x+d1[]y-d1..y+d1[. * On considère que rho est entre -diamètre(bm_orig)/2 et +diamètre(bm_orig)/2, * et que theta est entre -90 et +90 degrés (l'origine rho=0, theta=0 est * au centre de bm_res1). */ void calcul_hough (BsMap *bm_orig, BsMap *bm_res1, int d1, int d2) { int xp, yp, xmin, xmax, ymax, xq, yq ; double dx, dy, rho, theta, xC = bm_orig->xsiz/2, yC = bm_orig->ysiz/2, xD = bm_res1->xsiz/2, yD = bm_res1->ysiz/2; InitWholeBsMap (bm_res1, 0); for (yp = 0; yp < bm_orig->ysiz; yp++) for (xp = 0; xp < bm_orig->xsiz; xp++) if (bm_orig->tab[yp][xp] > 0) { xmin = xp-d2 ; if (xmin < 0) xmin = 0; xmax = xp+d2+1; if (xmax > bm_orig->xsiz) xmax = bm_orig->xsiz; ymax = yp+d2+1; if (ymax > bm_orig->ysiz) ymax = bm_orig->ysiz; for (yq = yp; yq < ymax; yq++) for (xq = xmin; xq < xmax; xq++) { dx = xq-xp; dy = yq-yp; if (fabs(dx) >= d1 || fabs(dy) >= d1) if (bm_orig->tab[yq][xq] > 0) { /* Aire signée */ rho = ((xp-xC)*(yq-yC) - (xq-xC)*(yp-yC)) / sqrt (dx*dx + dy*dy); if (dy == 0) theta = (dx < 0) ? 90 : -90; else theta = -atan (dx/dy) * 180 / M_PI; bm_res1->tab[(int)(theta+yD)][(int)(rho+xD)] = 255; } } } } /*--------------------------- C A L L B A C K S ------------------------------*/ void calcul_proc (He_node *hn) { calcul_hough (bm_orig, bm_res1, atoi(HeGetTextValue(text2)), atoi(HeGetTextValue(text3))); FreeXImage (xi_res1); xi_res1 = NewXImageFromBsMap (bm_res1, LUT_GREY); HePostRepaint (canvas2); } void quit_proc (He_node *hn) { HeQuit(0); } void lire_proc (He_node *hn) { char *nomf = HeGetTextValue (text1); /* Destruction anciennes données */ FreeBsMap (bm_orig); bm_orig = NULL; FreeBsMap (bm_res1); bm_res1 = NULL; /* Lecture */ bm_orig = ReadBsMapFromPGM (nomf, 0); /* Test réussite */ if (bm_orig == NULL) { HeSimpleDialog ( HE_DIALOG_BELL, HE_DIALOG_TITLE, "Attention", HE_DIALOG_MESSAGE, "Erreur de lecture du fichier", HE_DIALOG_QUOTED, nomf, HE_DIALOG_BUTTON, "OK", 0); return; } /* Création de bm_res1 */ max_ro = sqrt (bm_orig->xsiz*bm_orig->xsiz + bm_orig->ysiz*bm_orig->ysiz); bm_res1 = NewBsMap (181, max_ro, 0); if (bm_res1 == NULL) HeQuit(1); /* Taille canvas1 et fenêtre princ */ HeSetWidth (canvas1, bm_orig->xsiz); HeSetHeight (canvas1, bm_orig->ysiz); HeSetX (canvas1, 0); HeFit (princ); HeSetX (canvas1, (HeGetWidth(princ) - HeGetWidth(canvas1)-2)/2); /* Taille canvas2 et fenêtre sub2 */ HeSetWidth (canvas2, bm_res1->xsiz); HeSetHeight (canvas2, bm_res1->ysiz); HeSetX (canvas2, 0); HeJustify (canvas2, panel2, HE_TOP); HeJustify (panel3, canvas2, HE_TOP); HeFit (sub2); HeSetX (canvas2, (HeGetWidth(sub2) - HeGetWidth(canvas2)-2)/2); /* XImages */ FreeXImage (xi_orig); FreeXImage (xi_res1); xi_orig = NewXImageFromBsMap (bm_orig, LUT_GREY); xi_res1 = NewXImageFromBsMap (bm_res1, LUT_GREY); HePostRepaint (canvas1); HePostRepaint (canvas2); } void canvas1_repaint (He_node *hn, Window win) { PaintXImage (xi_orig, win); } void canvas2_repaint (He_node *hn, Window win) { PaintXImage (xi_res1, win); } void canvas2_event (He_node *hn, He_event *hev) { switch (hev->type) { case ButtonPress : case MotionNotify : { char bla[100]; double rho, theta; if (hev->sb == 0) break; if (hev->sx < 0 || hev->sx >= bm_res1->xsiz || hev->sy < 0 || hev->sy >= bm_res1->ysiz) break; rho = hev->sx - HeGetWidth (canvas2)/2; theta = hev->sy - HeGetHeight (canvas2)/2; sprintf (bla, "rho = %.0f theta = %.0f", rho, theta); HeSetMessageLabel (mess2, bla); PaintXImage (xi_orig, HeGetWindow (canvas1)); couleur (c_rouge); trace_droite_polaire (HeGetWindow (canvas1), HeGetWidth (canvas1), HeGetHeight (canvas1), rho, theta ); } break; } } void tog1_proc (He_node *hn) { HeSetShow (sub2, HeGetToggleValue (hn)); } /*--------------------------------- M A I N ----------------------------------*/ int main (int argc, char **argv) { int code_sortie; HeInit (&argc, &argv); if (argc != 2){ printf ("USAGE : %s image.pgm\n", argv[0]); HeQuit(1); } init_couleurs (); princ = HeCreateFrame (); HeSetFrameLabel (princ, "Hough - image binaire (cor)"); panel1 = HeCreatePanel (princ); HeCreateMessageP (panel1, "Image", TRUE); text1 = HeCreateText (panel1); HeSetTextVisibleLen (text1, 28); HeSetTextValue (text1, argv[1]); HeSetTextCompletion (text1, TRUE); HeSetTextNotifyProc (text1, lire_proc); HeSetPanelLayout (panel1, HE_LINE_FEED); HeCreateButtonP (panel1, "Lire", lire_proc, NULL); HeCreateToggleLedP (panel1, "Transformation", tog1_proc, FALSE); HeCreateButtonP (panel1, "Quit", quit_proc, NULL); HeFit (panel1); canvas1 = HeCreateCanvas (princ); HeSetCanvasRepaintProc (canvas1, canvas1_repaint); HeJustify (canvas1, panel1, HE_TOP); HeFit (princ); sub2 = HeCreateFrame (); HeSetFrameLabel (sub2, "Hough - transformée"); panel2 = HeCreatePanel (sub2); HeCreateMessageP (panel2, "d1 :", TRUE); text2 = HeCreateText (panel2); HeSetTextVisibleLen (text2, 4); HeSetTextValue (text2, "3"); HeSetTextNotifyProc (text2, calcul_proc); HeCreateMessageP (panel2, "d2 :", TRUE); text3 = HeCreateText (panel2); HeSetTextVisibleLen (text3, 4); HeSetTextValue (text3, "6"); HeSetTextNotifyProc (text3, calcul_proc); HeCreateButtonP (panel2, "Calcul", calcul_proc, NULL); HeFit (panel2); canvas2 = HeCreateCanvas (sub2); HeSetCanvasRepaintProc (canvas2, canvas2_repaint); HeSetCanvasEventProc (canvas2, canvas2_event); panel3 = HeCreatePanel (sub2); mess2 = HeCreateMessageP (panel3, "Cliquez dans cette fenêtre", FALSE); HeFit (panel3); HeJustify (canvas2, panel2, HE_TOP); HeJustify (panel3, canvas2, HE_TOP); HeFit (sub2); init_couleurs (); lire_proc (NULL); code_sortie = HeMainLoop (princ); FreeBsMap (bm_orig); FreeBsMap (bm_res1); FreeXImage (xi_orig); FreeXImage (xi_res1); return code_sortie; }