今天是地球日,就選了張相關主題的圖像做測試
第一種:rgb color space
第二種:rg color space
第三種:ycrcb之cr分量+otsu門檻值化
還有别的一些模型,效果不太好就不貼了
1.rgb model
[cpp] view
plaincopy
// skin region location using rgb limitation
void skinrgb(iplimage* rgb,iplimage* _dst)
{
assert(rgb->nchannels==3&& _dst->nchannels==3);
static const int r=2;
static const int g=1;
static const int b=0;
iplimage* dst=cvcreateimage(cvgetsize(_dst),8,3);
cvzero(dst);
for (int h=0;h<rgb->height;h++) {
unsigned char* prgb=(unsigned char*)rgb->imagedata+h*rgb->widthstep;
unsigned char* pdst=(unsigned char*)dst->imagedata+h*dst->widthstep;
for (int w=0;w<rgb->width;w++) {
if ((prgb[r]>95 && prgb[g]>40 && prgb[b]>20 &&
prgb[r]-prgb[b]>15 && prgb[r]-prgb[g]>15/*&&
!(prgb[r]>170&&prgb[g]>170&&prgb[b]>170)*/)||//uniform illumination
(prgb[r]>200 && prgb[g]>210 && prgb[b]>170 &&
abs(prgb[r]-prgb[b])<=15 && prgb[r]>prgb[b]&& prgb[g]>prgb[b])//lateral illumination
) {
memcpy(pdst,prgb,3);
}
prgb+=3;
pdst+=3;
}
}
cvcopyimage(dst,_dst);
cvreleaseimage(&dst);
}
2.rg model
// skin detection in rg space
void cvskinrg(iplimage* rgb,iplimage* gray)
assert(rgb->nchannels==3&&gray->nchannels==1);
const int r=2;
const int g=1;
const int b=0;
double aup=-1.8423;
double bup=1.5294;
double cup=0.0422;
double adown=-0.7279;
double bdown=0.6066;
double cdown=0.1766;
unsigned char* pgray=(unsigned char*)gray->imagedata+h*gray->widthstep;
unsigned char* prgb=(unsigned char* )rgb->imagedata+h*rgb->widthstep;
int s=prgb[r]+prgb[g]+prgb[b];
double r=(double)prgb[r]/s;
double g=(double)prgb[g]/s;
double gup=aup*r*r+bup*r+cup;
double gdown=adown*r*r+bdown*r+cdown;
double wr=(r-0.33)*(r-0.33)+(g-0.33)*(g-0.33);
if (g<gup && g>gdown && wr>0.004){
*pgray=255;
}else{
*pgray=0;
}
pgray++;
3.cr+otsu
[c-sharp] view
// implementation of otsu algorithm
// author: onezeros#yahoo.cn
// reference: rafael c. gonzalez. digital image processing using matlab
void cvthresholdotsu(iplimage* src, iplimage* dst)
int height=src->height;
int width=src->width;
//histogram
float histogram[256]={0};
for(int i=0;i<height;i++) {
unsigned char* p=(unsigned char*)src->imagedata+src->widthstep*i;
for(int j=0;j<width;j++) {
histogram[*p++]++;
//normalize histogram
int size=height*width;
for(int i=0;i<256;i++) {
histogram[i]=histogram[i]/size;
//average pixel value
float avgvalue=0;
avgvalue+=i*histogram[i];
int threshold;
float maxvariance=0;
float w=0,u=0;
w+=histogram[i];
u+=i*histogram[i];
float t=avgvalue*w-u;
float variance=t*t/(w*(1-w));
if(variance>maxvariance) {
maxvariance=variance;
threshold=i;
cvthreshold(src,dst,threshold,255,cv_thresh_binary);
void cvskinotsu(iplimage* src, iplimage* dst)
assert(dst->nchannels==1&& src->nchannels==3);
iplimage* ycrcb=cvcreateimage(cvgetsize(src),8,3);
iplimage* cr=cvcreateimage(cvgetsize(src),8,1);
cvcvtcolor(src,ycrcb,cv_bgr2ycrcb);
cvsplit(ycrcb,0,cr,0,0);
cvthresholdotsu(cr,cr);
cvcopyimage(cr,dst);
cvreleaseimage(&cr);
cvreleaseimage(&ycrcb);
原圖像
rgb model
rg model
otsu+cr
皮膚檢測算法三種,示例與代碼