using OpenCvSharp; using System; using System.Collections; using System.Collections.Generic; using System.Drawing; using CaptureEye; using Point = OpenCvSharp.Point; using System.Windows.Forms; namespace AssessEye { public class AssessEye { // 虹膜清晰度权重 double sharpnessWeight = 0.5; // 虹膜半径权重 double radiusWeight = 0.1; // 虹膜有效区域权重 double areaWeight = 0.2; // 虹膜对比度权重 double constrastWeight = 0.2; ////////////////////////// ///*** 程序主入口点 ***/// ////////////////////////// public double M_AssessEye(Bitmap bitmap, EyeParams eyeParams) { Mat FaceImage = OpenCvSharp.Extensions.BitmapConverter.ToMat(bitmap); // 有效虹膜区域 double usable_iris_area = eyeParams.Hm_Effect_Area; if (usable_iris_area == 0) { MessageBox.Show("虹膜质量打分:" + 0 + "\r\n有效区域不满足要求", "提示"); return 0; } //清晰度 double sharpness = SharpnessArea(FaceImage, eyeParams); // 虹膜-巩膜对比度 double iris_sclera_constrast = Iris_Sclera_Constrast(FaceImage, eyeParams); // 虹膜-瞳孔对比度 double iris_pupil_constrast = Iris_Pupil_Constrast(FaceImage, eyeParams); // 虹膜半径 int hm_radius = eyeParams.Hm_radius; // 质量评分 double assess_score = Assess_Score(sharpness, hm_radius, usable_iris_area, iris_sclera_constrast, iris_pupil_constrast); MessageBox.Show("虹膜质量打分:" + assess_score + "\r\n清晰度:" + sharpness + "\r\n半径:" + hm_radius + "\r\n有效区域:" + usable_iris_area + "\r\n虹膜巩膜对比度:" + iris_sclera_constrast + "\r\n虹膜瞳孔对比度:" + iris_pupil_constrast, "提示"); // 返回质量评分结果 return assess_score; //return 0.0; } ////////////////////////////// ///*** 虹膜-巩膜对比度 ***//// ////////////////////////////// unsafe double Iris_Sclera_Constrast(Mat FaceImage, EyeParams eyeParams) { ArrayList irisList = new ArrayList(); // 虹膜像素 ArrayList scleraList = new ArrayList(); // 巩膜像素 ArrayList pupilList = new ArrayList(); // 瞳孔像素 int cols = FaceImage.Cols; int rows = FaceImage.Rows; int minRow = eyeParams.Tk_row - eyeParams.Tk_radius; int maxRow = eyeParams.Tk_row + eyeParams.Tk_radius; // 巩膜像素范围(环形) // 以虹膜-巩膜边界的半径为1,选中圆形(内半径1.1,外半径1.2)中所有未被遮挡的像素 Mat scleraTemp = new Mat(rows, cols, MatType.CV_8UC1, new Scalar(0, 0, 0)); // 复制一张黑色图片 Cv2.Circle(scleraTemp, eyeParams.Hm_col, eyeParams.Hm_row, (int)(eyeParams.Hm_radius * 1.2), new Scalar(255, 255, 255), -1); // 画白色一个实心圆 Cv2.Circle(scleraTemp, eyeParams.Hm_col, eyeParams.Hm_row, (int)(eyeParams.Hm_radius * 1.1), new Scalar(0, 0, 0), -1); // 画一个黑色实心圆 int circle_row; int circle_col; int circle_raduis; iris_pupil_circle(eyeParams, out circle_row, out circle_col, out circle_raduis); // 虹膜像素范围(环形) // 圆形外半径为0.9,内半径延伸至两个边界未被遮挡部分的中点 Mat irisTemp = new Mat(rows, cols, MatType.CV_8UC1, new Scalar(0, 0, 0)); // 复制一张黑色图片 Cv2.Circle(irisTemp, eyeParams.Hm_col, eyeParams.Hm_row, (int)(eyeParams.Hm_radius * 0.9), new Scalar(255, 255, 255), -1); // 画白色一个实心圆 Cv2.Circle(irisTemp, circle_col, circle_row, circle_raduis, new Scalar(0, 0, 0), -1); // 画一个黑色实心圆 // 瞳孔像素范围(圆形) // 以虹膜-瞳孔边界半径为1,选中半径为0.8的圆形中所有未被遮挡的像素 Mat pupilTemp = new Mat(rows, cols, MatType.CV_8UC1, new Scalar(0, 0, 0)); // 复制一张黑色图片 Cv2.Circle(pupilTemp, eyeParams.Tk_col, eyeParams.Tk_row, (int)(eyeParams.Tk_radius * 0.8), new Scalar(255, 255, 255), -1); // 画白色一个实心圆 // 获取各个范围中的像素值(只取瞳孔边界以下的区域) for (int i = minRow; i <= maxRow; i++)//行循环 { byte* facedata = (byte*)FaceImage.Ptr(i).ToPointer(); //获取第i行的首地址 byte* scleradata = (byte*)scleraTemp.Ptr(i).ToPointer(); byte* irisdata = (byte*)irisTemp.Ptr(i).ToPointer(); byte* pupildata = (byte*)pupilTemp.Ptr(i).ToPointer(); for (int j = 0; j < cols; j++)//列循环 { if (255 == scleradata[j]) { scleradata[j] = 150; scleraList.Add(facedata[j]); } if (255 == irisdata[j]) { irisdata[j] = 150; irisList.Add(facedata[j]); } if (255 == pupildata[j]) { pupildata[j] = 150; pupilList.Add(facedata[j]); } } } // 排序,取像素中值 scleraList.Sort(); irisList.Sort(); pupilList.Sort(); byte sclear_value = (byte)scleraList[scleraList.Count / 2]; byte iris_value = (byte)irisList[irisList.Count / 2]; byte pupil_value = (byte)pupilList[pupilList.Count / 2]; // 取平均值 double constrast = 0.0; if (iris_value >= pupil_value) { constrast = System.Math.Abs(sclear_value - iris_value) * 100 / (sclear_value + iris_value - 2 * pupil_value); } //Console.WriteLine("iris_sclera_constrast: " + constrast + ", sclear_value:" + sclear_value + ", iris_value:" + iris_value + ", pupil_value:" + pupil_value); return constrast; } ////////////////////////////// ///*** 虹膜-瞳孔对比度 ***//// ////////////////////////////// unsafe double Iris_Pupil_Constrast(Mat FaceImage, EyeParams eyeParams) { ArrayList irisList = new ArrayList(); // 虹膜像素 ArrayList pupilList = new ArrayList(); // 瞳孔像素 int rows = FaceImage.Rows; int cols = FaceImage.Cols; int minRow = eyeParams.Tk_row - eyeParams.Tk_radius; int maxRow = eyeParams.Tk_row + eyeParams.Tk_radius; // 瞳孔像素范围(圆形) // 以虹膜-瞳孔边界半径为1,选中半径为0.8的圆形中所有未被遮挡的像素 Mat pupilTemp = new Mat(rows, cols, MatType.CV_8UC1, new Scalar(0, 0, 0)); // 复制一张黑色图片 Cv2.Circle(pupilTemp, eyeParams.Tk_col, eyeParams.Tk_row, (int)(eyeParams.Tk_radius * 0.8), new Scalar(255, 255, 255), -1); // 画白色一个实心圆 int circle_row; int circle_col; int circle_raduis; iris_pupil_circle(eyeParams, out circle_row, out circle_col, out circle_raduis); // 虹膜像素范围(环形) // 圆形内半径为1.1,外半径延伸至两个边界未被遮挡部分的中点 Mat irisTemp = new Mat(rows, cols, MatType.CV_8UC1, new Scalar(0, 0, 0)); // 复制一张黑色图片 Cv2.Circle(irisTemp, circle_col, circle_row, circle_raduis, new Scalar(255, 255, 255), -1); // 画白色一个实心圆 Cv2.Circle(irisTemp, eyeParams.Tk_col, eyeParams.Tk_row, (int)(eyeParams.Tk_radius * 1.1), new Scalar(0, 0, 0), -1); // 画黑色一个实心圆 // 获取各个范围中的像素值(只取瞳孔边界以下的区域) for (int i = minRow; i <= maxRow; i++)//行循环 { byte* facedata = (byte*)FaceImage.Ptr(i).ToPointer(); //获取第i行的首地址 byte* irisdata = (byte*)irisTemp.Ptr(i).ToPointer(); byte* pupildata = (byte*)pupilTemp.Ptr(i).ToPointer(); for (int j = 0; j < cols; j++)//列循环 { if (255 == irisdata[j]) { irisdata[j] = 150; irisList.Add(facedata[j]); } if (255 == pupildata[j]) { pupildata[j] = 150; pupilList.Add(facedata[j]); } } } // 排序,取像素中值 irisList.Sort(); pupilList.Sort(); byte iris_value = (byte)irisList[irisList.Count / 2]; byte pupil_value = (byte)pupilList[pupilList.Count / 2]; // 取平均值 double weber_ratio = (double)System.Math.Abs(iris_value - pupil_value) / (20 + pupil_value); double constrast = weber_ratio * 100 / (0.75 + weber_ratio); //Console.WriteLine("iris_sclera_constrast: " + constrast + ", iris_value:" + iris_value + ", pupil_value:" + pupil_value); return constrast; // return 0.0; } // 计算两点之间距离 public double Distance(int x1, int y1, int x2, int y2) { return System.Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); } // 以虹膜-巩膜,虹膜-瞳孔之间间距的中点,绘制圆,计算圆的圆心和半径 public void iris_pupil_circle(EyeParams eyeParams, out int circle_row, out int circle_col, out int circle_raduis) { double distance = Distance(eyeParams.Hm_row, eyeParams.Hm_col, eyeParams.Tk_row, eyeParams.Tk_col); if (distance == 0) { circle_row = eyeParams.Hm_row; circle_col = eyeParams.Hm_col; circle_raduis = (int)((eyeParams.Hm_radius + eyeParams.Tk_radius) * 0.5); } else { int middle1_row; int middle1_col; int middle2_row; int middle2_col; if (eyeParams.Hm_row == eyeParams.Tk_row) { middle1_row = eyeParams.Tk_row; middle2_row = eyeParams.Tk_row; middle1_col = ((eyeParams.Hm_col + eyeParams.Hm_radius) + (eyeParams.Tk_col + eyeParams.Tk_radius)) / 2; middle2_col = ((eyeParams.Hm_col - eyeParams.Hm_radius) + (eyeParams.Tk_col - eyeParams.Tk_radius)) / 2; } else if (eyeParams.Hm_col == eyeParams.Tk_col) { middle1_col = eyeParams.Tk_col; middle2_col = eyeParams.Tk_col; middle1_row = ((eyeParams.Hm_row + eyeParams.Hm_radius) + (eyeParams.Tk_row + eyeParams.Tk_radius)) / 2; middle2_row = ((eyeParams.Hm_row - eyeParams.Hm_radius) + (eyeParams.Tk_row - eyeParams.Tk_radius)) / 2; } else { middle1_row = (int)(eyeParams.Hm_row + (eyeParams.Hm_radius + eyeParams.Tk_radius + distance) * (eyeParams.Tk_row - eyeParams.Hm_row) / (2 * distance)); middle1_col = (int)(eyeParams.Hm_col + (eyeParams.Hm_radius + eyeParams.Tk_radius + distance) * (eyeParams.Tk_col - eyeParams.Hm_col) / (2 * distance)); middle2_row = (int)(eyeParams.Hm_row - (eyeParams.Hm_radius - eyeParams.Tk_radius + distance) * (eyeParams.Tk_row - eyeParams.Hm_row) / (2 * distance)); middle2_col = (int)(eyeParams.Hm_col - (eyeParams.Hm_radius - eyeParams.Tk_radius + distance) * (eyeParams.Tk_col - eyeParams.Hm_col) / (2 * distance)); } circle_row = (middle1_row + middle2_row) / 2; circle_col = (middle1_col + middle2_col) / 2; circle_raduis = (int)Distance(circle_row, circle_col, middle1_row, middle1_col); } } public int average(ArrayList list) { if (list.Count == 0) { return 0; } int sum = 0; foreach (byte item in list) { sum += item; } return sum / list.Count; } //////////////////////////////////// ///*** 图像清晰度(拉普拉斯) ***/// //////////////////////////////////// public double Sharpness(Mat img) { Mat imageSobel = new Mat(); Cv2.Laplacian(img, imageSobel, MatType.CV_8UC1); double meanValue = Cv2.Mean(imageSobel)[0]; //Console.WriteLine("Laplacian mean" + meanValue); return meanValue; } public double SharpnessArea(Mat img, EyeParams eyeParams) { int x = eyeParams.Hm_col - eyeParams.Hm_radius; int y = eyeParams.Hm_row - eyeParams.Hm_radius; if (x < 0) x = 0; if (y < 0) y = 0; Mat imgArea = img.Clone(new Rect(x, y, eyeParams.Hm_radius * 2, eyeParams.Hm_radius * 2)); Mat imageSobel = new Mat(); Cv2.Laplacian(imgArea, imageSobel, MatType.CV_8UC1); Mat meanValueImage = new Mat(); Mat meanStdValueImage = new Mat(); Cv2.MeanStdDev(imageSobel, meanValueImage, meanStdValueImage); double meanValue = meanStdValueImage.At<double>(0, 0); //Console.WriteLine("Std mean" + meanValue); return meanValue; } ///////////////////////////// ///*** 虹膜质量评分 ***////// ///////////////////////////// public double Assess_Score(double sharpness, int Hm_raduis, double usable_iris_area, double iris_sclera_constrast, double iris_pupil_constrast) { int high = 10; int sharpness_score = 0; if (sharpness < 7) { sharpness_score = 0; } else if (sharpness >= 7 && sharpness <= high) { sharpness_score = (int)(sharpness * 100 / (high - 7) - 700 / (high - 7)); } else { sharpness_score = 100; } Console.WriteLine("sharpness: " + sharpness + ", score: " + sharpness_score); // 虹膜半径不小于 100像素(100像素:60分,往上每一像素增加一分,大于140像素100分) int Hm_raduis_socre = 0; if (Hm_raduis < 100) { Hm_raduis_socre = 0; } else if (Hm_raduis <= 140) { Hm_raduis_socre = Hm_raduis - 100 + 60; } else { Hm_raduis_socre = 100; } Console.WriteLine("raduis: " + Hm_raduis + ", score: " + Hm_raduis_socre); // 虹膜有效区域占比大于 60%(按比例取分数) double usable_iris_area_score = 0; if (usable_iris_area < 0.6) { usable_iris_area_score = 0; } else { usable_iris_area_score = usable_iris_area * 100; } Console.WriteLine("area: " + usable_iris_area + ", score: " + usable_iris_area_score); // 虹膜与巩膜对比度不小于 10(>30满分,10-30内按比例取分,满分50分) double iris_sclera_constrast_score = 0; if (iris_sclera_constrast < 10) { iris_sclera_constrast_score = 0; } else if (iris_sclera_constrast >= 10 && iris_sclera_constrast <= 30) { iris_sclera_constrast_score = (iris_sclera_constrast - 10) * 2.5; } else { iris_sclera_constrast_score = 50; } Console.WriteLine("iris_sclera_constrast: " + iris_sclera_constrast + ", score: " + iris_sclera_constrast_score); // 虹膜与瞳孔对比度不小于 30(>50满分,30-50内按比例取分,满分50分) double iris_pupil_constrast_score = 0; if (iris_pupil_constrast < 30) { iris_pupil_constrast_score = 0; } else if (iris_pupil_constrast >= 30 && iris_pupil_constrast <= 80) { iris_pupil_constrast_score = (iris_pupil_constrast - 30) * 1; } else { iris_pupil_constrast_score = 50; } Console.WriteLine("iris_pupil_constrast: " + iris_pupil_constrast + ", score: " + iris_pupil_constrast_score); if (iris_pupil_constrast_score == 0 || iris_sclera_constrast_score == 0) return 0; double assess_score = sharpness_score * sharpnessWeight + Hm_raduis_socre * radiusWeight + usable_iris_area_score * areaWeight + (iris_pupil_constrast_score + iris_sclera_constrast_score) * constrastWeight; Console.WriteLine("assecc_score: " + assess_score); Console.WriteLine("========================================"); return assess_score; } } }