本文和下文介绍如何对一个虹膜图像进行分割提取出虹膜,在虹膜分割中,最重要的是检测两个圆,一个内圆,一个是外圆。下面是两个圆的示意图。
本文先讲解如何检测内圆,在我的方法中,内圆的检测可分为四步:
1. 用Canny边缘检测和Hough变换从经过高斯平滑处理后的图片中检测圆。在此步操作,我故意把Hough变换的阈值设得比较小,这样我们就可以检测出很多圆了。下图就是用cvHoughCircle检测出的圆。
可以看到,在此步中,我们检测到了圆,但是有很多圆,我们现在要想办法找到我们要的那个内圆。下面的步骤就是我找内圆的方法。
2. 把原图二值化,这个可以通过cvThreshold很容易实现,阈值设在五十左右就可以了。阈值化后的图像如下:
这个二值化后得到的图像是为了后面计算每个圆中包含的瞳孔点比率做准备的。
3. 计算第一步中得到的每个圆的一个比率,计算是根据第二步中二值图像进行。比率的定义如下
PupilInclusion Rate = Number of black points / Area of circle
即:用每一个circle中包含的黑点的个数除以圆的面积
4. 在计算出每一个圆的比率后,找到比率最大的那个,并把那个作为最后的内圆,这样就可以完美得检测出内圆了。
opencv代码如下:
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat srcImage=imread("C://1.bmp");
Mat midImage,dstImage,edge;
imshow("原始图",srcImage);
threshold(srcImage, srcImage, 30, 200.0, CV_THRESH_BINARY);//二值化
int cn=0;//cn是圆的个数
int radius=0;
float ratio = 0;
float maxratio = 0;
float result[3];
cvtColor(srcImage,midImage,COLOR_BGR2GRAY);
blur(midImage,edge,Size(3,3));
Canny(edge,edge,3,9,3);
GaussianBlur(midImage,midImage,Size(9,9),2,2);
vector<Vec3f> circles;
HoughCircles(midImage,circles,CV_HOUGH_GRADIENT,2,10,200,80,0,0);
for(cn=0;cn<circles.size();cn++)
{
Point center(cvRound(circles[cn][0]),cvRound(circles[cn][1]));
radius=cvRound(circles[cn][2]);
// circle(srcImage,center,3,Scalar(0,255,0),-1,8,0);
// circle(srcImage,center,radius,Scalar(155,50,255),3,8,0);
//////////////////////////////
int width = srcImage.cols;
int height = srcImage.rows;
int value; //pixel value
int count = 0;
for(int i=0;i<height;i++)
{
for(int j=0;j<width;j++)
{
if (sqrt(pow(float(center.x-j),2)+pow(float(center.y-i),2))< radius)
{
//获得某点的像素值
value = srcImage.at<Vec3b>(i,j)[2]; //cvGetReal2D(img,i,j);
if(value == 0)
count++;
}
}
ratio = float(count)/(3.14*radius*radius);
if (ratio >= maxratio)
{
result[0] = circles[cn][0];
result[1] = circles[cn][1];
result[2] = radius;
maxratio = ratio;
}
}
printf("黑色点像素的个数:%d\n",count);
printf("瞳孔重合比率:%f\n",ratio);
Point center1(cvRound(result[0]),cvRound(result[1]));
circle(srcImage,center1,3,Scalar(0,255,0),-1,8,0);
circle(srcImage,center1,result[2],Scalar(155,50,255),3,8,0);
}
if(cn==0)
{
printf("No Circle Detected!!Please Check!!\n");
system("pause");
}
imshow("效果图",srcImage);
waitKey(0);
return 0;
}
一定要注意这段代码是在循环里面的:
if (ratio >= maxratio)
{
result[0] = circles[cn][0];
result[1] = circles[cn][1];
result[2] = radius;
maxratio = ratio;
}
而且result[0]=cricles[cn][0];
最后的运行结果如下所示:
这样就把所有可能的霍夫圆的重合的最大比率的圆画出来了,输出统计到黑色像素点的总个数。