호출방법: Thinning(&배열이름, 행의 수, 열의 수);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | void Thinning(unsigned char *arr, int row, int col) { int x, y, p, q, xp, yp, xm, ym, cc, cd; int np1, sp1, hv; int cnt=0, chk=0, flag=0; // 들어오는 배열과 같은 크기의 배열을 선언 및 복사 unsigned char *m_BufImage; unsigned char *m_ResultImg; m_BufImage = (unsigned char*)malloc(sizeof(unsigned char)*row*col); m_ResultImg = (unsigned char*)malloc(sizeof(unsigned char)*row*col); memcpy(m_ResultImg, arr, sizeof(unsigned char) * row * col); do{ // Image Buffer를 0으로 셋팅 for( y = 1 ; y < row-1 ; y ++ ){ for( x = 1 ; x < col-1 ; x++ ){ *(m_BufImage+(col*y)+x) = 0; } } // 천이 추출 if(chk == 0) flag = 0; chk = cnt % 2; cnt ++; for( y = 1 ; y < row-1 ; y ++ ){ ym = y - 1; yp = y + 1; for( x = 1 ; x < col-1 ; x ++ ){ if(*(m_ResultImg+(col*y)+x) == 0) continue; np1 = 0; for(q = y-1 ; q <= y+1; q ++ ){ for(p = x-1 ; p <= x+1; p ++ ){ if(*(m_ResultImg+(col*q)+p) != 0) np1++; } } if(np1 < 3 || np1 > 7){ *(m_BufImage+(col*y)+x) = 255; continue; } xm = x - 1; xp = x + 1; sp1 = 0; if(*(m_ResultImg+(col*ym)+x) == 0 && *(m_ResultImg+(col*ym)+xp) != 0) sp1++; if(*(m_ResultImg+(col*ym)+xp) == 0 && *(m_ResultImg+(col*y)+xp) != 0) sp1++; if(*(m_ResultImg+(col*y)+xp) == 0 && *(m_ResultImg+(col*yp)+xp) != 0) sp1++; if(*(m_ResultImg+(col*yp)+xp) == 0 && *(m_ResultImg+(col*yp)+x) != 0) sp1++; if(*(m_ResultImg+(col*yp)+x) == 0 && *(m_ResultImg+(col*yp)+xm) != 0) sp1++; if(*(m_ResultImg+(col*yp)+xm) == 0 && *(m_ResultImg+(col*y)+xm) != 0) sp1++; if(*(m_ResultImg+(col*y)+xm) == 0 && *(m_ResultImg+(col*ym)+xm) != 0) sp1++; if(*(m_ResultImg+(col*ym)+xm) == 0 && *(m_ResultImg+(col*ym)+x) != 0) sp1++; if(sp1 != 1){ *(m_BufImage+(col*y)+x) = 255; continue; } if(chk == 0){ cc = *(m_ResultImg+(col*ym)+x) * *(m_ResultImg+(col*y)+xp); cc = cc * *(m_ResultImg+(col*yp)+x); cd = *(m_ResultImg+(col*y)+xp) * *(m_ResultImg+(col*yp)+x); cd = cd * *(m_ResultImg+(col*y)+xm); } else{ cc = *(m_ResultImg+(col*ym)+x) * *(m_ResultImg+(col*y)+xp); cc = cc * *(m_ResultImg+(col*y)+xm); cd = *(m_ResultImg+(col*ym)+x) * *(m_ResultImg+(col*yp)+x); cd = cd * *(m_ResultImg+(col*y)+xm); } if(cc != 0 || cd != 0){ *(m_BufImage+(col*y)+x) = 255; continue; } flag = 1; } } for( y = 1 ; y < row-1 ; y ++ ){ for( x = 1 ; x < col-1 ; x ++ ){ *(m_ResultImg+(col*y)+x) = *(m_BufImage+(col*y)+x); } } }while(!(chk == 1 && flag == 0)); // 4연결점 처리 for( y = 1 ; y < row-1 ; y ++ ){ yp = y + 1; ym = y - 1; for( x = 1 ; x < col-1 ; x ++ ){ if(*(m_ResultImg+(col*y)+x) == 0) continue; xm = x - 1; xp = x + 1; sp1 = 0; if(*(m_ResultImg+(col*ym)+x) == 0 && *(m_ResultImg+(col*ym)+xp) != 0) sp1++; if(*(m_ResultImg+(col*ym)+xp) == 0 && *(m_ResultImg+(col*y)+xp) != 0) sp1++; if(*(m_ResultImg+(col*y)+xp) == 0 && *(m_ResultImg+(col*yp)+xp) != 0) sp1++; if(*(m_ResultImg+(col*yp)+xp) == 0 && *(m_ResultImg+(col*yp)+x) != 0) sp1++; if(*(m_ResultImg+(col*yp)+x) == 0 && *(m_ResultImg+(col*yp)+xm) != 0) sp1++; if(*(m_ResultImg+(col*yp)+xm) == 0 && *(m_ResultImg+(col*y)+xm) != 0) sp1++; if(*(m_ResultImg+(col*y)+xm) == 0 && *(m_ResultImg+(col*ym)+xm) != 0) sp1++; if(*(m_ResultImg+(col*ym)+xm) == 0 && *(m_ResultImg+(col*ym)+x) != 0) sp1++; hv = 0; if(sp1 == 2){ if ((*(m_ResultImg+(col*ym)+x) & *(m_ResultImg+(col*y)+xp)) != 0) hv++; else if ((*(m_ResultImg+(col*y)+xp) & *(m_ResultImg+(col*yp)+x)) != 0) hv++; else if ((*(m_ResultImg+(col*yp)+x) & *(m_ResultImg+(col*y)+xm)) != 0) hv++; else if ((*(m_ResultImg+(col*y)+xm) & *(m_ResultImg+(col*ym)+x)) != 0) hv++; if(hv == 1) *(m_ResultImg+(col*y)+x) = 0; } else if(sp1 == 3){ if ((*(m_ResultImg+(col*ym)+x) & *(m_ResultImg+(col*y)+xm) & *(m_ResultImg+(col*y)+xp)) != 0) hv++; else if ((*(m_ResultImg+(col*yp)+x) & *(m_ResultImg+(col*y)+xm) & *(m_ResultImg+(col*y)+xp)) != 0) hv++; else if ((*(m_ResultImg+(col*ym)+x) & *(m_ResultImg+(col*yp)+x) & *(m_ResultImg+(col*y)+xm)) != 0) hv++; else if ((*(m_ResultImg+(col*ym)+x) & *(m_ResultImg+(col*yp)+x) & *(m_ResultImg+(col*y)+xp)) != 0) hv++; if(hv == 1) *(m_ResultImg+(col*y)+x) = 0; } } } // 들어온 배열에 재복사 memcpy(arr, m_ResultImg, sizeof(unsigned char)*row*col); free(m_BufImage); free(m_ResultImg); } |
[출처]비젼시스템 및 실습(저자: 신동욱)
728x90
반응형
'Programming > Image Processing' 카테고리의 다른 글
[OpenCV] 2.4 이상 버전에서 SIFT + SURF 사용 설정 (3) | 2014.01.27 |
---|---|
[OpenCV] Labeling(레이블링, 라벨링) 이론 및 소스코드 (3) | 2014.01.14 |
[OpenCV] Mat을 이용한 Thinning(세선화) 구현 (0) | 2014.01.13 |
[OpenCV] Edge Detection(Canny Filter) 사용하기 예제 (0) | 2014.01.10 |
[OpenCV] Edge detection(Sobel Filter) 사용하기 예제 (1) | 2014.01.10 |