📄 dib.cpp
字号:
GlobalFree(hTempDIB);
}
void DIB::Dilation(HANDLE hDIB)
{
LPBITMAPINFOHEADER lpbi;
int height;
int width;
WORD wBytesPerLine;
LPBYTE lpData;
LPBYTE lpTemp;
long lOffset;
//得到图象的基本信息
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
height = lpbi->biHeight;
width = lpbi->biWidth;
wBytesPerLine = this->BytePerLine(hDIB);
lpData = this->FindDIBBits(hDIB);
//申请一块和数据区大小相同的内存
lpTemp = (LPBYTE) new BYTE[wBytesPerLine * height];
long lOffsetJudge;
for (int i=1; i<height-1; i++)
for (int j=1; j<width-1; j++)
{
lOffset = this->PixelOffset(i, j, wBytesPerLine);
//如果当前点为白色,接着循环
if(*(lpData + lOffset) == 255)
{
*(lpTemp + lOffset++) = 255;
*(lpTemp + lOffset++) = 255;
*(lpTemp + lOffset++) = 255;
continue;
}
//否则考察上下左右四个点
else
{
lOffsetJudge = this->PixelOffset(i-1, j, wBytesPerLine);
//如果上面的点为白色
if(*(lpData + lOffsetJudge) == 255)
{ //设置为白色,并继续循环
*(lpTemp + lOffset++) = 255;
*(lpTemp + lOffset++) = 255;
*(lpTemp + lOffset++) = 255;
continue;
}
//考察下面的点
lOffsetJudge = this->PixelOffset(i+1,j, wBytesPerLine);
if(*(lpData + lOffsetJudge) == 255)
{
*(lpTemp + lOffset++) = 255;
*(lpTemp + lOffset++) = 255;
*(lpTemp + lOffset++) = 255;
continue;
}
//考察左边的点
lOffsetJudge = this->PixelOffset(i,j-1, wBytesPerLine);
if(*(lpData + lOffsetJudge) == 255)
{
*(lpTemp + lOffset++) = 255;
*(lpTemp + lOffset++) = 255;
*(lpTemp + lOffset++) = 255;
continue;
}
//考察右边的点
lOffsetJudge = this->PixelOffset(i,j+1, wBytesPerLine);
if(*(lpData + lOffsetJudge) == 255)
{
*(lpTemp + lOffset++) = 255;
*(lpTemp + lOffset++) = 255;
*(lpTemp + lOffset++) = 255;
continue;
}
//如果上下左右都是黑色点,则把暂时区域的点设置为黑色
lOffset = this->PixelOffset(i,j,wBytesPerLine);
*(lpTemp + lOffset++) = 0;
*(lpTemp + lOffset++) = 0;
*(lpTemp + lOffset++) = 0;
}
}
//处理图象四周的点,设置为黑色
for(i=0; i<height; i++)
{
lOffset = this->PixelOffset(i, 0, wBytesPerLine);
{
*(lpTemp + lOffset++) = 0;
*(lpTemp + lOffset++) = 0;
*(lpTemp + lOffset++) = 0;
}
}
for(i=0; i<height; i++)
{
lOffset = this->PixelOffset(i, width-1, wBytesPerLine);
{
*(lpTemp + lOffset++) = 0;
*(lpTemp + lOffset++) = 0;
*(lpTemp + lOffset++) = 0;
}
}
for(i=0; i<width; i++)
{
lOffset = this->PixelOffset(0, i, wBytesPerLine);
{
*(lpTemp + lOffset++) = 0;
*(lpTemp + lOffset++) = 0;
*(lpTemp + lOffset++) = 0;
}
}
for(i=0; i<width; i++)
{
lOffset = this->PixelOffset(height-1, i, wBytesPerLine);
{
*(lpTemp + lOffset++) = 0;
*(lpTemp + lOffset++) = 0;
*(lpTemp + lOffset++) = 0;
}
}
//把暂时区域的点拷贝到原句柄区域下面
memcpy(lpData, lpTemp, wBytesPerLine*height);
delete [] lpTemp;
GlobalUnlock(hDIB);
}
void DIB::DeleteFasleEye(HANDLE hDIB, CRect facelocation)
{
LPBYTE lpData;
LPBITMAPINFOHEADER lpbi;
int height;
int width;
long lOffset;
WORD wBytesPerLine;
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
height = lpbi->biHeight;
width = lpbi->biWidth;
lpData = this->FindDIBBits(hDIB);
wBytesPerLine = this->BytePerLine(hDIB);
for (int i=0; i<height; i++)
for (int j=0; j<width; j++)
{
lOffset = this->PixelOffset(i, j, wBytesPerLine);
if(*(lpData + lOffset) == 255)
{
if(i<(facelocation.bottom+facelocation.top)/2)
{
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 0;
}
}
}
GlobalUnlock(hDIB);
}
void DIB::DeleteScatePoint(HANDLE hDIB)
{
LPBITMAPINFOHEADER lpbi;
int height;
int width;
LPBYTE lpData;
WORD wBytesPerLine;
long lOffset;
//得到图象的基本信息
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
height = lpbi->biHeight;
width = lpbi->biWidth;
wBytesPerLine = this->BytePerLine(hDIB);
lpData = this->FindDIBBits(hDIB);
for (int i=0; i<height; i++)
for(int j=0; j<width; j++)
{
//得到偏移
lOffset = this->PixelOffset(i, j, wBytesPerLine);
//如果当前点为白色点
if(*(lpData + lOffset) == 255)
{
//设定判断数组
for(int ii = 0;ii<ImgRange;ii++)
for (int jj=0; jj<ImgRange; jj++)
this->lab[ii][jj] = false;
//设定判断长度
this->lenth=0;
//判断是否为离散点
bool judge = this->IsScaterPoint(j, i, width,height,lpData,wBytesPerLine,3,this->lab);
if(!judge)
{
//是离散点则把该点设置为黑色
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 0;
}
}
}
GlobalUnlock(hDIB);
}
void DIB:: MouseMap(LPBYTE lpRgb, const LPBYTE lpYcc, WORD wBytesPerLine, CRect faceLocation)
{
//下面的循环在人脸的区域内实现嘴巴的匹配
for (int i=faceLocation.top; i<faceLocation.bottom; i++)
for (int j=faceLocation.left; j<faceLocation.right; j++)
{
//得到偏移
long lOffset = this->PixelOffset(i, j, wBytesPerLine);
//得到cr,cb的数值
int cr = *(lpYcc+lOffset+1);
int cb = *(lpYcc+lOffset+2);
//标志
bool lab;
int mapm;
//根据cr的数值设定标志
cr = cr-143;
if(cr <-5 || cr>5)
{
cr = 0;
}
cr *=cr;
if(cr>16)
lab = true;
else
lab = false;
//根据cb的时值设定标志
cb= cb-120;
if(cb<-5 || cb >5)
{
cb = 0;
if(lab = true)
lab = false;
}
//如果cr,cb两项数值都在设定的范围之内,则设定颜色位白色,否则黑色
if(lab)
mapm = 255;
else
mapm = 0;
*(lpRgb + lOffset++) = mapm;
*(lpRgb + lOffset++) = mapm;
*(lpRgb + lOffset++) = mapm;
}
}
void DIB::MouthCenter(HANDLE hDIB, CRect faceLocation, CPoint &mouthLocation)
{
LPBITMAPINFOHEADER lpbi;
int height;
int width;
long lOffset;
WORD wBytesPerLine;
LPBYTE lpData;
//得到图象的基本信息
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
height = lpbi->biHeight;
width = lpbi->biWidth;
wBytesPerLine = this->BytePerLine(hDIB);
lpData = this->FindDIBBits(hDIB);
//下面的三个变量用来累计嘴巴区域的象素的x,y和象素点数
int xnum = 0 ;
int ynum = 0 ;
int count = 0;
for (int i=faceLocation.top; i<faceLocation.bottom; i++)
for (int j=faceLocation.left; j<faceLocation.right; j++)
{
lOffset = this->PixelOffset(i, j, wBytesPerLine);
//白色点
if(*(lpData + lOffset) == 255)
{
//x值加
xnum +=j;
//y值加
ynum +=i;
//点数加
count++;
}
}
//得到中心点位置
mouthLocation.x = xnum/count;
mouthLocation.y = ynum/count;
//把中心点设置位绿色
lOffset = this->PixelOffset(mouthLocation.y, mouthLocation.x, wBytesPerLine);
*(lpData + lOffset++) =0;
*(lpData + lOffset++) =255;
*(lpData + lOffset++) =0;
GlobalUnlock(hDIB);
}
void DIB::EyeCenter(HANDLE hDIB, CRect faceLocation, CPoint &eye1, CPoint &eye2)
{
LPBITMAPINFOHEADER lpbi;
LPBYTE lpData;
long lOffset;
WORD wBytesPerLine;
int height;
int width;
int pixelnum =0;
int num =0;
//得到图象基本信息
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
height = lpbi->biHeight;
width = lpbi->biWidth;
lpData = this->FindDIBBits(hDIB);
wBytesPerLine = this->BytePerLine(hDIB);
//考察人脸区域
for(int i=faceLocation.top; i<faceLocation.bottom; i++)
for (int j=faceLocation.left; j<faceLocation.right; j++)
{
lOffset = this->PixelOffset(i, j, wBytesPerLine);
//白色点
if(*(lpData + lOffset) == 255)
//递归统计象素并修改象素值
this->RecursiveCal(lpData,i,j,wBytesPerLine,pixelnum,++num);
}
//初始化眼睛的坐标
eye1.x =0;
eye1.y =0;
eye2.x =0;
eye2.y =0;
//初始化象素点个数
int eye1count=0;
int eye2count =0;
for (i=faceLocation.top; i<faceLocation.bottom; i++)
for (int j=faceLocation.left; j<faceLocation.right; j++)
{
lOffset = this->PixelOffset(i, j, wBytesPerLine);
//如果象素点的数值为1
if(*(lpData + lOffset) == 1)
{
//眼睛1的横坐标和纵坐标加上当前点的坐标值
eye1.x +=j;
eye1.y +=i;
eye1count++;
//把当前点改成白色
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 255;
}
//如果当前象素的数值为2
else if(*(lpData + lOffset) == 2)
{
//眼睛2的横坐标和纵坐标加上当前点的坐标值
eye2.x +=j;
eye2.y +=i;
//象素点个数加一
eye2count++;
//把当前点设置为白色
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 255;
}
}
//计算眼睛的中心点坐标
eye1.x /=eye1count;
eye1.y /=eye1count;
eye2.x /=eye2count;
eye2.y /=eye2count;
//把中心点设置为绿色
lOffset = this->PixelOffset(eye1.y, eye1.x ,wBytesPerLine);
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 0;
lOffset = this->PixelOffset(eye2.y, eye2.x ,wBytesPerLine);
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 0;
GlobalUnlock(hDIB);
}
void DIB::EllipseFace(HANDLE hDIB, CPoint mouth, CPoint eye1, CPoint eye2)
{
LPBYTE lpData;
LPBITMAPINFOHEADER lpbi;
int width;
int height;
WORD wBytesPerLine;
long lOffset;
//得到图象的基本信息
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
height = lpbi->biHeight;
width = lpbi->biWidth;
lpData = this->FindDIBBits(hDIB);
wBytesPerLine = this->BytePerLine(hDIB);
//用dda算法画三角形
this->DdaLine(mouth,eye1,lpData,wBytesPerLine);
this->DdaLine(mouth,eye2,lpData,wBytesPerLine);
this->DdaLine(eye1,eye2,lpData,wBytesPerLine);
//椭圆的中心点和两个焦点坐标
int ellipsecenter_x;
int ellipsecenter_y;
int ellipseFocusTop_x;
int ellipseFocusTop_y;
int ellipseFocusBottom_x;
int ellipseFocusBottom_y;
//根据眼睛和嘴巴的坐标计算椭圆的中心点坐标
ellipsecenter_x = (eye1.x + eye2.x + mouth.x )/3;
ellipsecenter_y = (eye1.y + eye2.y)/2 -abs(eye2.x - eye1.x)/2;
//上面的焦点
ellipseFocusTop_x = ellipsecenter_x;
ellipseFocusBottom_x = ellipsecenter_x;
//下面的焦点
ellipseFocusTop_y = ellipsecenter_y + (eye1.y +eye2.y)/2 -mouth.y;
ellipseFocusBottom_y = ellipsecenter_y - ((eye1.y +eye2.y)/2 -mouth.y)+2;
//长轴
int a = (eye1.x-eye2.x)*2-2;
for (int i=0; i<height; i++)
for (int j=0; j<width; j++)
{
//得到一个点到两个焦点的距离和
int lenth = sqrt(pow(j-ellipseFocusTop_x,2)+pow(i-ellipseFocusTop_y,2))
+sqrt(pow(j-ellipseFocusBottom_x,2)+ pow(i-ellipseFocusBottom_y,2));
//判断距离和与长轴的关系
if(lenth<2*a+2 && lenth >2*a-2)
{
//把点设置为绿色
lOffset = this->PixelOffset(i, j, wBytesPerLine);
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 0;
}
}
GlobalUnlock(hDIB);
}
void DIB::DdaLine(CPoint from, CPoint end, LPBYTE lpData, WORD wBytesPerLine)
{
//x,y的增量
float delta_x;
float delta_y;
//x,y的坐标
float x;
float y;
//x,y上的差值
int dx;
int dy;
//总的步长
int steps;
int k;
//得到x,y的差值
dx = end.x - from.x;
dy = end.y - from.y;
//判断x,y上的差值大小,确定步长
if(abs(dx) > abs(dy))
{
steps = abs(dx);
}
else
{
steps = abs(dy);
}
//得到每次增量的大小
delta_x = (float)dx / (float)steps;
delta_y = (float)dy / (float)steps;
//设定x,y的起点
x = (float)from.x;
y = (float)from.y;
//设定初始点的颜色为绿色
long lOffset = this->PixelOffset(y, x, wBytesPerLine);
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 0;
//根据计算得到的步长,把直线上的点填充成绿色
for (k=1;k<=steps; k++)
{
//x,y分别加上各自的增量
x+=delta_x;
y+=delta_y;
//设置点的颜色
lOffset = this->PixelOffset(y, x, wBytesPerLine);
*(lpData + lOffset++) = 0;
*(lpData + lOffset++) = 255;
*(lpData + lOffset++) = 0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -