Programming/Image Processing

[OpenCV] Labeling 응용(가장 많은 화소 Label만 남기기) Source Code

DevMonster 2014. 2. 2. 20:04

OpenCV의 Mat Format을 사용한 Source Code
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
void extractMainLabel(Mat input, int row, int col)
{
    int x, y, top;
    short l_no = 0, r, c, m, n;
 
    unsigned char *m_ResultImg;
    m_ResultImg = (unsigned char*)malloc(sizeof(unsigned char)*row*col);
 
    unsigned char *arr;
    arr = (unsigned char*)malloc(sizeof(unsigned char)*row*col);
 
    // 스택으로 사용할 메모리 할당
    short *stack_x;
    short *stack_y;
 
    stack_x = (short *)malloc(sizeof(short)*row*col);
    stack_y = (short *)malloc(sizeof(short)*row*col);
 
    // 속도개선을 위하여 배열에 Mat Pixel 값을 복사
    for( y = 0 ; y < row ; y ++ ){
        for( x = 0 ; x < col ; x++ ){
            *(arr+(col*y)+x) = input.at<uchar>(y,x);
        }
    }
 
    // 결과 이미지 배열 초기화
    for(y=0; y<row; y++){
        for(x=0; x<col; x++) *(m_ResultImg+(col*y)+x) = 0;
    }
 
    for(y=0; y<row; y++){
        for(x=0; x<col; x++) {
            // 이미 방문한 점이거나 픽셀값이 255가 아니면처리하지 않음
            if(*(arr+(col*y)+x) != 255 ||*(m_ResultImg+(col*y)+x) != 0) continue;
 
            r=y;
            c=x;
            top=0;
            l_no++;
 
            while(1){        
                for(m=r-1; m<=r+1; m++){
                    if(m<0 || m>row-1) continue
 
                    for(n=c-1; n<=c+1; n++){
                        if(n<0 || n>col-1) continue
                        if(*(arr+(col*m)+n) != 255 || *(m_ResultImg+(col*m)+n) != 0) continue;
 
                        // l_no: Labeling Number(Label Key)
                        *(m_ResultImg+(col*m)+n) = (unsigned char)l_no;
                        if(Push(stack_x, stack_y, m, n, &top) == -1) continue;
 
                    }
                }
                if(Pop(stack_x, stack_y, &r, &c, &top) == -1) break;
            }
        }
    }
 
 
 
 
    //**************** 수정부분 시작
    int max_ln = 0;            // 가장 많은 픽셀을 갖고 있는 Labeling number
    int* max_px;
    max_px = new int[(int)l_no+1];
 
    for(int i = 0 ; i <= l_no ; i ++){
        max_px[i] = 0;
    }
 
    // Labeling Pixel 저장
    for(y=0; y<row; y++){
        for(x=0; x<col; x++){
            if(*(m_ResultImg+(col*y)+x) == 0) continue;
            max_px[*(m_ResultImg+(col*y)+x)]++;
        }
    }
 
 
    // 가장 큰 Label Number 저장
    forint i = 1; i < l_no - 1 ; i ++ ){
        if(max_px[max_ln] < max_px[i]) max_ln = i;
    }
 
    // 가장 큰 영역을 남기고 제거(가장 큰 영역은 흰색으로)
    for(y=0; y<row; y++){
        for(x=0; x<col; x++){
            if(*(m_ResultImg+(col*y)+x) == 0) continue;
            if(*(m_ResultImg+(col*y)+x) == max_ln) *(m_ResultImg+(col*y)+x) = 255;
            else    
                *(m_ResultImg+(col*y)+x) = 0;
        }
    }
    delete[] max_px;
    //**************** 수정부분 종료
 
 
    // Labeling Number로 나누어 색 변환
    /*float l_gap = 250.0f / (float)l_no;
    for(y=0; y<row; y++){
        for(x=0; x<col; x++){
            *(m_ResultImg+(col*y)+x) *= (unsigned char)l_gap;
        }
    }*/
 
    for( y = 0 ; y < row ; y ++ ){
        for( x = 0 ; x < col ; x++ ){
            input.at<uchar>(y,x) = *(m_ResultImg+(col*y)+x);
        }
    }
 
    free(arr);
    free(m_ResultImg);
    free(stack_x);
    free(stack_y);
 
 
}


Stack overflow 방지를 위한 Stack 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int Push(short* st_x, short* st_y, short xx, short yy, int* top)
{
    if(*top>=65536) return(-1);
    (*top)++;
    st_x[*top] = xx;
    st_y[*top] = yy;
    return(1);
}
 
int Pop(short* st_x, short* st_y, short* xx, short* yy, int* top)
{
    if(*top == 0) return(-1);
    *xx = st_x[*top];
    *yy = st_y[*top];
    (*top)--;
    return(1);
}


728x90
반응형