2014년 12월 17일 수요일

Circel detection (hough transform)


허프변환을 이용하여 circle을 찾는다. 라플라시안 엣지를 추출하여 픽셀마다 원을 그려준다. 원 가장자리 픽셀마다 원을 그려주게되면 원끼리 겹친다. 이때 픽셀의 밝기를 +1씩 증가시켜주면 가장 밝은 곳이 원의 중심이 된다. 물론 중심을 찾기위해서는 원의 반지름을 적절하게 넣어주어야 한다.


cos%5Ccombi%20%7B%20%5Ctheta%20%20%7D%3D%5Cfrac%20%7B%20x%20%7D%7B%20r%20%7D%3D%3Ex%3Dr*cos%5Ccombi%20%7B%20%5Ctheta%20%20%7D%20
sin%5Ccombi%20%7B%20%5Ctheta%20%20%7D%3D%5Cfrac%20%7B%20y%20%7D%7B%20r%20%7D%3D%3Ey%3Dr*sin%5Ccombi%20%7B%20%5Ctheta%20%20%7D%20
위의 식을 이용하여 픽셀마다 원을 그려준다. x좌표에 i, y좌표에 j를 더해주었는데 이는 좌표의 시작점을 가리킨다.



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
#include <opencv\cv.h>
#include <opencv\highgui.h>
#include <math.h>
 
void main()
{
 
    // Create other image plane
    IplImage* image = cvLoadImage("circle.jpg",1);
    int i, j, k, wi, hi, rwsize;
    wi = image->width;
    hi = image->height;
    rwsize = image->widthStep;
    IplImage* edgeimage = cvCreateImage(cvSize( wi, hi ), IPL_DEPTH_8U, 3);
    IplImage* tempimage = cvCreateImage(cvSize( wi, hi ), IPL_DEPTH_8U, 3);
    for(i=0; i<hi; ++i)
        for(j=0; j<wi; ++j)
            for(k=0; k<3; ++k)
                edgeimage->imageData[i*rwsize+j*3+k] = tempimage->imageData[i*rwsize+j*3+k] = 0;
 
 
    // Graysclae
    for(i=0; i<hi; ++i)
        for(j=0; j<wi; ++j)
            image->imageData[i*rwsize+j*3+2] = (unsigned char)(((int)image->imageData[i*rwsize+j*3+2]+(int)image->imageData[i*rwsize+j*3+1]+(int)image->imageData[i*rwsize+j*3+0])/3);
 
    // cvShowImage( "image",image );  
 
 
    ////라플라시안 edge 
    //int laplacianMask[3][3] = {-1,-1,-1,-1,8,-1,-1,-1,-1};
    //int THD = 0;
    //int edge;
    //for(int i=1;i<hi-1;i++){
    // for(int j=1;j<wi-1;j++){
    //  edge = 0;   
    //  for(int x=-1;x<2;x++){
    //   for(int y=-1;y<2;y++){
    //    edge += image->imageData[(i+x)*rwsize+(j+y)*3]*laplacianMask[x+1][y+1];
    //   }
    //  }
    //  //edge 값이 threshold 보다 크면 edgeimage에 그려줌
    //  if(edge > THD)
    //   edgeimage->imageData[i*rwsize+j*3+0] =edgeimage->imageData[i*rwsize+j*3+1] =edgeimage->imageData[i*rwsize+j*3+2] = 255;
    // }
 
    //}
    cvLaplace(image, edgeimage, 3);
 
    // cvShowImage( "edge", edgeimage );  
 
    // Draw Circle to Hough Plane
    double r = 135;
    double angle = 0;
    int count = 0;
 
    for(i=1; i<hi-1; ++i)
        for(j=1; j<wi-1; ++j)
            if (edgeimage->imageData[i*rwsize+j*3] != 0) //흰색이라면
            {
                angle = 0; //각도 초기화
                while(angle<360) //한바퀴
                {
                    int x = r * cos((double)angle) + i; //여기서 i, j는 시작지점을 말한다.
                    int y = r * sin((double)angle) + j;
                    if (x>=0 && x<hi && y>=0 && y<wi) //그림 크기 안에서
                        tempimage->imageData[x*rwsize+y*3+0] = tempimage->imageData[x*rwsize+y*3+1] = tempimage->imageData[x*rwsize+y*3+2] = 255;
                    angle = angle + 0.1;
                }
 
                for(int ti=0; ti<hi; ++ti)
                    for(int tj=0; tj<wi; ++tj)
                    {
                        if(tempimage->imageData[ti*rwsize+tj*3] != 0) //검은색이 아닌 어떤 픽셀이 존재한다면
                            for(int tk=0; tk<3; ++tk)
                                image->imageData[ti*rwsize+tj*3+tk]++; //grayscale된 이미지의 r,g,b값을 각각 증가시킴
 
                        tempimage->imageData[ti*rwsize+tj*3] = 0; //r,g,b에서 b값만 0이되고 나머지는 255이므로 노란색이 나옴
                        //위의 if문에서 중복하여 읽지 않도록 0으로 초기화한다
                    }
 
            }
 
            // cvShowImage( "exchangedimage", image );  
 
            //Find Maximum Point
            int mx = 0;
            int centeri, centerj;
            centeri = centerj = 0;
 
            for(i=1; i<hi-1; ++i)
                for(j=1; j<wi-1; ++j)
                {
                    if (mx < (image->imageData[i*rwsize+j*3+2]+image->imageData[i*rwsize+j*3+1]+image->imageData[i*rwsize+j*3+0])/3)
                    {
                        mx = (image->imageData[i*rwsize+j*3+2]+image->imageData[i*rwsize+j*3+1]+image->imageData[i*rwsize+j*3+0])/3;
                        centeri = i;
                        centerj = j;
                    }
                }
 
                // Draw Result Circle
                printf("%d",mx);
                cvCircle(image, cvPoint(centerj,centeri), (int)r, cvScalar(0,0,255));
                cvCircle(image, cvPoint(centerj,centeri), (int)1, cvScalar(0,0,255));
 
                cvShowImage("finalimage", image);
 
                cvWaitKey(0);                   
}

댓글 없음:

댓글 쓰기