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

转地址: 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  }

 

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  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值