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#程序设计有所帮助。