Emgu CV 中基于眼部位置进行人脸对齐






4.80/5 (3投票s)
人脸对齐旋转以提高人脸识别率
引言
人脸识别是图像处理中的一项重要任务。但由于人脸姿势各异,例如向左或向右旋转,人脸识别的准确率会降低。因此,旋转人脸并使其正面朝向以获得更好的人脸识别效果至关重要。
背景
我搜索了大量网站以进行人脸识别和人脸旋转。我找到了一些代码和提示,但它们对我来说根本不起作用。因此,在实施了一些我的想法后,我编写了这段代码,根据眼部位置进行人脸对齐。它对我来说准确率超过 97%。
Using the Code
首先,使用haar级联检测器检测左右眼。
HaarCascade haar_righteye = new HaarCascade(path + "haarcascade_mcs_righteye.xml"); HaarCascade haar_lefteye = new HaarCascade(path + "haarcascade_mcs_lefteye.xml"); //following variables are used to detect right eye and //left eye for fixing position and hence used for face alignment MCvAvgComp[][] Right_Eye = upper_face.DetectHaarCascade(haar_righteye, 1.4, 4, Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.DO_CANNY_PRUNING, new Size(4, 4)); MCvAvgComp[][] Left_Eye = upper_face.DetectHaarCascade(haar_lefteye, 1.4, 4, Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.DO_CANNY_PRUNING, new Size(4, 4));
这里,upper_face
是人脸从鼻子中部开始的上半部分。简单来说,我将检测到的人脸图像取一个子矩形,高度设置为原始图像的一半。
int height = Face.Height / 2; Rectangle rect = new Rectangle(0, 0, Face.Width, height); Image<Gray, byte> upper_face = Face.GetSubRect(rect);
我将根据眼部位置(X 值)在图像中找到左眼和右眼。所述haar级联检测器并不总是直接给出左眼和右眼。因此,检查它们非常重要。
为了实际旋转人脸,我将根据眼部位置找到角度。然后,使用此角度与 180 度的计算,找到旋转人脸图像的最终角度。
var deltaY = (L_eye.rect.Y + L_eye.rect.Height / 2) - (R_eye.rect.Y + R_eye.rect.Height / 2); //using horizontal position and width attribute find out the variable deltaX var deltaX = (L_eye.rect.X + L_eye.rect.Width / 2) - (R_eye.rect.X + R_eye.rect.Width / 2); double degrees = (Math.Atan2(deltaY, deltaX) * 180) / Math.PI;//find out the angle //as per position of eyes degrees = 180 - degrees; Face = Face.Rotate(degrees, new Gray(220),true);
请在下面找到完整的代码
public Image<Gray, byte> AlignFace(Image<Gray, byte> Face) { try { int height = Face.Height / 2; Rectangle rect = new Rectangle(0, 0, Face.Width, height); Image<Gray, byte> upper_face = Face.GetSubRect(rect); //following variables are used to detect right eye and //left eye for fixing position and hence used for face alignment MCvAvgComp[][] Right_Eye = upper_face.DetectHaarCascade (haar_righteye, 1.4, 4, Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.DO_CANNY_PRUNING, new Size(4, 4)); MCvAvgComp[][] Left_Eye = upper_face.DetectHaarCascade (haar_lefteye, 1.4, 4, Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.DO_CANNY_PRUNING, new Size(4, 4)); bool FLAG = false; foreach (MCvAvgComp R_eye in Right_Eye[0]) { foreach (MCvAvgComp L_eye in Left_Eye[0]) { if (R_eye.rect.X > (L_eye.rect.X+L_eye.rect.Width)) { //upper_face.Draw(R_eye.rect, new Gray(200), 2); //upper_face.Draw(L_eye.rect, new Gray(200), 2); var deltaY = (L_eye.rect.Y + L_eye.rect.Height / 2) - (R_eye.rect.Y + R_eye.rect.Height / 2); //using horizontal position and width attribute find out the variable deltaX var deltaX = (L_eye.rect.X + L_eye.rect.Width / 2) - (R_eye.rect.X + R_eye.rect.Width / 2); double degrees = (Math.Atan2(deltaY, deltaX) * 180) / Math.PI;//find out //the angle as per position of eyes degrees = 180 - degrees; Face = Face.Rotate(degrees, new Gray(220),true); FLAG = true; break; } } if(FLAG==true) { break; } } } catch (Exception d) { op += " Align Error: " + d.Message; } res = op; return Face; }
关注点
计算的度数的计算包含 180 度的角度,因此代码行...
degrees = 180 - degrees;
...是这段代码中一个有趣的方面。因为通过添加这一行代码,准确率得到了提高。
我为什么要添加这个呢?
请找出....