基於C#的眼部瞳孔追蹤 與 雙圖片融合成像
阿新 • • 發佈:2018-12-09
前期我們先用畫餅充飢的方法來做研發與測試
手動畫人眼
測試演算法
藍線中心點為瞳孔中心,可以看到比較準。
具體程式碼如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Drawing.Imaging; using System.Runtime.InteropServices; namespace WindowsFormsApplication8 { public partial class Form1 : Form { Point p = new Point(); static Bitmap b; int h; int w; Bitmap b1; BitmapData bd; BitmapData bd1; public Form1() { InitializeComponent(); this.Show(); String s = ""; b = null; OpenFileDialog ofd = new OpenFileDialog(); if (ofd.ShowDialog() == DialogResult.OK) { s = ofd.FileName; b = (Bitmap)Bitmap.FromFile(s, false); int[] point = getdivimg(b); try { //Bitmap bmp = new Bitmap(b.Width, b.Height, PixelFormat.Format32bppArgb); MessageBox.Show(point[0] + "---" + point[1]); p.X = point[1]; p.Y = point[0]; this.pictureBox1.Load(s); //g = Graphics.FromImage(bmp); //g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; //g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; //Image img = Image.FromFile(s); //g.DrawImage(img, 0, 0); pictureBox1.Refresh(); //g.FillEllipse(Brushes.Red, 0, 0, 100, 100); ////this.pictureBox1.Image = img; //g.Dispose(); } catch (Exception e1) { MessageBox.Show(e1.Message); } } } private void Form1_Load(object sender, EventArgs e) { this.Show(); } public void setgray(Bitmap b) { ColorPalette cp = b.Palette; for (int i = 0; i < 256; i++) { cp.Entries[i] = Color.FromArgb(i, i, i); } b.Palette = cp; } public int[] getdivimg(Bitmap b) { h = b.Height; w = b.Width; Rectangle rect = new Rectangle(0, 0, w, h); bd = b.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); b1 = new Bitmap(b.Width, b.Height, PixelFormat.Format8bppIndexed); bd1 = b1.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); int len = bd.Stride * h; byte[] imgbyte = new byte[len]; Marshal.Copy(bd.Scan0, imgbyte, 0, len); int i = 0; int j = 0; int[] hist = new int[256]; int maxgray = 0; int maxpos = 0; int bogugray = 0; int bogupos = 0; try { for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { int t = imgbyte[i * bd.Stride + j]; hist[t]++; if (hist[t] > maxgray) { maxgray = hist[t]; maxpos = t; } } } bogugray = maxgray; for (int k = 9; k < maxpos; k++) { if (hist[k] < bogugray) { bogugray = hist[k]; bogupos = k; } } int[] apoint = getcenterpoint(imgbyte, 0, h, 0, w, bogupos); MessageBox.Show(apoint[0] + "---" + apoint[1]); int[] point = getcenterpoint(imgbyte, apoint[0] - 100, apoint[0] + 100, apoint[1] - 100, apoint[1] + 100, bogupos); MessageBox.Show(point[0] + "---" + point[1]); return point; } catch (Exception e1) { MessageBox.Show(e1.Message); return null; } } double r; public int[] getcenterpoint(byte[] imgbyte, int xstart = 0, int xend = 378, int ystart = 0, int yend = 681, int thresh=0) { if(xstart < 0) xstart=0; if (xend > h) xend = h; if (ystart < 0) ystart = 0; if (yend > w) yend = w; bool firstpoint = false; int firstx = 0; int firsty = 0; int xpossum = 0, ypossum = 0, count = 0; for (int i = xstart; i < xend; i++) { for (int j = ystart; j < yend; j++) { //Console.WriteLine(i * bd.Stride + j); int t = imgbyte[i * bd.Stride + j]; if (t <= thresh) { if (!firstpoint) { firstx = i; firsty = j; firstpoint = true; } imgbyte[i * bd.Stride + j] = (byte)0; xpossum += i; ypossum += j; count++; } else { imgbyte[i * bd.Stride + j] = (byte)255; } } } //b.UnlockBits(bd); int[] point = new int[2]; point[0] = xpossum / count; point[1] = ypossum / count; r = Math.Sqrt(Math.Abs(firstx - point[0]) * Math.Abs(firstx - point[0]) + Math.Abs(firsty - point[1]) * Math.Abs(firsty - point[1])); Console.WriteLine(r); return point; } private void pictureBox1_Paint(object sender, PaintEventArgs e) { } private void pictureBox1_Paint_1(object sender, PaintEventArgs e) { Pen pen=new Pen (Color .Blue,50); Point q = new Point(p.X + 1, p.Y + 1); e.Graphics.DrawLine(pen, p, q); } private void pictureBox1_Click(object sender, EventArgs e) { } } }
那麼對真實人眼準不準呢
接下來是讀入兩副眼睛圖片並做拼接融合
上面是先用picturebox做的偽融合,真正的融合需要在記憶體地址中融合,用到Marshal
偽融合程式碼:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Drawing.Imaging; using System.Runtime.InteropServices; namespace WindowsFormsApplication8 { public partial class Form1 : Form { Point p = new Point(); Point p2 = new Point(); static Bitmap b; static Bitmap b2; int h; int w; Bitmap b1; BitmapData bd; BitmapData bd1; public Form1() { InitializeComponent(); this.Show(); String s = ""; b = null; OpenFileDialog ofd = new OpenFileDialog(); if (ofd.ShowDialog() == DialogResult.OK) { s = ofd.FileName; b = (Bitmap)Bitmap.FromFile(s, false); int[] point = getdivimg(b); try { //Bitmap bmp = new Bitmap(b.Width, b.Height, PixelFormat.Format32bppArgb); MessageBox.Show(point[0] + "---" + point[1]); p.X = point[1]; p.Y = point[0]; this.pictureBox1.Load(s); //g = Graphics.FromImage(bmp); //g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; //g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; //Image img = Image.FromFile(s); //g.DrawImage(img, 0, 0); pictureBox1.Refresh(); //g.FillEllipse(Brushes.Red, 0, 0, 100, 100); ////this.pictureBox1.Image = img; //g.Dispose(); } catch (Exception e1) { MessageBox.Show(e1.Message); } } if (ofd.ShowDialog() == DialogResult.OK) { s = ofd.FileName; b2 = (Bitmap)Bitmap.FromFile(s, false); int[] point = getdivimg(b2); try { //Bitmap bmp = new Bitmap(b.Width, b.Height, PixelFormat.Format32bppArgb); MessageBox.Show(point[0] + "---" + point[1]); p2.X = point[1]; p2.Y = point[0]; this.pictureBox2.Load(s); //g = Graphics.FromImage(bmp); //g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; //g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; //Image img = Image.FromFile(s); //g.DrawImage(img, 0, 0); pictureBox2.Refresh(); //g.FillEllipse(Brushes.Red, 0, 0, 100, 100); ////this.pictureBox1.Image = img; //g.Dispose(); } catch (Exception e1) { MessageBox.Show(e1.Message); } } } private void Form1_Load(object sender, EventArgs e) { this.Show(); } public void setgray(Bitmap b) { ColorPalette cp = b.Palette; for (int i = 0; i < 256; i++) { cp.Entries[i] = Color.FromArgb(i, i, i); } b.Palette = cp; } public int[] getdivimg(Bitmap b) { h = b.Height; w = b.Width; Rectangle rect = new Rectangle(0, 0, w, h); bd = b.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); b1 = new Bitmap(b.Width, b.Height, PixelFormat.Format8bppIndexed); bd1 = b1.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); int len = bd.Stride * h; byte[] imgbyte = new byte[len]; Marshal.Copy(bd.Scan0, imgbyte, 0, len); int i = 0; int j = 0; int[] hist = new int[256]; int maxgray = 0; int maxpos = 0; int bogugray = 0; int bogupos = 0; try { for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { int t = imgbyte[i * bd.Stride + j]; hist[t]++; if (hist[t] > maxgray) { maxgray = hist[t]; maxpos = t; } } } bogugray = maxgray; for (int k = 9; k < maxpos; k++) { if (hist[k] < bogugray) { bogugray = hist[k]; bogupos = k; } } int[] apoint = getcenterpoint(imgbyte, 0, h, 0, w, bogupos); MessageBox.Show(apoint[0] + "---" + apoint[1]); int[] point = getcenterpoint(imgbyte, apoint[0] - 100, apoint[0] + 100, apoint[1] - 100, apoint[1] + 100, bogupos); MessageBox.Show(point[0] + "---" + point[1]); return point; } catch (Exception e1) { MessageBox.Show(e1.Message); return null; } } double r; public int[] getcenterpoint(byte[] imgbyte, int xstart = 0, int xend = 378, int ystart = 0, int yend = 681, int thresh=0) { if(xstart < 0) xstart=0; if (xend > h) xend = h; if (ystart < 0) ystart = 0; if (yend > w) yend = w; bool firstpoint = false; int firstx = 0; int firsty = 0; int xpossum = 0, ypossum = 0, count = 0; for (int i = xstart; i < xend; i++) { for (int j = ystart; j < yend; j++) { //Console.WriteLine(i * bd.Stride + j); int t = imgbyte[i * bd.Stride + j]; if (t <= thresh) { if (!firstpoint) { firstx = i; firsty = j; firstpoint = true; } imgbyte[i * bd.Stride + j] = (byte)0; xpossum += i; ypossum += j; count++; } else { imgbyte[i * bd.Stride + j] = (byte)255; } } } //b.UnlockBits(bd); int[] point = new int[2]; point[0] = xpossum / count; point[1] = ypossum / count; r = Math.Sqrt(Math.Abs(firstx - point[0]) * Math.Abs(firstx - point[0]) + Math.Abs(firsty - point[1]) * Math.Abs(firsty - point[1])); Console.WriteLine(r); return point; } private void pictureBox1_Paint(object sender, PaintEventArgs e) { } private void pictureBox1_Paint_1(object sender, PaintEventArgs e) { Pen pen = new Pen(Color.Blue, 50); Point q = new Point(p.X, p.Y + 1); e.Graphics.DrawLine(pen, p, q); Point q2 = new Point(p.X, p.Y - 1); e.Graphics.DrawLine(pen, p, q2); Point q3 = new Point(p.X+1, p.Y ); e.Graphics.DrawLine(pen, p, q3); Point q4 = new Point(p.X-1, p.Y); e.Graphics.DrawLine(pen, p, q4); } private void pictureBox1_Click(object sender, EventArgs e) { } private void pictureBox2_Paint(object sender, PaintEventArgs e) { Pen pen = new Pen(Color.Blue, 50); Point q = new Point(p2.X, p2.Y + 1); e.Graphics.DrawLine(pen, p2, q); Point q2 = new Point(p2.X, p2.Y - 1); e.Graphics.DrawLine(pen, p2, q2); Point q3 = new Point(p2.X + 1, p2.Y); e.Graphics.DrawLine(pen, p2, q3); Point q4 = new Point(p2.X - 1, p2.Y); e.Graphics.DrawLine(pen, p2, q4); } } }
真正融合程式碼:
在自己開發的程式中,初次嘗試byte上的融合
出現了這種情況
右邊為融合之後的,出現了間隔柵格+噪聲
做了一些除錯以後,感覺問題應該是在於 變數沒上鎖,變數還沒進入 就被讀出,所以會產生噪聲和黑色蒙版
嘗試在變數上加鎖