C#開辟的人臉閣下類似度盤算軟件源碼剖析。本站提示廣大學習愛好者:(C#開辟的人臉閣下類似度盤算軟件源碼剖析)文章只能為提供參考,不一定能成為您想要的結果。以下是C#開辟的人臉閣下類似度盤算軟件源碼剖析正文
本文實例講述了C#開辟的人臉閣下類似度盤算軟件。分享給年夜家供年夜家參考。詳細剖析以下:
模擬湖南衛視快活年夜本營中所應用的一款人臉閣下對稱類似度盤算軟件,本身寫的一個小軟件,應用說話是C#,願望跟愛好這個軟件的同志們同享!
1. FaceClass類法式
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Drawing.Drawing2D; namespace FaceSmile { class FaceClass { /// <summary> /// 左臉對稱函數 /// </summary> /// <param name="a"></param> /// <returns></returns> public static Bitmap FaceFlipLeft(Bitmap a) { Rectangle rect = new Rectangle(0, 0, a.Width, a.Height); System.Drawing.Imaging.BitmapData srcData = a.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, a.PixelFormat); IntPtr ptr = srcData.Scan0; int bytes = 0; bytes = srcData.Stride * a.Height; byte[] grayValues = new byte[bytes]; System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes); byte[] temp = new byte[bytes]; temp = (byte[])grayValues.Clone(); for (int j = 0; j < a.Height; j++) { for (int i = 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); return a; } /// <summary> /// 右臉對稱函數 /// </summary> /// <param name="a"></param> /// <returns></returns> public static Bitmap FaceFlipRight(Bitmap a) { Rectangle rect = new Rectangle(0, 0, a.Width, a.Height); System.Drawing.Imaging.BitmapData srcData = a.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, a.PixelFormat); IntPtr ptr = srcData.Scan0; int bytes = 0; bytes = srcData.Stride * a.Height; byte[] grayValues = new byte[bytes]; System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes); byte[] temp = new byte[bytes]; temp = (byte[])grayValues.Clone(); for (int j = 0; j < a.Height; j++) { for (int i = 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); return a; } /// <summary> /// 界說膚色檢測函數 /// </summary> /// <param name="a"></param> /// <returns></returns> public static Bitmap SkinDetect(Bitmap a) { Rectangle rect = new Rectangle(0, 0, a.Width, a.Height); System.Drawing.Imaging.BitmapData bmpData = a.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb); int stride = bmpData.Stride; unsafe { byte* pIn = (byte*)bmpData.Scan0.ToPointer(); byte* P; int R, G, B; double r, g, Fupr, Flor, Wrg; for (int y = 0; y < a.Height; y++) { for (int x = 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); return a; } /// <summary> /// 界說圖象灰度化函數 /// </summary> /// <param name="src"></param> /// <returns></returns> public static Bitmap ImageGray(Bitmap src) { int w = src.Width; int h = src.Height; //構建與原圖象年夜小一樣的模疆土像 Bitmap dstBitmap = new Bitmap(src.Width, src.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); //將原圖象存入內存 System.Drawing.Imaging.BitmapData srcData = src.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb); System.Drawing.Imaging.BitmapData dstData = dstBitmap.LockBits(new Rectangle(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; int stride = srcData.Stride; int r, g, b; for (int y = 0; y < h; y++) { for (int x = 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); return dstBitmap; } } } }
2. SameRatioClass類法式
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Drawing.Drawing2D; namespace FaceSmile { class SameRatioClass { /// <summary> /// 閣下臉類似度函數 /// </summary> /// <param name="src"></param> /// <param name="dst"></param> /// <returns></returns> public static double SameRatio(Bitmap src, Bitmap dst) { byte[] srcData = GetBytes(src); byte[] dstData = GetBytes(dst); double ratio = 0; int sum = 0; int std=0; for (int i = 0; i < srcData.Length; i++) { sum += Math.Abs(srcData[i] - dstData[i]); std += srcData[i]; } ratio = 100-(double)(100*sum / std); return ratio; } /// <summary> /// 獲得圖象信息函數 /// </summary> /// <param name="src"></param> /// <returns></returns> private static byte[] GetBytes(Bitmap src) { int w = src.Width; int h = src.Height; byte[] dataImage = new byte[w * h]; System.Drawing.Imaging.BitmapData srcData = src.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb); unsafe { byte* pIn = (byte*)srcData.Scan0.ToPointer(); byte* p; int stride = srcData.Stride; int r, g, b; for (int y = 0; y < h; y++) { for (int x = 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); return dataImage; } } } }
3. 主窗體法式
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace FaceSmile { public partial class Form1 : Form { public Form1() { InitializeComponent(); groupBox1.Visible = true; groupBox2.Visible = false; } #region 全局變量界說 //界說原始圖象變量 private Bitmap src ; //界說圖象類似度變量 private double ratio = 0; //界說圖象途徑變量 private string curFileName; //界說人臉地位圖象調劑變量 private int numAdjust = 0; #endregion #region 軟件操作 //左臉對稱 private void button1_Click(object sender, EventArgs e) { if (src != null) { Bitmap temp = (Bitmap)src.Clone(); Bitmap a = FaceClass.FaceFlipLeft(temp); pictureBox1.Image = (Image)a; ratio = SameRatioClass.SameRatio(a, src); label1.Text = ratio.ToString(); } else { MessageBox.Show("Please open one image!"); } } //右臉對稱 private void button2_Click(object sender, EventArgs e) { if (src != null) { Bitmap temp = (Bitmap)src.Clone(); Bitmap a = FaceClass.FaceFlipRight(temp); pictureBox1.Image = (Image)a; ratio = SameRatioClass.SameRatio(a, src); label1.Text = ratio.ToString(); } else { MessageBox.Show("Please open one image!"); } } //翻開圖象 private void button3_Click(object sender, EventArgs e) { OpenImage(); if (src != null) { pictureBox1.Image = (Image)src; pictureBox1.Width = src.Width; pictureBox1.Height = src.Height; } else { MessageBox.Show("Please open one image!"); } } //保留圖象 private void button4_Click(object sender, EventArgs e) { SaveImage(); } //圖象翻開函數 private void OpenImage() { try { ofd.Filter = "All files (*.*)|*.*|bmp files (*.bmp)|*.bmp|jpeg files (*.jpg)|*.jpg|png files (*.png)|*.png"; ofd.Title = "翻開"; ofd.ShowHelp = true; if (ofd.ShowDialog() == DialogResult.OK) { curFileName = ofd.FileName; src = new Bitmap(curFileName); } } catch (Exception ex) { MessageBox.Show(ex.Message); } } //圖象保留函數 private void SaveImage() { try { sfd.Filter = "保留(*.bmp)|*.bmp"; sfd.Title = "保留"; sfd.ShowHelp = true; if (sfd.ShowDialog() == DialogResult.OK) { Bitmap temp = (Bitmap)pictureBox1.Image; temp.Save(sfd.FileName, System.Drawing.Imaging.ImageFormat.Bmp); } } catch (Exception ex) { MessageBox.Show(ex.Message); } } //其他操作 private void button5_Click(object sender, EventArgs e) { groupBox2.Location = new Point(groupBox1.Location.X, groupBox1.Location.Y); groupBox2.Visible = true; groupBox1.Visible = false; } //膚色檢測 private void button6_Click(object sender, EventArgs e) { if (pictureBox1.Image != null) { pictureBox1.Image = (Image)FaceClass.SkinDetect((Bitmap)pictureBox1.Image); } else { MessageBox.Show("Please open one image!"); } } //前往操作 private void button7_Click(object sender, EventArgs e) { groupBox1.Visible = true; groupBox2.Visible = false; } //灰度化 private void button8_Click(object sender, EventArgs e) { if (pictureBox1.Image != null) { pictureBox1.Image = (Image)FaceClass.ImageGray((Bitmap)pictureBox1.Image); } else { MessageBox.Show("Please open one image!"); } } //博客銜接 private void label2_Click(object sender, EventArgs e) { System.Diagnostics.Process.Start("IEXPLORE.EXE", "http://dongtingyueh.blog.163.com/"); } //修改人臉地位 private void button9_Click(object sender, EventArgs e) { if (numAdjust != 0) { int a = numAdjust; int b = src.Width - a; int result = a < b ? a : b; if (result == b) { src = src.Clone(new Rectangle(src.Width - 2 * result, 0, 2 * result, src.Height), src.PixelFormat); } else { src = src.Clone(new Rectangle(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 人臉地位修改 private void trackBar1_Scroll(object sender, EventArgs e) { if (src != null) { trackBar1.Maximum = src.Width; trackBar1.Minimum = 0; numAdjust = trackBar1.Value; label4.Text = numAdjust.ToString(); } else { MessageBox.Show("Please open one image!"); } } private void trackBar1_ValueChanged(object sender, EventArgs e) { pictureBox1.Invalidate(); } private void trackBar1_MouseUp(object sender, MouseEventArgs e) { if (src != null) { Graphics g = pictureBox1.CreateGraphics(); g.DrawLine(new Pen(Color.Red, 2), new Point((int)(numAdjust), 0), new Point((int)(numAdjust), src.Height)); g.Dispose(); } else { MessageBox.Show("Please open one image!"); } } #endregion } }
願望本文所述對年夜家的C#法式設計有所贊助。