?? dib.cpp
字號:
}
GlobalUnlock(hDIB);
return true;
}
else AfxMessageBox("Can't find the corresponding point!");
GlobalUnlock(hDIB);
return false;
}
//比較兩張圖片的相似度
BOOL DIB::IsScaterPoint(int x, int y, int width, int height, LPBYTE lpData,WORD wBytesPerLine, int threshold,bool lab[m_HEIGHT][m_WIDTH])
{
long lOffset;
//得到數(shù)據(jù)的偏移
lOffset = this->PixelOffset(y,x,wBytesPerLine);
//判斷該點是否為白色以及是否計算過了
if(*(lpData+lOffset) == 255 && lab[y][x] == false)
{
//鏈長度加一
this->lenth++;
//更改標志位
lab[y][x] = true;
//如果鏈長度達到臨界值則返回真
if(this->lenth >= threshold)
return true;
//對右邊點的邊界判斷以及標志位判斷
if(x+1<width && lab[y][x+1] == false)
{
//遞歸調(diào)用本函數(shù),對右邊的點進行判斷
IsScaterPoint(x+1,y,width,height,lpData,wBytesPerLine,threshold,lab);
if(this->lenth>=threshold)
return true;
}
//處理左邊的點
if(x-1>=0 && lab[y][x-1] == false)
{
(IsScaterPoint(x-1,y,width,height,lpData,wBytesPerLine,threshold,lab));
if(this->lenth>=threshold)
return true;
}
//處理上面的點
if(y-1>=0 && lab[y-1][x]==false)
{
(IsScaterPoint(x,y-1,width,height,lpData,wBytesPerLine,threshold,lab));
if(this->lenth>=threshold)
return true;
}
//處理下面的點
if(y+1<height && lab[y+1][x]==false)
{ (IsScaterPoint(x,y+1,width,height,lpData,wBytesPerLine,threshold,lab));
if(this->lenth>=threshold)
return true;
}
//處理右下的點
if(y+1<height && x+1 <width && lab[y+1][x+1]==false)
{ (IsScaterPoint(x+1,y+1,width,height,lpData,wBytesPerLine,threshold,lab));
if(this->lenth>=threshold)
return true;
}
//處理左下的點
if(y+1<height && x-1 >=0 && lab[y+1][x-1]==false)
{ (IsScaterPoint(x-1,y+1,width,height,lpData,wBytesPerLine,threshold,lab));
if(this->lenth>=threshold)
return true;
}
//處理左上的點
if(y-1>=0 && x-1 >=0 &&lab[y-1][x-1]==false)
{ (IsScaterPoint(x-1,y-1,width,height,lpData,wBytesPerLine,threshold,lab));
if(this->lenth>=threshold)
return true;
}
//處理右上的點
if(y-1<height && x+1<width && lab[y+1][x]==false)
{ (IsScaterPoint(x+1,y-1,width,height,lpData,wBytesPerLine,threshold,lab));
if(this->lenth>=threshold)
return true;
}
}
//如果遞歸結(jié)束,長度達不到臨界值,返回假
return false;
}
BOOL DIB::LightingCompensate(HANDLE hDIB)
{
if(!hDIB)
return FALSE;
LPBITMAPINFOHEADER lpbi;
int width,height;
LPBYTE lpData;
WORD wBytesPerLine;
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
//得到圖片寬和高
width = lpbi->biWidth;
height = lpbi->biHeight;
//得到圖片數(shù)據(jù)區(qū)
lpData = this->FindDIBBits(hDIB);
//得到圖片每行的象素所占字節(jié)個數(shù)
wBytesPerLine = this->BytePerLine(hDIB);
//比例系數(shù)
const float thresholdco = 0.05;
//象素個數(shù)的臨界常數(shù)
const int thresholdnum = 100;
//灰度級數(shù)組
int histogram[256];
for(int i =0;i<256;i++)
histogram[i] = 0;
//對于過于小的圖片的判斷
if(width*height*thresholdco < thresholdnum)
return false;
int colorr,colorg,colorb;
long lOffset;
//考察整個圖片
for( i=0;i<height;i++)
for(int j=0;j<width;j++)
{
//得到象素數(shù)據(jù)的偏移
lOffset = this->PixelOffset(i,j,wBytesPerLine);
//得到rgb值
colorb = *(lpData+lOffset++);
colorg = *(lpData+lOffset++);
colorr = *(lpData+lOffset++);
//計算灰度值
int gray = (colorr * 299 + colorg * 587 + colorb * 114)/1000;
histogram[gray]++;
}
int calnum =0;
int total = width*height;
int num;
//下面的循環(huán)得到滿足系數(shù)thresholdco的臨界灰度級
for(i =0;i<256;i++)
{
if((float)calnum/total < thresholdco)
{
calnum+= histogram[255-i];
num = i;
}
else
break;
}
int averagegray = 0;
calnum =0;
//得到滿足條件的象素總的灰度值
for(i = 255;i>=255-num;i--)
{
averagegray += histogram[i]*i;
calnum += histogram[i];
}
averagegray /=calnum;
//得到光線補償?shù)南禂?shù)
float co = 255.0/(float)averagegray;
//下面的循環(huán)對圖象進行光線補償
for(i =0;i<height;i++)
for(int j=0;j<width;j++)
{
//得到數(shù)據(jù)便宜
lOffset = this->PixelOffset(i,j,wBytesPerLine);
//得到藍色分量
colorb = *(lpData+lOffset);
//調(diào)整
colorb *=co;
//臨界判斷
if(colorb >255)
colorb = 255;
//保存
*(lpData+lOffset) = colorb;
//綠色分量
colorb = *(lpData+lOffset+1);
colorb *=co;
if(colorb >255)
colorb = 255;
*(lpData+lOffset+1) = colorb;
//紅色分量
colorb = *(lpData+lOffset+2);
colorb *=co;
if(colorb >255)
colorb = 255;
*(lpData+lOffset+2) = colorb;
}
return TRUE;
}
BOOL DIB::FaceModeling(int Cr,int Cb)
{
//Cb的系數(shù)常量
const float cx = 114.38;
//cr的系數(shù)常量
const float cy = 160.02;
//角度常量
const float theta = 2.53;
//x軸線和y軸線的兩個常量
const float ecx = 1.60;
const float ecy = 2.41;
//長軸
const float a = 25.39;
//短軸
const float b = 14.03;
//相似度常量
const float judge = 0.5;
//計算得到x軸數(shù)值
float x = cos(theta)*(Cb-cx)+sin(theta)*(Cr-cy);
//y軸數(shù)值
float y = -sin(theta)*(Cb -cx)+cos(theta)*(Cr-cy);
//計算離心率
float temp = pow(x-ecx,2)/pow(a,2)+pow(y-ecy,2)/pow(b,2);
//如果滿足要求返回真,否則假
if(fabs(temp-1.0)<judge)
return TRUE;
else
return FALSE;
}
LPBYTE DIB::YcctoRgb(LPBYTE lpYcc,WORD wBytesPerLine,int height,int width)
{
LPBYTE lpRGB;
//申請內(nèi)存
lpRGB = new BYTE[wBytesPerLine*height];
//檢查內(nèi)容分配
if(lpRGB == NULL)
{
AfxMessageBox("not enought memory");
return NULL;
}
long lOffset;
//下面的循環(huán)實現(xiàn)從ycc到rgb的轉(zhuǎn)換
for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
{
//得到數(shù)據(jù)便宜
lOffset = PixelOffset(i,j,wBytesPerLine);
//得到y(tǒng),Cr,Cb的數(shù)值
int Y = *(lpYcc+lOffset);
int Cr = *(lpYcc+lOffset+1);
int Cb = *(lpYcc+lOffset+2);
//利用公式進行計算,并把結(jié)果保存到動態(tài)數(shù)組里面
*(lpRGB+lOffset+2) = (1164*(Y-16)+1596*(Cr-128))/1000;
*(lpRGB+lOffset+1) = (1164*(Y-16) - 813*(Cr-128) - 392*(Cb-128))/1000;
*(lpRGB+lOffset) = (1164*(Y-16) +2017*(Cb-128))/1000;
}
return lpRGB;
}
int DIB::_Cb(int Y)
{
int Cb;
//如果亮度很小的情況
if(Y<Kl)
Cb = 108 + ((Kl-Y)*10)/(Kl-Ymin);
//亮度很大的情況
else if(Y>Kh)
Cb = 108 + ((Y-Kh)*10)/(Ymax - Kh);
else
Cb = -1;
return Cb;
}
int DIB::_Cr(int Y)
{
int Cr;
//亮度很小的情況
if(Y<Kl)
Cr = 154 - ((Kl-Y)*10)/(Kl-Ymin);
//亮度很大的情況
else if(Y>Kh)
Cr = 154 - ((Y-Kh)*22)/(Ymax - Kh);
else
Cr = -1;
return Cr;
}
int DIB::_WCr(int Y)
{
int WCr;
if(Y<Kl)
//亮度很小的情況
WCr = WLcr + ((Y-Ymin)*(Wcr-WLcr))/(Kl-Ymin);
else if(Y>Kh)
//亮度很大的情況
WCr = WHcr + ((Ymax-Y)*(Wcr-WHcr))/(Ymax-Kh);
else WCr = -1;
return WCr;
}
int DIB:: _WCb(int Y)
{
int WCb;
if(Y<Kl)
//亮度很小的情況
WCb = WLcb + ((Y-Ymin)*(Wcb-WLcb))/(Kl-Ymin);
else if(Y>Kh)
//亮度很大的情況
WCb = WHcb + ((Ymax-Y)*(Wcb-WHcb))/(Ymax-Kh);
else WCb = -1;
return WCb;
}
void DIB::YccTransform(LPBYTE lpYcc,WORD wBytesPerLine,int height,int width)
{
int Y,Cr,Cb;
long lOffset;
//下面的循環(huán)實現(xiàn)ycc色彩空間的非線性轉(zhuǎn)換
for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
{
//得到數(shù)據(jù)偏移
lOffset = PixelOffset(i,j,wBytesPerLine);
//得到y(tǒng),Cr,Cb數(shù)值
Y = *(lpYcc+lOffset);
Cr = *(lpYcc+lOffset+1);
Cb = *(lpYcc+lOffset+2);
//如果y數(shù)值在兩個臨界值之間,保持不變
if(Y>=Kl && Y<=Kh)
continue;
//調(diào)用非線性轉(zhuǎn)換函數(shù)調(diào)整Cr,Cb的數(shù)值
Cr = (Cr-_Cr(Y))*(Wcr/_WCr(Y))+_Cr(Kh);
Cb = (Cb-_Cb(Y))*(Wcb/_WCb(Y))+_Cb(Kh);
*(lpYcc+lOffset+1) = Cr;
*(lpYcc+lOffset+2) = Cb;
}
}
void DIB::faceear(LPBYTE lpYcc, WORD wBytesPerLine, int height,int width, bool flag[ImgRange][ImgRange])
{
//初始化標志位
for (int i=0; i<ImgRange; i++)
for (int j=0; j<ImgRange; j++)
{
flag[i][j] = false;
}
long lOffset;
int Cr;
int Cb;
for (i=0; i<height; i++)
for (int j=0; j<width; j++)
{
//得到偏移
lOffset = PixelOffset(i,j,wBytesPerLine);
//得到Cr,Cb數(shù)值
Cr = *(lpYcc+lOffset+1);
Cb = *(lpYcc+lOffset+2);
//人臉顏色建模
if(FaceModeling(Cr,Cb))
{
//修改標志位
flag[i][j] = true;
}
}
}
void DIB::FaceLocate(HANDLE hDIB, CRect faceLocation[10], int &faceNum)
{
HANDLE hDIBTemp;
//保存當前數(shù)據(jù)
hDIBTemp = this->CopyHandle(hDIB);
LPBITMAPINFOHEADER lpbi;
LPBYTE lpData;
WORD wBytesPerLine;
int height;
int width;
long lOffset;
//得到圖象的基本信息
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
height = lpbi->biHeight;
width = lpbi->biWidth;
lpData = FindDIBBits(hDIB);
wBytesPerLine = BytePerLine(hDIB);
//人臉數(shù)目初始化為0
faceNum =0;
for(int k=0; k<10; k++)
{
//初始化區(qū)域
faceLocation[k].bottom = -1;
faceLocation[k].top = height;
faceLocation[k].right = -1;
faceLocation[k].left = width;
}
for(int i=0; i<height; i++)
for (int j=0; j<width; j++)
{
//偏移
lOffset = PixelOffset(i,j,wBytesPerLine);
int num;
//當前點的數(shù)值
num = *(lpData + lOffset);
if (num !=0)//不是黑色
{
//遞歸計算
RecursiveLocateRect(lpData, wBytesPerLine, i, j, num, faceLocation[faceNum]);
faceNum++;
}
}
GlobalUnlock(hDIB);
GlobalFree(hDIB);
//數(shù)值還原
hDIB = this->CopyHandle(hDIBTemp);
lpData = FindDIBBits(hDIB);
wBytesPerLine = BytePerLine(hDIB);
for (i=0; i<faceNum; i++)
for (int j=faceLocation[i].top; j<faceLocation[i].bottom; j++)
{
//把得到的人臉區(qū)域用綠色矩形標注,處理豎直的兩條邊
lOffset = this->PixelOffset(j, faceLocation[i].left, wBytesPerLine);
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 0;
lOffset = this->PixelOffset(j, faceLocation[i].right, wBytesPerLine);
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 0;
}
for (i=0; i<faceNum; i++)
for (int j=faceLocation[i].left; j<faceLocation[i].right; j++)
{
//處理水平的兩天矩形邊
lOffset = this->PixelOffset(faceLocation[i].top, j, wBytesPerLine);
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 0;
lOffset = this->PixelOffset(faceLocation[i].bottom, j, wBytesPerLine);
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 0;
}
GlobalFree(hDIBTemp);
GlobalUnlock(hDIB);
}
void DIB::RecursiveLocateRect(LPBYTE lpData,WORD wBytesPerLine, int y, int x, int num, CRect &faceRect)
{
long lOffset;
//得到偏移
lOffset = PixelOffset(y,x,wBytesPerLine);
//數(shù)值判斷
if(*(lpData + lOffset) == num)
{
//更改顏色為黑色
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 0;
//修改矩形的上下左右四個點位置
if(faceRect.bottom < y)
{
faceRect.bottom = y;
}
if(faceRect.top > y)
{
faceRect.top = y;
}
if(faceRect.right < x)
{
faceRect.right = x;
}
if(faceRect.left > x)
{
faceRect.left = x;
}
//上下左右調(diào)用本函數(shù)進行區(qū)域判定
RecursiveLocateRect(lpData, wBytesPerLine, y-1, x, num,faceRect);
RecursiveLocateRect(lpData, wBytesPerLine, y+1, x, num, faceRect);
RecursiveLocateRect(lpData, wBytesPerLine, y, x-1, num, faceRect);
RecursiveLocateRect(lpData, wBytesPerLine, y, x+1, num, faceRect);
}
}
void DIB::EyeMapC(LPBYTE lpRgb, const LPBYTE lpYcc, WORD wBytesPerLine, CRect faceLocation)
{
long lOffset;
int cr;
int cb;
//根據(jù)傳進來的矩形區(qū)域進行眼睛的色度匹配
for(int i=faceLocation.top; i<=faceLocation.bottom; i++)
for (int j=faceLocation.left; j<=faceLocation.right; j++)
{
//得到Cr,Cb數(shù)值
lOffset = PixelOffset(i, j, wBytesPerLine);
cr = *(lpYcc + lOffset +1);
cb = *(lpYcc + lOffset +2);
//標志
bool lab;
//判斷Cb分量的數(shù)值,并修改標志
int cmap = cb -116 ;
if(cmap >-1 && cmap <4)
lab = true;
else
lab = false;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -