转地址: http://www.cnblogs.com/oomusou/archive/2008/07/23/sobel_edge_detector.html
Abstract
使用C與C++/CLI實現Sobel Edge Detector。
Introduction
演算法部分我就不多談,請參考Sobel Edge Detector。
Method 1:
sobel_edge.c / C
1
/*
2 (C) OOMusou 2007 http://oomusou.cnblogs.com
3
4 Filename : sobel_edge.c
5 Compiler : Visual C++ 8.0
6 Description : Demo the how to use sobel detector on gray level image
7 Release : 07/23/2008 1.0
8 */
9 #include < stdio.h >
10 #include < stdlib.h >
11 #include < math.h >
12
13 #define MASK_N 2
14 #define MASK_X 3
15 #define MASK_Y 3
16 #define WHITE 255
17 #define BLACK 0
18
19 unsigned char * image_s = NULL; // source image array
20 unsigned char * image_t = NULL; // target image array
21 FILE * fp_s = NULL; // source file handler
22 FILE * fp_t = NULL; // target file handler
23
24 unsigned int width, height; // image width, image height
25 unsigned int rgb_raw_data_offset; // RGB raw data offset
26 unsigned char bit_per_pixel; // bit per pixel
27 unsigned short byte_per_pixel; // byte per pixel
28
29 // bitmap header
30 unsigned char header[ 54 ] = {
31 0x42 , // identity : B
32 0x4d , // identity : M
33 0 , 0 , 0 , 0 , // file size
34 0 , 0 , // reserved1
35 0 , 0 , // reserved2
36 54 , 0 , 0 , 0 , // RGB data offset
37 40 , 0 , 0 , 0 , // struct BITMAPINFOHEADER size
38 0 , 0 , 0 , 0 , // bmp width
39 0 , 0 , 0 , 0 , // bmp height
40 1 , 0 , // planes
41 24 , 0 , // bit per pixel
42 0 , 0 , 0 , 0 , // compression
43 0 , 0 , 0 , 0 , // data size
44 0 , 0 , 0 , 0 , // h resolution
45 0 , 0 , 0 , 0 , // v resolution
46 0 , 0 , 0 , 0 , // used colors
47 0 , 0 , 0 , 0 // important colors
48 };
49
50
51 // sobel mask
52 int mask[MASK_N][MASK_X][MASK_Y] = {
53 {{ - 1 , - 2 , - 1 },
54 { 0 , 0 , 0 },
55 { 1 , 2 , 1 }},
56
57 {{ - 1 , 0 , 1 },
58 { - 2 , 0 , 2 },
59 { - 1 , 0 , 1 }}
60 };
61
62 int read_bmp( const char * fname_s) {
63 fp_s = fopen(fname_s, " rb " );
64 if (fp_s == NULL) {
65 printf( " fopen fp_s error/n " );
66 return - 1 ;
67 }
68
69 // move offset to 10 to find rgb raw data offset
70 fseek(fp_s, 10 , SEEK_SET);
71 fread( & rgb_raw_data_offset, sizeof (unsigned int ), 1 , fp_s);
72
73 // move offset to 18 to get width & height;
74 fseek(fp_s, 18 , SEEK_SET);
75 fread( & width, sizeof (unsigned int ), 1 , fp_s);
76 fread( & height, sizeof (unsigned int ), 1 , fp_s);
77
78 // get bit per pixel
79 fseek(fp_s, 28 , SEEK_SET);
80 fread( & bit_per_pixel, sizeof (unsigned short ), 1 , fp_s);
81 byte_per_pixel = bit_per_pixel / 8 ;
82
83 // move offset to rgb_raw_data_offset to get RGB raw data
84 fseek(fp_s, rgb_raw_data_offset, SEEK_SET);
85
86 image_s = (unsigned char * )malloc((size_t)width * height * byte_per_pixel);
87 if (image_s == NULL) {
88 printf( " malloc images_s error/n " );
89 return - 1 ;
90 }
91
92 image_t = (unsigned char * )malloc((size_t)width * height * byte_per_pixel);
93 if (image_t == NULL) {
94 printf( " malloc image_t error/n " );
95 return - 1 ;
96 }
97
98 fread(image_s, sizeof (unsigned char ), (size_t)( long )width * height * byte_per_pixel, fp_s);
99
100 return 0 ;
101 }
102
103 // convert RGB to gray level int
104 int color_to_int( int r, int g, int b) {
105 return (r + g + b) / 3 ;
106 }
107
108 int sobel( double threshold) {
109 unsigned int x, y, i, v, u; // for loop counter
110 unsigned char R, G, B; // color of R, G, B
111 double val[MASK_N] = { 0.0 };
112 int adjustX, adjustY, xBound, yBound;
113 double total;
114
115 for (y = 0 ; y != height; ++ y) {
116 for (x = 0 ; x != width; ++ x) {
117 for (i = 0 ; i != MASK_N; ++ i) {
118 adjustX = (MASK_X % 2 ) ? 1 : 0 ;
119 adjustY = (MASK_Y % 2 ) ? 1 : 0 ;
120 xBound = MASK_X / 2 ;
121 yBound = MASK_Y / 2 ;
122
123 val[i] = 0.0 ;
124 for (v = - yBound; v != yBound + adjustY; ++ v) {
125 for (u = - xBound; u != xBound + adjustX; ++ u) {
126 if (x + u >= 0 && x + u < width && y + v >= 0 && y + v < height) {
127 R = * (image_s + byte_per_pixel * (width * (y + v) + (x + u)) + 2 );
128 G = * (image_s + byte_per_pixel * (width * (y + v) + (x + u)) + 1 );
129 B = * (image_s + byte_per_pixel * (width * (y + v) + (x + u)) + 0 );
130
131 val[i] += color_to_int(R, G, B) * mask[i][u + xBound][v + yBound];
132 }
133 }
134 }
135 }
136
137 total = 0.0 ;
138 for (i = 0 ; i != MASK_N; ++ i) {
139 total += val[i] * val[i];
140 }
141
142 total = sqrt(total);
143
144 if (total - threshold >= 0 ) {
145 // black
146 * (image_t + byte_per_pixel * (width * y + x) + 2 ) = BLACK;
147 * (image_t + byte_per_pixel * (width * y + x) + 1 ) = BLACK;
148 * (image_t + byte_per_pixel * (width * y + x) + 0 ) = BLACK;
149 }
150 else {
151 // white
152 * (image_t + byte_per_pixel * (width * y + x) + 2 ) = WHITE;
153 * (image_t + byte_per_pixel * (width * y + x) + 1 ) = WHITE;
154 * (image_t + byte_per_pixel * (width * y + x) + 0 ) = WHITE;
155 }
156 }
157 }
158
159 return 0 ;
160 }
161
162 int write_bmp( const char * fname_t) {
163 unsigned int file_size; // file size
164
165 fp_t = fopen(fname_t, " wb " );
166 if (fp_t == NULL) {
167 printf( " fopen fname_t error/n " );
168 return - 1 ;
169 }
170
171 // file size
172 file_size = width * height * byte_per_pixel + rgb_raw_data_offset;
173 header[ 2 ] = (unsigned char )(file_size & 0x000000ff );
174 header[ 3 ] = (file_size >> 8 ) & 0x000000ff ;
175 header[ 4 ] = (file_size >> 16 ) & 0x000000ff ;
176 header[ 5 ] = (file_size >> 24 ) & 0x000000ff ;
177
178 // width
179 header[ 18 ] = width & 0x000000ff ;
180 header[ 19 ] = (width >> 8 ) & 0x000000ff ;
181 header[ 20 ] = (width >> 16 ) & 0x000000ff ;
182 header[ 21 ] = (width >> 24 ) & 0x000000ff ;
183
184 // height
185 header[ 22 ] = height & 0x000000ff ;
186 header[ 23 ] = (height >> 8 ) & 0x000000ff ;
187 header[ 24 ] = (height >> 16 ) & 0x000000ff ;
188 header[ 25 ] = (height >> 24 ) & 0x000000ff ;
189
190 // bit per pixel
191 header[ 28 ] = bit_per_pixel;
192
193 // write header
194 fwrite(header, sizeof (unsigned char ), rgb_raw_data_offset, fp_t);
195
196 // write image
197 fwrite(image_t, sizeof (unsigned char ), (size_t)( long )width * height * byte_per_pixel, fp_t);
198
199 fclose(fp_s);
200 fclose(fp_t);
201
202 return 0 ;
203 }
204
205 int main() {
206 read_bmp( " lena.bmp " ); // 24 bit gray level image
207 sobel( 90.0 );
208 write_bmp( " lena_sobel.bmp " );
209 }
2 (C) OOMusou 2007 http://oomusou.cnblogs.com
3
4 Filename : sobel_edge.c
5 Compiler : Visual C++ 8.0
6 Description : Demo the how to use sobel detector on gray level image
7 Release : 07/23/2008 1.0
8 */
9 #include < stdio.h >
10 #include < stdlib.h >
11 #include < math.h >
12
13 #define MASK_N 2
14 #define MASK_X 3
15 #define MASK_Y 3
16 #define WHITE 255
17 #define BLACK 0
18
19 unsigned char * image_s = NULL; // source image array
20 unsigned char * image_t = NULL; // target image array
21 FILE * fp_s = NULL; // source file handler
22 FILE * fp_t = NULL; // target file handler
23
24 unsigned int width, height; // image width, image height
25 unsigned int rgb_raw_data_offset; // RGB raw data offset
26 unsigned char bit_per_pixel; // bit per pixel
27 unsigned short byte_per_pixel; // byte per pixel
28
29 // bitmap header
30 unsigned char header[ 54 ] = {
31 0x42 , // identity : B
32 0x4d , // identity : M
33 0 , 0 , 0 , 0 , // file size
34 0 , 0 , // reserved1
35 0 , 0 , // reserved2
36 54 , 0 , 0 , 0 , // RGB data offset
37 40 , 0 , 0 , 0 , // struct BITMAPINFOHEADER size
38 0 , 0 , 0 , 0 , // bmp width
39 0 , 0 , 0 , 0 , // bmp height
40 1 , 0 , // planes
41 24 , 0 , // bit per pixel
42 0 , 0 , 0 , 0 , // compression
43 0 , 0 , 0 , 0 , // data size
44 0 , 0 , 0 , 0 , // h resolution
45 0 , 0 , 0 , 0 , // v resolution
46 0 , 0 , 0 , 0 , // used colors
47 0 , 0 , 0 , 0 // important colors
48 };
49
50
51 // sobel mask
52 int mask[MASK_N][MASK_X][MASK_Y] = {
53 {{ - 1 , - 2 , - 1 },
54 { 0 , 0 , 0 },
55 { 1 , 2 , 1 }},
56
57 {{ - 1 , 0 , 1 },
58 { - 2 , 0 , 2 },
59 { - 1 , 0 , 1 }}
60 };
61
62 int read_bmp( const char * fname_s) {
63 fp_s = fopen(fname_s, " rb " );
64 if (fp_s == NULL) {
65 printf( " fopen fp_s error/n " );
66 return - 1 ;
67 }
68
69 // move offset to 10 to find rgb raw data offset
70 fseek(fp_s, 10 , SEEK_SET);
71 fread( & rgb_raw_data_offset, sizeof (unsigned int ), 1 , fp_s);
72
73 // move offset to 18 to get width & height;
74 fseek(fp_s, 18 , SEEK_SET);
75 fread( & width, sizeof (unsigned int ), 1 , fp_s);
76 fread( & height, sizeof (unsigned int ), 1 , fp_s);
77
78 // get bit per pixel
79 fseek(fp_s, 28 , SEEK_SET);
80 fread( & bit_per_pixel, sizeof (unsigned short ), 1 , fp_s);
81 byte_per_pixel = bit_per_pixel / 8 ;
82
83 // move offset to rgb_raw_data_offset to get RGB raw data
84 fseek(fp_s, rgb_raw_data_offset, SEEK_SET);
85
86 image_s = (unsigned char * )malloc((size_t)width * height * byte_per_pixel);
87 if (image_s == NULL) {
88 printf( " malloc images_s error/n " );
89 return - 1 ;
90 }
91
92 image_t = (unsigned char * )malloc((size_t)width * height * byte_per_pixel);
93 if (image_t == NULL) {
94 printf( " malloc image_t error/n " );
95 return - 1 ;
96 }
97
98 fread(image_s, sizeof (unsigned char ), (size_t)( long )width * height * byte_per_pixel, fp_s);
99
100 return 0 ;
101 }
102
103 // convert RGB to gray level int
104 int color_to_int( int r, int g, int b) {
105 return (r + g + b) / 3 ;
106 }
107
108 int sobel( double threshold) {
109 unsigned int x, y, i, v, u; // for loop counter
110 unsigned char R, G, B; // color of R, G, B
111 double val[MASK_N] = { 0.0 };
112 int adjustX, adjustY, xBound, yBound;
113 double total;
114
115 for (y = 0 ; y != height; ++ y) {
116 for (x = 0 ; x != width; ++ x) {
117 for (i = 0 ; i != MASK_N; ++ i) {
118 adjustX = (MASK_X % 2 ) ? 1 : 0 ;
119 adjustY = (MASK_Y % 2 ) ? 1 : 0 ;
120 xBound = MASK_X / 2 ;
121 yBound = MASK_Y / 2 ;
122
123 val[i] = 0.0 ;
124 for (v = - yBound; v != yBound + adjustY; ++ v) {
125 for (u = - xBound; u != xBound + adjustX; ++ u) {
126 if (x + u >= 0 && x + u < width && y + v >= 0 && y + v < height) {
127 R = * (image_s + byte_per_pixel * (width * (y + v) + (x + u)) + 2 );
128 G = * (image_s + byte_per_pixel * (width * (y + v) + (x + u)) + 1 );
129 B = * (image_s + byte_per_pixel * (width * (y + v) + (x + u)) + 0 );
130
131 val[i] += color_to_int(R, G, B) * mask[i][u + xBound][v + yBound];
132 }
133 }
134 }
135 }
136
137 total = 0.0 ;
138 for (i = 0 ; i != MASK_N; ++ i) {
139 total += val[i] * val[i];
140 }
141
142 total = sqrt(total);
143
144 if (total - threshold >= 0 ) {
145 // black
146 * (image_t + byte_per_pixel * (width * y + x) + 2 ) = BLACK;
147 * (image_t + byte_per_pixel * (width * y + x) + 1 ) = BLACK;
148 * (image_t + byte_per_pixel * (width * y + x) + 0 ) = BLACK;
149 }
150 else {
151 // white
152 * (image_t + byte_per_pixel * (width * y + x) + 2 ) = WHITE;
153 * (image_t + byte_per_pixel * (width * y + x) + 1 ) = WHITE;
154 * (image_t + byte_per_pixel * (width * y + x) + 0 ) = WHITE;
155 }
156 }
157 }
158
159 return 0 ;
160 }
161
162 int write_bmp( const char * fname_t) {
163 unsigned int file_size; // file size
164
165 fp_t = fopen(fname_t, " wb " );
166 if (fp_t == NULL) {
167 printf( " fopen fname_t error/n " );
168 return - 1 ;
169 }
170
171 // file size
172 file_size = width * height * byte_per_pixel + rgb_raw_data_offset;
173 header[ 2 ] = (unsigned char )(file_size & 0x000000ff );
174 header[ 3 ] = (file_size >> 8 ) & 0x000000ff ;
175 header[ 4 ] = (file_size >> 16 ) & 0x000000ff ;
176 header[ 5 ] = (file_size >> 24 ) & 0x000000ff ;
177
178 // width
179 header[ 18 ] = width & 0x000000ff ;
180 header[ 19 ] = (width >> 8 ) & 0x000000ff ;
181 header[ 20 ] = (width >> 16 ) & 0x000000ff ;
182 header[ 21 ] = (width >> 24 ) & 0x000000ff ;
183
184 // height
185 header[ 22 ] = height & 0x000000ff ;
186 header[ 23 ] = (height >> 8 ) & 0x000000ff ;
187 header[ 24 ] = (height >> 16 ) & 0x000000ff ;
188 header[ 25 ] = (height >> 24 ) & 0x000000ff ;
189
190 // bit per pixel
191 header[ 28 ] = bit_per_pixel;
192
193 // write header
194 fwrite(header, sizeof (unsigned char ), rgb_raw_data_offset, fp_t);
195
196 // write image
197 fwrite(image_t, sizeof (unsigned char ), (size_t)( long )width * height * byte_per_pixel, fp_t);
198
199 fclose(fp_s);
200 fclose(fp_t);
201
202 return 0 ;
203 }
204
205 int main() {
206 read_bmp( " lena.bmp " ); // 24 bit gray level image
207 sobel( 90.0 );
208 write_bmp( " lena_sobel.bmp " );
209 }
Method 2
sobel_edge.cpp / C++/CLI
1
/*
2 (C) OOMusou 2007 http://oomusou.cnblogs.com
3
4 Filename : sobel_edge.cpp
5 Compiler : C++/CLI / Visual C++ 8.0
6 Description : Demo the how to use sobel detector on gray level image
7 Release : 07/23/2008 1.0
8 */
9
10 #include " stdafx.h "
11 #include < cmath >
12
13 using namespace System::Drawing;
14 using namespace System::Drawing::Imaging;
15
16 const int MASK_N = 2 ;
17 const int MASK_X = 3 ;
18 const int MASK_Y = 3 ;
19
20 // Convert RGB to gray level int
21 int colorToInt(Color % color) {
22 return (color.R + color.G + color.B) / 3 ;
23 }
24
25 void edgeDetector(Bitmap ^ oriImg, Bitmap ^ resImg, const int mask[MASK_N][MASK_X][MASK_Y], const double & threshold) {
26 double val[MASK_N] = { 0.0 };
27
28 for ( int y = 0 ; y != oriImg -> Height; ++ y) {
29 for ( int x = 0 ; x != oriImg -> Width; ++ x) {
30 for ( int i = 0 ; i != MASK_N; ++ i) {
31 int adjustX = (MASK_X % 2 ) ? 1 : 0 ;
32 int adjustY = (MASK_Y % 2 ) ? 1 : 0 ;
33 int xBound = MASK_X / 2 ;
34 int yBound = MASK_Y / 2 ;
35
36 val[i] = 0.0 ;
37 for ( int v = - yBound; v != yBound + adjustY; ++ v) {
38 for ( int u = - xBound; u != xBound + adjustX; ++ u) {
39 if (x + u >= 0 && x + u < oriImg -> Width && y + v >= 0 && y + v < oriImg -> Height) {
40 val[i] += colorToInt(oriImg -> GetPixel(x + u, y + v)) * mask[i][u + xBound][v + yBound];
41 }
42 }
43 }
44 }
45
46 double total = 0.0 ;
47 for ( int i = 0 ; i != MASK_N; ++ i) {
48 total += val[i] * val[i];
49 }
50
51 total = sqrt(total);
52
53 if (total - threshold >= 0 )
54 resImg -> SetPixel(x , y, Color::Black);
55 else
56 resImg -> SetPixel(x, y, Color::White);
57 }
58 }
59 }
60
61 int main() {
62 const int mask[MASK_N][MASK_X][MASK_Y] = {
63 {{ - 1 , - 2 , - 1 },
64 { 0 , 0 , 0 },
65 { 1 , 2 , 1 }},
66
67 {{ - 1 , 0 , 1 },
68 { - 2 , 0 , 2 },
69 { - 1 , 0 , 1 }}
70 };
71
72 Bitmap ^ oriImg = gcnew Bitmap( " lena.bmp " );
73 Bitmap ^ resImg = gcnew Bitmap(oriImg -> Width, oriImg -> Height);
74
75 const double threshold = 90.0 ;
76 edgeDetector(oriImg, resImg, mask, threshold);
77
78 resImg -> Save( " lena_sobel.bmp " );
79
80 return 0 ;
81 }
2 (C) OOMusou 2007 http://oomusou.cnblogs.com
3
4 Filename : sobel_edge.cpp
5 Compiler : C++/CLI / Visual C++ 8.0
6 Description : Demo the how to use sobel detector on gray level image
7 Release : 07/23/2008 1.0
8 */
9
10 #include " stdafx.h "
11 #include < cmath >
12
13 using namespace System::Drawing;
14 using namespace System::Drawing::Imaging;
15
16 const int MASK_N = 2 ;
17 const int MASK_X = 3 ;
18 const int MASK_Y = 3 ;
19
20 // Convert RGB to gray level int
21 int colorToInt(Color % color) {
22 return (color.R + color.G + color.B) / 3 ;
23 }
24
25 void edgeDetector(Bitmap ^ oriImg, Bitmap ^ resImg, const int mask[MASK_N][MASK_X][MASK_Y], const double & threshold) {
26 double val[MASK_N] = { 0.0 };
27
28 for ( int y = 0 ; y != oriImg -> Height; ++ y) {
29 for ( int x = 0 ; x != oriImg -> Width; ++ x) {
30 for ( int i = 0 ; i != MASK_N; ++ i) {
31 int adjustX = (MASK_X % 2 ) ? 1 : 0 ;
32 int adjustY = (MASK_Y % 2 ) ? 1 : 0 ;
33 int xBound = MASK_X / 2 ;
34 int yBound = MASK_Y / 2 ;
35
36 val[i] = 0.0 ;
37 for ( int v = - yBound; v != yBound + adjustY; ++ v) {
38 for ( int u = - xBound; u != xBound + adjustX; ++ u) {
39 if (x + u >= 0 && x + u < oriImg -> Width && y + v >= 0 && y + v < oriImg -> Height) {
40 val[i] += colorToInt(oriImg -> GetPixel(x + u, y + v)) * mask[i][u + xBound][v + yBound];
41 }
42 }
43 }
44 }
45
46 double total = 0.0 ;
47 for ( int i = 0 ; i != MASK_N; ++ i) {
48 total += val[i] * val[i];
49 }
50
51 total = sqrt(total);
52
53 if (total - threshold >= 0 )
54 resImg -> SetPixel(x , y, Color::Black);
55 else
56 resImg -> SetPixel(x, y, Color::White);
57 }
58 }
59 }
60
61 int main() {
62 const int mask[MASK_N][MASK_X][MASK_Y] = {
63 {{ - 1 , - 2 , - 1 },
64 { 0 , 0 , 0 },
65 { 1 , 2 , 1 }},
66
67 {{ - 1 , 0 , 1 },
68 { - 2 , 0 , 2 },
69 { - 1 , 0 , 1 }}
70 };
71
72 Bitmap ^ oriImg = gcnew Bitmap( " lena.bmp " );
73 Bitmap ^ resImg = gcnew Bitmap(oriImg -> Width, oriImg -> Height);
74
75 const double threshold = 90.0 ;
76 edgeDetector(oriImg, resImg, mask, threshold);
77
78 resImg -> Save( " lena_sobel.bmp " );
79
80 return 0 ;
81 }