📄 imagepr.cpp
字号:
/**************************************************
file name: ImagePr.cpp
Copyright (c) 2001-2004 16-320,TJU
founder: Li Xuewei
date: 3,20,2003
mender: Li Xuewei
date:
description:this implementation file can process the whole skin detection,
facial feature extraction,and face verify.
version:1.0
*/
#include "stdafx.h"
#include "ImageProcess.h"
#include "ImagePr.h"
#include "math.h"
#include "afx.h"
#include <Mmsystem.h>
#define PI 3.1415926
#ifdef _DEBUG //#if defined(_DEBUG)/#endif
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// ImagePr
IMPLEMENT_DYNCREATE(ImagePr, CView)
ImagePr::ImagePr()
{
myHSIArray=NULL;
}
ImagePr::~ImagePr()
{
}
BEGIN_MESSAGE_MAP(ImagePr, CView)
//{{AFX_MSG_MAP(ImagePr)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// ImagePr drawing
void ImagePr::OnDraw(CDC* pDC)
{
CDocument* pDoc = GetDocument();
// TODO: add draw code here
}
/////////////////////////////////////////////////////////////////////////////
// ImagePr diagnostics
#ifdef _DEBUG
void ImagePr::AssertValid() const
{
CView::AssertValid();
}
void ImagePr::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// ImagePr message handlers
void ImagePr::ReadDIB(CString fName)
{
/*
** function name: ReadDIB(CString fName)
** input: file name
** fName--
** output:
** function description: open an image of 24-bmp
** global varible-- myPArray,myPWidth,myPHeight
** call block: none
** founder: Zhang Ge
** date: 2001
** mender: Li Xuewei
** date:
** version: 1.0
*/
//BITMAPFILEHEADER tFileHead;
//BITMAPINFOHEADER tFileInfo;
int RowLength;
int tPWidth;
int tPHeight;
LONG tOffset;
BYTE * tPArray;
BYTE tBlue;
BYTE tGreen;
BYTE tRed;
int i,j;
// CFile f1("text.txt",CFile::modeWrite|CFile::typeBinary);
CFile tPfile(fName,CFile::modeRead);
nHeadRead1=tPfile.Read(&tFileHead,14);
nInfoRead2=tPfile.Read(&tFileInfo,40);
//tFileHead.bfReserved1+tFileHead.bfSize+tFileHead.bfType;
// f1.Write(&tFileHead,sizeof(BITMAPFILEHEADER));
if(tFileInfo.biBitCount!=24)
{
AfxMessageBox("This file isn't a 24 bit BMP");
return;
}
tOffset = tFileHead.bfOffBits-54;
gOffset = tOffset;
tPWidth = tFileInfo.biWidth;
tPHeight = tFileInfo.biHeight;
tPArray= new BYTE[tFileHead.bfSize-54];
myPArray= new COLORREF[tPHeight*tPWidth];
RGBImage= new COLORREF[tPHeight*tPWidth];
// tPArray: File buffer
tPfile.Read(tPArray,(tFileHead.bfSize-54));
RowLength=tPWidth*3/4;
if ((tPWidth*3)!=(RowLength*4))
RowLength+=1;
RowLength*=4;
int tPP;
for (i=tPHeight-1; i>=0; i--)// last row corresponded to 1st row's data
{
tPP=tOffset;
for(j=0; j<tPWidth; j++)
{
tBlue=tPArray[tPP];
tPP++;
tGreen=tPArray[tPP];
tPP++;
tRed=tPArray[tPP];
tPP++;
*(myPArray+i*tPWidth+j)=RGB(tRed,tGreen,tBlue);
*(RGBImage+i*tPWidth+j)=RGB(tRed,tGreen,tBlue);
}
tOffset+=RowLength;
}
delete []tPArray;
myPWidth=tPWidth;
myPHeight=tPHeight;
fileName=fName;
}
void ImagePr::HSItrans(char tp)
{
/*
** input: tp
** tp--varible of char type,it is used to judge whether HSI-RGB.
** output:
** function description: image format transformation from HSI-RGB or RGB-HSI
** global varible-- myHSIArray,myPArray
** call block: none
** founder: Zhang Ge
** date: 2001
** mender: Li Xuewei
** date: 2003
** version: 1.0
*/
if (myHSIArray==NULL) myHSIArray= new sHSI[myPHeight*myPWidth];
double tH,tS,tI,fR,fG,fB;
BYTE R,G,B;
int i,j;
double v;
switch (tp)
{
case 't':
for(i=0; i<(int)myPHeight; i++)
{
for (j=0; j<(int)myPWidth; j++)
{
R=GetRValue(myPArray[i*myPWidth+j]);
G=GetGValue(myPArray[i*myPWidth+j]);
B=GetBValue(myPArray[i*myPWidth+j]);
fR=R;
fG=G;
fB=B;
myHSIArray[i*myPWidth+j].I=(int)(fR+fG+fB)/3; ///*
if(fR+fG+fB==0)//当I=0时,S没有意义,定义为0。
myHSIArray[i*myPWidth+j].S=0;
else
myHSIArray[i*myPWidth+j].S
=float(1-min(min(fR,fG),fB)*3/(fR+fG+fB));
v=atan2(1.73205081*(G-B),(2*R-G-B));//atan2 returns value between -PI to PI;
if(v<0)
v+=2*PI;
myHSIArray[i*myPWidth+j].H=int(v*180/PI);//change arc to angle.
}
}
break;
case 'v': //con't
for(i=0; i<(int)myPHeight; i++)
{
for (j=0; j<(int)myPWidth; j++)
{
tH=PI*(myHSIArray[i*myPWidth+j].H)/180;
tS=myHSIArray[i*myPWidth+j].S;
tI=myHSIArray[i*myPWidth+j].I;
if(tS==0)
{
if(tI==0)
{
fR=fG=fB=0;
}
else
{
fR=fG=fB=tI;
}
}
else
{
}
R=(BYTE)fR;
G=(BYTE)fG;
B=(BYTE)fB;
myPArray[i*myPWidth+j]=RGB(R,G,B);
}
}
break;
}
}
void ImagePr::sobel()
{
/*
** function name: sobel()
** function description: image edge detection
** global varible-- myPArray
** call block: none
** founder: Li Shuda
** date: 2002
** mender: Li Xuewei
** date:
** version: 1.0
*/
int * tPArray; //int
int i,j,v;
double vx,vy;
tPArray= new int[myPHeight*myPWidth]; //
for(i=0; i<myPHeight; i++)
{
for (j=0; j<myPWidth; j++)
{
*(tPArray+i*myPWidth+j)=myHSIArray[i*myPWidth+j].I;//COLORREF myPArray
}
}
for(i=0;i<myPWidth;i++)//置第一行和最后一行像素值为零;可无
{
*(tPArray+i)=0;
*(tPArray+i+(myPHeight-1)*myPWidth)=0;
}
for(j=0;j<myPHeight;j++) //置第一列和最后一列像素值为零;可无
{
*(tPArray+j*myPWidth)=0;
*(tPArray+(j+1)*myPWidth-1)=0;
}
/*for(i=0;i<360;i++)//gradient angle
fany[i]=0;
double tf;*/
//double t1,t2,t3,t4;
//int t;
for(j=1;j<myPHeight-1;j++)
{
for(i=1;i<myPWidth-1;i++)
{
vx=*(tPArray+(i+1)+(j-1)*myPWidth)+2 * *(tPArray+(i+1)+(j)*myPWidth)
+*(tPArray+(i+1)+(j+1)*myPWidth)-
(*(tPArray+(i-1)+(j-1)*myPWidth)+2 * *(tPArray+(i-1)+(j)*myPWidth)
+*(tPArray+(i-1)+(j+1)*myPWidth));
vy=*(tPArray+(i-1)+(j+1)*myPWidth)+2 * *(tPArray+(i)+(j+1)*myPWidth)
+*(tPArray+(i+1)+(j+1)*myPWidth)-
(*(tPArray+(i-1)+(j-1)*myPWidth)+2 * *(tPArray+(i)+(j-1)*myPWidth)
+*(tPArray+(i+1)+(j-1)*myPWidth));/**/
/* weber fechner law
t1=(*(tPArray+(i+1)+(j-1)*myPWidth)-*(tPArray+i+j*myPWidth))/ double(*(tPArray+i+j*myPWidth));
t2=(*(tPArray+(i+1)+(j+1)*myPWidth)-*(tPArray+i+j*myPWidth))/ double(*(tPArray+i+j*myPWidth));
t3=(*(tPArray+(i-1)+(j+1)*myPWidth)-*(tPArray+i+j*myPWidth))/ double(*(tPArray+i+j*myPWidth));
t4=(*(tPArray+(i-1)+(j-1)*myPWidth)-*(tPArray+i+j*myPWidth))/ double(*(tPArray+i+j*myPWidth));
t=*(tPArray+ i +j * myPWidth);
if(abs(t1)>0.02 || abs(t2)>0.02 ||abs(t3)>0.02|| abs(t4)>0.02)
*(myPArray+i+j*myPWidth)=RGB(t,t,t);
else
*(myPArray+i+j*myPWidth)=RGB(255,255,255);*/
/* gradient angle
if(!(vx==0 && vy==0))
{
tf=atan2(vy,vx);
if(tf<0)
tf+=2*PI;//
fany[int(tf*180/PI)]++;
}
//v=int(v/2.55);*/
v=(int)sqrt(vx*vx+vy*vy);//v=abs(vx)+abs(vy);
if(v>255)
v=255;
if(v<0)
v=0;
*(myPArray+i+j*myPWidth)=RGB(v,v,v);
//bilevel display
/*if(v>150) //
*(myPArray+i+j*myPWidth)=RGB(0,0,0);
else
*(myPArray+i+j*myPWidth)=RGB(t,t,t);*/
}
}
delete []tPArray;
}
void ImagePr::visionSobel()
{
/*
** function name: visionSobel()
** function description: image edge detction by using vision intensity
** global varible-- myHSIArray,myPArray
** call block: none
** founder: Li Xuewei
** date: 2003
** mender: Li Xuewei
** date:
** version: 1.0
*/
short * tPArray;//COLORREF
int i,j,v;
double vx,vy;
double t;
tPArray= new short[myPHeight*myPWidth];//COLORREF
gradient=new short[myPHeight*myPWidth];
for(i=0; i<myPHeight; i++)
{
for (j=0; j<myPWidth; j++)
{
t=myHSIArray[i*myPWidth+j].I;//COLORREF myPArray
t=t*100/256;
if(t>=0 &&t <18)
t=7.519+2.098*t;
if(t>=18 && t<=100)
t=-58.936+79.192*log(t)/log(10);/**/
//t=t*255/100;
if(t>255)
t=255;
if(t<0)
t=0;
*(tPArray+i*myPWidth+j)=short(t);
*(gradient+i*myPWidth+j)=0;
}
}
for(i=0;i<myPWidth;i++)//the pixels of the first and last row are be set to zero.
{
*(tPArray+i)=0;
*(tPArray+i+(myPHeight-1)*myPWidth)=0;
}
for(j=0;j<myPHeight;j++) //the pixels of the first and last coloum are be set to zero.
{
*(tPArray+j*myPWidth)=0;
*(tPArray+(j+1)*myPWidth-1)=0;
}
int thresh=binarizeForImage('n');
for(i=0;i<180;i++)//gradient angle
fany[i]=0;
double tf;
int ti;
for(j=1;j<myPHeight-1;j++)
for(i=1;i<myPWidth-1;i++)
{
//vertical edge
vx=*(tPArray+(i+1)+(j-1)*myPWidth)+ 2 * *(tPArray+(i+1)+(j)*myPWidth)
+*(tPArray+(i+1)+(j+1)*myPWidth)-
(*(tPArray+(i-1)+(j-1)*myPWidth)+ 2 * *(tPArray+(i-1)+(j)*myPWidth)
+*(tPArray+(i-1)+(j+1)*myPWidth));
//horizontal edge
vy=*(tPArray+(i-1)+(j+1)*myPWidth)+ 2 * *(tPArray+(i)+(j+1)*myPWidth)
+*(tPArray+(i+1)+(j+1)*myPWidth)-
(*(tPArray+(i-1)+(j-1)*myPWidth)+ 2 * *(tPArray+(i)+(j-1)*myPWidth)
+*(tPArray+(i+1)+(j-1)*myPWidth));
if(!(vx==0 && vy==0))//this point's gradient is not 0
{
tf=atan2(vy,vx);
if(tf<0)
tf+=PI;//
ti=int(tf*180/PI);
if(ti==180)
ti=0;
fany[ti]++;
}/**/
//vx=vx*2.55;
//vy*=2.55;
v=(int)sqrt(vx*vx+vy*vy);
if(v>255)//
v=255;
*(myPArray+i+j*myPWidth)=RGB(v,v,v);
//eye extraction
/*if(v>50&& *(tPArray+j*myPWidth+i)<thresh)
*(myPArray+i+j*myPWidth)=RGB(255,0,255);
else
*(myPArray+i+j*myPWidth)=RGB(255,255,255);//*/
*(gradient+i+j*myPWidth)=v;
}
delete []tPArray;
}
bool ImagePr::IsDebugSkinClassify=false;
void ImagePr::skinclassify()
{
/*
** function name: skinclassify()
** function description: postprocessing after skin pixels classification,
** global varible-- myHSIArray,myPArray,gFlag
** call block: Dilate(),Erosion(),
** founder: Li Xuewei
** date: 2003
** mender: Li Xuewei
** date:
** version: 1.0
*/
int R,G,B;
int j,i;
bool *flag; // record if the pixel is skin pixel.
COLORREF * Temp_myPArray;
Temp_myPArray= new COLORREF[myPHeight*myPWidth];
flag=new bool[myPHeight*myPWidth];
IsDebugSkinClassify=true;
//classify the skin region and non-skin region.
//
//HistEqulization();
FirstClassify();
// TestClassify(); //not good for shadow
for(i=0; i<myPHeight; i++)///*
{
for (j=0; j<myPWidth; j++)
{
*(flag+i*myPWidth+j)=*(gFlag+i*myPWidth+j);
}
}
//*********** remove the single pixel ****************
int R1,G1,B1,R2,G2,B2,R3,G3,B3,R4,G4,B4;
for(i=1; i<myPHeight-1; i++)
{
for (j=1; j<myPWidth-1; j++)
{
R=GetRValue(myPArray[i*myPWidth+j]);
G=GetGValue(myPArray[i*myPWidth+j]);
B=GetBValue(myPArray[i*myPWidth+j]);
R1=GetRValue(myPArray[(i-1)*myPWidth+j]);
G1=GetGValue(myPArray[(i-1)*myPWidth+j]);
B1=GetBValue(myPArray[(i-1)*myPWidth+j]);
R2=GetRValue(myPArray[i*myPWidth+j-1]);
G2=GetGValue(myPArray[i*myPWidth+j-1]);
B2=GetBValue(myPArray[i*myPWidth+j-1]);
R3=GetRValue(myPArray[(i+1)*myPWidth+j]);
G3=GetGValue(myPArray[(i+1)*myPWidth+j]);
B3=GetBValue(myPArray[(i+1)*myPWidth+j]);
R4=GetRValue(myPArray[i*myPWidth+j+1]);
G4=GetGValue(myPArray[i*myPWidth+j+1]);
B4=GetBValue(myPArray[i*myPWidth+j+1]);
if((R+G+B)==765&&((R1+G1+B1)!=765&&(R2+G2+B2)!=765&&(R3+G3+B3)!=765&&(R4+G4+B4)!=765))
{
//*(Temp_myPArray+i*myPWidth+j)=RGB((R1+R2+R3+R4)/4,(G1+G2+G3+G4)/4,(B1+B2+B3+B4)/4);
*(Temp_myPArray+i*myPWidth+j)=RGB(R,G,B);
*(gFlag+i*myPWidth+j)=true;
*(flag+i*myPWidth+j)=true;
}
}
}
//*****************close operation***********************//
//connected the unconnected regions
int size;// 2*size-1 is the structure element's size.
//firstly,remove the pixel if there is less than 12 skin pixels in it's 5*5 adjcent region.
/* int subi,subj;
int count;
size=2;
for(i=size; i<myPHeight-size; i++)//size=2
{
for (j=size; j<myPWidth-size; j++)
{
count=0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -