使用C與C++/CLI實現Sobel Edge Detector。
http://www.cnblogs.com/oomusou/archive/2008/07/23/sobel_edge_detector.html
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 "); 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 "); 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 "); 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 "); 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 }
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 }