(原創) 如何實現Sobel Edge Detector? (Image Processing) (C/C++) (C++/CLI) (C)

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 }

 

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 }


原圖
lena

執行結果
lena_sobel

See Also
(原創) 如何實現Real Time的Sobel Edge Detector? (SOC) (Verilog) (Image Processing) (DE2-70) (TRDB-D5M)
(原創) 如何實現Real Time的Sobel Edge Detector? (SOC) (Verilog) (Image Processing) (DE2) (TRDB-DC2) 

posted on 2008-07-23 12:41  真 OO无双  阅读(21956)  评论(6编辑  收藏  举报

导航