(原創) 如何實現Face Detection? (C/C++) (C) (Image Processing)

Abstract
本文使用C語言實現face detection。

Introduction
使用環境:Visual Studio 2008 / Visual C++ 9.0

Face Detection的應用相當廣,本文使用人臉偵測與辨識系統[1]這篇論文所提出的演算法加以實現,效果相當不錯。

face_detection.c / C

  1 /* 
  2 (C) OOMusou 2007 http://oomusou.cnblogs.com
  3 
  4 Filename    : face_detection.c
  5 Compiler    : Visual C++ 9.0 / ANSI C
  6 Description : Demo the how to implement face detection by C
  7 Release     : 09/30/2009 1.0
  8 */
  9 #include <stdio.h>
10 #include <stdlib.h>
11 
12 int face_detection(const char *fname_s, const char *fname_t) {
13   FILE          *fp_s = NULL;    // source file handler
14   FILE          *fp_t = NULL;    // target file handler
15   unsigned int  x,y;             // for loop counter
16   unsigned int  width, height;   // image width, image height
17   unsigned char *image_s = NULL; // source image array
18   unsigned char *image_t = NULL; // target image array
19   unsigned char R, G, B;         // color of R, G, B
20  
21   // face detection
22   double r,g;
23   double Gup, Gdown, Wr;
24  
25   unsigned char header[54] = {
26     0x42,        // identity : B
27     0x4d,        // identity : M
28     0, 0, 0, 0// file size
29     0, 0,        // reserved1
30     0, 0,        // reserved2
31     54, 0, 0, 0, // RGB data offset
32     40, 0, 0, 0, // struct BITMAPINFOHEADER size
33     0, 0, 0, 0// bmp width
34     0, 0, 0, 0// bmp height
35     1, 0,        // planes
36     24, 0,       // bit per pixel
37     0, 0, 0, 0// compression
38     0, 0, 0, 0// data size
39     0, 0, 0, 0// h resolution
40     0, 0, 0, 0// v resolution
41     0, 0, 0, 0// used colors
42     0, 0, 0, 0   // important colors
43   };
44  
45   unsigned int file_size;           // file size
46   unsigned int rgb_raw_data_offset; // RGB raw data offset
47  
48   fp_s = fopen(fname_s, "rb");
49   if (fp_s == NULL) {
50     printf("fopen fp_s error\n");
51     return -1;
52   }
53 
54   // move offset to 10 to find rgb raw data offset
55   fseek(fp_s, 10, SEEK_SET);
56   fread(&rgb_raw_data_offset, sizeof(unsigned int), 1, fp_s);
57   // move offset to 18    to get width & height;
58   fseek(fp_s, 18, SEEK_SET);
59   fread(&width,  sizeof(unsigned int), 1, fp_s);
60   fread(&height, sizeof(unsigned int), 1, fp_s);
61   // move offset to rgb_raw_data_offset to get RGB raw data
62   fseek(fp_s, rgb_raw_data_offset, SEEK_SET);
63 
64   image_s = (unsigned char *)malloc((size_t)width * height * 3);
65   if (image_s == NULL) {
66     printf("malloc images_s error\n");
67     return -1;
68   }
69  
70   image_t = (unsigned char *)malloc((size_t)width * height * 3);
71   if (image_t == NULL) {
72     printf("malloc image_t error\n");
73     return -1;
74   }
75  
76   fread(image_s, sizeof(unsigned char), (size_t)(long)width * height * 3, fp_s);
77  
78   for(y = 0; y != height; ++y) {
79     for(x = 0; x != width; ++x) {
80       R = *(image_s + 3 * (width * y + x) + 2);
81       G = *(image_s + 3 * (width * y + x) + 1);
82       B = *(image_s + 3 * (width * y + x) + 0);
83      
84       r = (double)R / (R + G + B);
85       g = (double)G / (R + G + B);
86      
87       Wr = (r-0.33) * (r-0.33) + (g-0.33) * (g-0.33);
88      
89       Gup = -1.3767 * r * r + 1.0743 * r + 0.25;
90       Gdown = -0.776 * r * r + 0.5601 * r + 0.18;
91      
92       if ((g < Gup) && (g > Gdown) && (Wr > 0.001) && ((R-G)>=15)) {
93         *(image_t + 3 * (width * y + x) + 2) = 255;
94         *(image_t + 3 * (width * y + x) + 1) = 255;
95         *(image_t + 3 * (width * y + x) + 0) = 255;
96       }
97       else {
98         *(image_t + 3 * (width * y + x) + 2) = 0;
99         *(image_t + 3 * (width * y + x) + 1) = 0;
100         *(image_t + 3 * (width * y + x) + 0) = 0;
101       }
102     }
103   }
104  
105   // write to new bmp
106   fp_t = fopen(fname_t, "wb");
107   if (fp_t == NULL) {
108     printf("fopen fname_t error\n");
109     return -1;
110   }
111 
112   // file size 
113   file_size = width * height * 3 + rgb_raw_data_offset;
114   header[2] = (unsigned char)(file_size & 0x000000ff);
115   header[3] = (file_size >> 8& 0x000000ff;
116   header[4] = (file_size >> 16) & 0x000000ff;
117   header[5] = (file_size >> 24) & 0x000000ff;
118  
119   // width
120   header[18] = width & 0x000000ff;
121   header[19] = (width >> 8& 0x000000ff;
122   header[20] = (width >> 16) & 0x000000ff;
123   header[21] = (width >> 24) & 0x000000ff;
124  
125   // height
126   header[22] = height &0x000000ff;
127   header[23] = (height >> 8& 0x000000ff;
128   header[24] = (height >> 16) & 0x000000ff;
129   header[25] = (height >> 24) & 0x000000ff;
130  
131   // write header
132   fwrite(header, sizeof(unsigned char), rgb_raw_data_offset, fp_t);
133   // write image
134   fwrite(image_t, sizeof(unsigned char), (size_t)(long)width * height * 3, fp_t);
135  
136   fclose(fp_s);
137   fclose(fp_t);
138  
139   return 0;
140 }
141 
142 int main() {
143   face_detection("cmaria.bmp", "cmaria_skin.bmp");
144 }


原圖 (高樹マリア)

cmaria 

執行結果

cmaria_skin

完整程式碼下載
Face_Detection.7z

Reference
[1] 李棟良、人臉偵測與辨識系統、銘傳大學電腦與通訊工程學系

See Also
(原創) 如何使用ANSI C讀寫24位元的BMP圖檔? (C/C++) (C) (Image Processing)

posted on 2008-09-30 21:22  真 OO无双  阅读(10833)  评论(49编辑  收藏  举报

导航