Skin color recognition is an important issue of digital image, there are many ways to solve this problem, there are many good methods, but almost all have their own shortcomings, it is difficult to achieve the perfect, after all, whether the recognition of success, recognition is accurate depends on many factors.
I do is based on the YUV space and yqi space adaptive illumination of the skin color recognition, the principle is very simple, can refer to the following information:
Http://wenku.baidu.com/link?url=m01RY0xYaraGnOmWVSSthhuGZq-yuC_JuvCq9JknxLRaTpLWV9X_ Khrf2f4xmnkhhgy8hb0ady-ykfcoijbxj3kywu-9ynjqcylecyojdlc
There is a problem with this document, however, when calculating the phase angle of the UV, it is defined as:
Angle=arctan (| v|/| u|)
This may not seem right, but I have looked up all kinds of information on the Internet, there is no result, but according to my own reasoning, the calculation method should be as follows:
1.v>0 && u>0//First Quadrant
Angle=arctan (v/u) *180/pi;
2.v>0 && u<0//Second quadrant
Angle=180-arctan (| v|/| u|) *180/PI;
3.v<0 && u<0//Third Quadrant
Angle=180+arctan (| v|/| u|) *180/PI;
4.v<0 && u>0//Fourth Quadrant
Angle=360-arctan (| v|/| u|) *180/PI;
According to my mathematics knowledge should be like this is not wrong, but this is only my personal reasoning, if there are errors please point out!
Another problem is his limited scope, he believes that the angle value should be in the [105,150],i value should be in [20,80], but the result is not how ideal, there are a lot of false negative and wrong, although it is inevitable! But it can be improved, here my solution is to use OPENCV face recognition, identify the face and then zoom in a specific area (under the eyes and the upper part of the mouth), in the calculation of this part of the angle value and I worth the average, and then in the dynamic amplification
, so the recognition effect will be much better!
Here is the core part of the algorithm
SkinIdentify.h
typedef unsigned char Byte;class skinidentify{public:skinidentify (void), virtual ~skinidentify (void), void Run (BYTE * Psrcr,byte *psrcg,byte *psrcb,int height,int width,byte *pdstrgbdata,byte *pdstrgbdata1,byte *pDstRGBData2,int Anglemin,int anglemax,int imin,int imax,float *pfangle,float *pfi); void runagain (int height,int Width,byte *pDstRGBData , byte *pdstrgbdata1,byte *pdstrgbdata2,int anglemin,int anglemax,int imin,int imax,float *pfAngle,float *pfI); void Calavgai (byte *psrcr,byte *psrcg,byte *psrcb,int height,int width,float &avga,float &AvgI);p rivate:void Gammaadjust (Byte *pgray,float * pgamma,int height,int Width);};
SkinIdentify.cpp
#include "StdAfx.h" #include "SkinIdentify.h" #include <cmath> #define Pi 3.1416skinidentify::skinidentify (void) {}skinidentify::~skinidentify (void) {}void skinidentify::run (byte *psrcr,byte *psrcg,byte *psrcb,int Height,int Width , byte *pdstrgbdata,byte *pdstrgbdata1,byte *pdstrgbdata2,int anglemin,int anglemax,int IMin,int IMax,float *pfAngle, Float *PFI) {//gamma correction float *pgammar=new float[height*width];float *pgammag=new float[height*width];float *pGammaB= New Float[height*width]; Gammaadjust (Psrcr,pgammar,height,width); Gammaadjust (Psrcg,pgammag,height,width); Gammaadjust (psrcb,pgammab,height,width);//yuv and Yqi space combined judgment float u,v,angle,i;float *pr=pgammar,*pg=pgammag,*pb= Pgammab;float imin=imin*1.0,imax=imax*1.0;float amin=anglemin*1.0,amax=anglemax*1.0;for (int i=0;i<Height;i++) { for (int j=0;j<width;j++) {u= ( -0.147) *pgammar[j]-0.289*pgammag[j]+0.436*pgammab[j]; v=0.615*pgammar[j]-0.515*pgammag[j]-0.100*pgammab[j];//Calculate the phase angle if (u==0) Angle=0;else Angle=atan (ABS (V/U)); if (V>0 &&u<0) ANgle=180-angle*180/pi;else if (v<0&&u<0) Angle=180+angle*180/pi;else if (V<0&&U>0) Angle =360-angle*180/pi;//calculates the I value i=0.596*pgammar[j]-0.274*pgammag[j]-0.322*pgammab[j];p fangle[j]=angle;//saves the Angle value, The Runagain function pfi[j]=i is called directly when the parameter is changed conveniently. The effect of the same//YUV space if (angle>=amin && Angle <=amax) {pdstrgbdata[j]=1;} else{pdstrgbdata[j]=0;} Yqi the effect of the space if (I>=imin&&i<=imax) {pdstrgbdata1[j]=1;} else{pdstrgbdata1[j]=0;} Combined effects if (angle>=amin && Angle <=amax &&i>=imin&&i<=imax) {pdstrgbdata2[j]=1;} else{pdstrgbdata2[j]=0;}} Psrcr+=width;psrcg+=width;psrcb+=width;pgammar+=width;pgammag+=width;pgammab+=width;pfangle+=width;pfi+=width; Pdstrgbdata+=width;pdstrgbdata1+=width;pdstrgbdata2+=width;} Delete[] pr;//pgammar=null;delete[] pg;//pgammag=null;delete [] pb;//pgammab=null;} void Skinidentify::gammaadjust (Byte *pgray,float * pgamma,int height,int Width) {float a=0.5;float x0=80.0,x1=175.0,x,y , cosx,gammax;for (int i=0;i
And the realization of the visual interface using MFC and OPENCV implementation of the face recognition Part I will not be attached to, interested in contact with me!
Here is the recognition effect
Original
YUV Space Effect
The effect of Yqi space
Combined effect
In fact, this picture effect is not good, but also can see YUV and Yqi's respective defects, YUV can not identify brown black, YQI can not recognize the color of the red, and comprehensive or good!
Adaptive skin Recognition