C#开发的人脸左右相似度计算软件源码分析
本文实例讲述了C#开发的人脸左右相似度计算软件。分享给大家供大家参考。具体分析如下:
模仿湖南卫视快乐大本营中所使用的一款人脸左右对称相似度计算软件,自己写的一个小软件,使用语言是C#,希望跟喜欢这个软件的同志们共享!
1.FaceClass类程序
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Drawing;
usingSystem.Drawing.Drawing2D;
namespaceFaceSmile
{
classFaceClass
{
///<summary>
///左脸对称函数
///</summary>
///<paramname="a"></param>
///<returns></returns>
publicstaticBitmapFaceFlipLeft(Bitmapa)
{
Rectanglerect=newRectangle(0,0,a.Width,a.Height);
System.Drawing.Imaging.BitmapDatasrcData=a.LockBits(rect,System.Drawing.Imaging.ImageLockMode.ReadWrite,a.PixelFormat);
IntPtrptr=srcData.Scan0;
intbytes=0;
bytes=srcData.Stride*a.Height;
byte[]grayValues=newbyte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr,grayValues,0,bytes);
byte[]temp=newbyte[bytes];
temp=(byte[])grayValues.Clone();
for(intj=0;j<a.Height;j++)
{
for(inti=0;i<(int)(a.Width/2);i++)
{
temp[(a.Width-2-i)*3+j*srcData.Stride]=temp[i*3+j*srcData.Stride];
temp[(a.Width-2-i)*3+1+j*srcData.Stride]=temp[i*3+1+j*srcData.Stride];
temp[(a.Width-2-i)*3+2+j*srcData.Stride]=temp[i*3+2+j*srcData.Stride];
}
}
grayValues=(byte[])temp.Clone();
System.Runtime.InteropServices.Marshal.Copy(grayValues,0,ptr,bytes);
a.UnlockBits(srcData);
returna;
}
///<summary>
///右脸对称函数
///</summary>
///<paramname="a"></param>
///<returns></returns>
publicstaticBitmapFaceFlipRight(Bitmapa)
{
Rectanglerect=newRectangle(0,0,a.Width,a.Height);
System.Drawing.Imaging.BitmapDatasrcData=a.LockBits(rect,System.Drawing.Imaging.ImageLockMode.ReadWrite,a.PixelFormat);
IntPtrptr=srcData.Scan0;
intbytes=0;
bytes=srcData.Stride*a.Height;
byte[]grayValues=newbyte[bytes];
System.Runtime.InteropServices.Marshal.Copy(ptr,grayValues,0,bytes);
byte[]temp=newbyte[bytes];
temp=(byte[])grayValues.Clone();
for(intj=0;j<a.Height;j++)
{
for(inti=0;i<(int)(a.Width/2);i++)
{
temp[i*3+j*srcData.Stride]=temp[(a.Width-2-i)*3+j*srcData.Stride];
temp[i*3+1+j*srcData.Stride]=temp[(a.Width-2-i)*3+1+j*srcData.Stride];
temp[i*3+2+j*srcData.Stride]=temp[(a.Width-2-i)*3+2+j*srcData.Stride];
}
}
grayValues=(byte[])temp.Clone();
System.Runtime.InteropServices.Marshal.Copy(grayValues,0,ptr,bytes);
a.UnlockBits(srcData);
returna;
}
///<summary>
///定义肤色检测函数
///</summary>
///<paramname="a"></param>
///<returns></returns>
publicstaticBitmapSkinDetect(Bitmapa)
{
Rectanglerect=newRectangle(0,0,a.Width,a.Height);
System.Drawing.Imaging.BitmapDatabmpData=a.LockBits(rect,System.Drawing.Imaging.ImageLockMode.ReadWrite,System.Drawing.Imaging.PixelFormat.Format24bppRgb);
intstride=bmpData.Stride;
unsafe
{
byte*pIn=(byte*)bmpData.Scan0.ToPointer();
byte*P;
intR,G,B;
doubler,g,Fupr,Flor,Wrg;
for(inty=0;y<a.Height;y++)
{
for(intx=0;x<a.Width;x++)
{
P=pIn;
B=P[0];
G=P[1];
R=P[2];
if(R+G+B==0)
{
r=0;
g=0;
}
else
{
r=(R/(R+G+B));
g=(G/(R+G+B));
}
Fupr=(1.0743*r+0.1452-1.3767*r*r);
Flor=(0.5601*r+0.1766-0.776*r*r);
Wrg=(r-0.33)*(r-0.33)+(g-0.33)*(g-0.33);
if((R-G>=45)&&((R>G)&&(G>B))&&(Fupr>g)&&(Wrg>=0.0004))
{
P[0]=(byte)B;
P[1]=(byte)G;
P[2]=(byte)R;
}
else
{
P[0]=0;
P[1]=0;
P[2]=0;
}
pIn+=3;
}
pIn+=stride-a.Width*3;
}
}
a.UnlockBits(bmpData);
returna;
}
///<summary>
///定义图像灰度化函数
///</summary>
///<paramname="src"></param>
///<returns></returns>
publicstaticBitmapImageGray(Bitmapsrc)
{
intw=src.Width;
inth=src.Height;
//构建与原图像大小一样的模版图像
BitmapdstBitmap=newBitmap(src.Width,src.Height,System.Drawing.Imaging.PixelFormat.Format24bppRgb);
//将原图像存入内存
System.Drawing.Imaging.BitmapDatasrcData=src.LockBits(newRectangle(0,0,w,h),System.Drawing.Imaging.ImageLockMode.ReadOnly,System.Drawing.Imaging.PixelFormat.Format24bppRgb);
System.Drawing.Imaging.BitmapDatadstData=dstBitmap.LockBits(newRectangle(0,0,w,h),System.Drawing.Imaging.ImageLockMode.WriteOnly,System.Drawing.Imaging.PixelFormat.Format24bppRgb);
unsafe
{
byte*pIn=(byte*)srcData.Scan0.ToPointer();
byte*pOut=(byte*)dstData.Scan0.ToPointer();
byte*p;
intstride=srcData.Stride;
intr,g,b;
for(inty=0;y<h;y++)
{
for(intx=0;x<w;x++)
{
p=pIn;
r=p[2];
g=p[1];
b=p[0];
//调用图像灰度化公式
pOut[0]=pOut[1]=pOut[2]=(byte)(b*0.114+g*0.587+r*0.299);
pIn+=3;
pOut+=3;
}
pIn+=srcData.Stride-w*3;
pOut+=srcData.Stride-w*3;
}
src.UnlockBits(srcData);
dstBitmap.UnlockBits(dstData);
returndstBitmap;
}
}
}
}
2.SameRatioClass类程序
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Drawing;
usingSystem.Drawing.Drawing2D;
namespaceFaceSmile
{
classSameRatioClass
{
///<summary>
///左右脸相似度函数
///</summary>
///<paramname="src"></param>
///<paramname="dst"></param>
///<returns></returns>
publicstaticdoubleSameRatio(Bitmapsrc,Bitmapdst)
{
byte[]srcData=GetBytes(src);
byte[]dstData=GetBytes(dst);
doubleratio=0;
intsum=0;
intstd=0;
for(inti=0;i<srcData.Length;i++)
{
sum+=Math.Abs(srcData[i]-dstData[i]);
std+=srcData[i];
}
ratio=100-(double)(100*sum/std);
returnratio;
}
///<summary>
///得到图像信息函数
///</summary>
///<paramname="src"></param>
///<returns></returns>
privatestaticbyte[]GetBytes(Bitmapsrc)
{
intw=src.Width;
inth=src.Height;
byte[]dataImage=newbyte[w*h];
System.Drawing.Imaging.BitmapDatasrcData=src.LockBits(newRectangle(0,0,w,h),System.Drawing.Imaging.ImageLockMode.ReadOnly,System.Drawing.Imaging.PixelFormat.Format24bppRgb);
unsafe
{
byte*pIn=(byte*)srcData.Scan0.ToPointer();
byte*p;
intstride=srcData.Stride;
intr,g,b;
for(inty=0;y<h;y++)
{
for(intx=0;x<w;x++)
{
p=pIn;
r=p[2];
g=p[1];
b=p[0];
dataImage[x+y*x]=(byte)((r+g+b)/3);
pIn+=3;
}
pIn+=srcData.Stride-w*3;
}
src.UnlockBits(srcData);
returndataImage;
}
}
}
}
3.主窗体程序
usingSystem;
usingSystem.Collections.Generic;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Windows.Forms;
namespaceFaceSmile
{
publicpartialclassForm1:Form
{
publicForm1()
{
InitializeComponent();
groupBox1.Visible=true;
groupBox2.Visible=false;
}
#region全局变量定义
//定义原始图像变量
privateBitmapsrc;
//定义图像相似度变量
privatedoubleratio=0;
//定义图像路径变量
privatestringcurFileName;
//定义人脸位置图像调整变量
privateintnumAdjust=0;
#endregion
#region软件操作
//左脸对称
privatevoidbutton1_Click(objectsender,EventArgse)
{
if(src!=null)
{
Bitmaptemp=(Bitmap)src.Clone();
Bitmapa=FaceClass.FaceFlipLeft(temp);
pictureBox1.Image=(Image)a;
ratio=SameRatioClass.SameRatio(a,src);
label1.Text=ratio.ToString();
}
else
{
MessageBox.Show("Pleaseopenoneimage!");
}
}
//右脸对称
privatevoidbutton2_Click(objectsender,EventArgse)
{
if(src!=null)
{
Bitmaptemp=(Bitmap)src.Clone();
Bitmapa=FaceClass.FaceFlipRight(temp);
pictureBox1.Image=(Image)a;
ratio=SameRatioClass.SameRatio(a,src);
label1.Text=ratio.ToString();
}
else
{
MessageBox.Show("Pleaseopenoneimage!");
}
}
//打开图像
privatevoidbutton3_Click(objectsender,EventArgse)
{
OpenImage();
if(src!=null)
{
pictureBox1.Image=(Image)src;
pictureBox1.Width=src.Width;
pictureBox1.Height=src.Height;
}
else
{
MessageBox.Show("Pleaseopenoneimage!");
}
}
//保存图像
privatevoidbutton4_Click(objectsender,EventArgse)
{
SaveImage();
}
//图像打开函数
privatevoidOpenImage()
{
try
{
ofd.Filter="Allfiles(*.*)|*.*|bmpfiles(*.bmp)|*.bmp|jpegfiles(*.jpg)|*.jpg|pngfiles(*.png)|*.png";
ofd.Title="打开";
ofd.ShowHelp=true;
if(ofd.ShowDialog()==DialogResult.OK)
{
curFileName=ofd.FileName;
src=newBitmap(curFileName);
}
}
catch(Exceptionex)
{
MessageBox.Show(ex.Message);
}
}
//图像保存函数
privatevoidSaveImage()
{
try
{
sfd.Filter="保存(*.bmp)|*.bmp";
sfd.Title="保存";
sfd.ShowHelp=true;
if(sfd.ShowDialog()==DialogResult.OK)
{
Bitmaptemp=(Bitmap)pictureBox1.Image;
temp.Save(sfd.FileName,System.Drawing.Imaging.ImageFormat.Bmp);
}
}
catch(Exceptionex)
{
MessageBox.Show(ex.Message);
}
}
//其他操作
privatevoidbutton5_Click(objectsender,EventArgse)
{
groupBox2.Location=newPoint(groupBox1.Location.X,groupBox1.Location.Y);
groupBox2.Visible=true;
groupBox1.Visible=false;
}
//肤色检测
privatevoidbutton6_Click(objectsender,EventArgse)
{
if(pictureBox1.Image!=null)
{
pictureBox1.Image=(Image)FaceClass.SkinDetect((Bitmap)pictureBox1.Image);
}
else
{
MessageBox.Show("Pleaseopenoneimage!");
}
}
//返回操作
privatevoidbutton7_Click(objectsender,EventArgse)
{
groupBox1.Visible=true;
groupBox2.Visible=false;
}
//灰度化
privatevoidbutton8_Click(objectsender,EventArgse)
{
if(pictureBox1.Image!=null)
{
pictureBox1.Image=(Image)FaceClass.ImageGray((Bitmap)pictureBox1.Image);
}
else
{
MessageBox.Show("Pleaseopenoneimage!");
}
}
//博客连接
privatevoidlabel2_Click(objectsender,EventArgse)
{
System.Diagnostics.Process.Start("IEXPLORE.EXE","http://dongtingyueh.blog.163.com/");
}
//修正人脸位置
privatevoidbutton9_Click(objectsender,EventArgse)
{
if(numAdjust!=0)
{
inta=numAdjust;
intb=src.Width-a;
intresult=a<b?a:b;
if(result==b)
{
src=src.Clone(newRectangle(src.Width-2*result,0,2*result,src.Height),src.PixelFormat);
}
else
{
src=src.Clone(newRectangle(0,0,2*result,src.Height),src.PixelFormat);
}
pictureBox1.Image=(Image)src;
pictureBox1.Width=src.Width;
pictureBox1.Height=src.Height;
}
trackBar1.Value=0;
label4.Text="0";
}
#endregion
#region人脸位置修正
privatevoidtrackBar1_Scroll(objectsender,EventArgse)
{
if(src!=null)
{
trackBar1.Maximum=src.Width;
trackBar1.Minimum=0;
numAdjust=trackBar1.Value;
label4.Text=numAdjust.ToString();
}
else
{
MessageBox.Show("Pleaseopenoneimage!");
}
}
privatevoidtrackBar1_ValueChanged(objectsender,EventArgse)
{
pictureBox1.Invalidate();
}
privatevoidtrackBar1_MouseUp(objectsender,MouseEventArgse)
{
if(src!=null)
{
Graphicsg=pictureBox1.CreateGraphics();
g.DrawLine(newPen(Color.Red,2),newPoint((int)(numAdjust),0),newPoint((int)(numAdjust),src.Height));
g.Dispose();
}
else
{
MessageBox.Show("Pleaseopenoneimage!");
}
}
#endregion
}
}
希望本文所述对大家的C#程序设计有所帮助。