4

目标:我正在尝试使用视频作为输入来获取虹膜的大小(宽度/半径)。

我尝试过 HoughCircles,但它似乎并不精确,因为虹膜圈似乎不太准确。我已经掌握的信息是眼睛瞳孔的中心点及其半径。

灰度眼

有人建议我找到虹膜边缘以尝试从瞳孔中心向外测量梯度幅度。然后使用直方图使用梯度最大值的累积来找到虹膜宽度。从特定点开始,我不确定以哪种方式实现这一点。

我在眼睛 ROI 上使用了 Sobel 算子来尝试获得梯度,输出如下所示。

索贝尔眼

索贝尔图像代码:

void irisFind(Mat gradMat, Point2i pupCenter, int pupRad){

imshow("original", gradMat);


Mat gradX;
Mat gradY;
Mat absGradX;
Mat absGradY;

GaussianBlur(gradMat, gradMat, Size(3, 3), 0, 0, BORDER_DEFAULT);
equalizeHist(gradMat, gradMat);

//Generate Gradient along x
Sobel(gradMat, gradX, CV_16S, 1, 0, 3, 1, 0, BORDER_DEFAULT);
convertScaleAbs(gradX, absGradX);

//Generate Gradient along y
Sobel(gradMat, gradY, CV_16S, 0, 1, 3, 1, 0, BORDER_DEFAULT);
convertScaleAbs(gradY, absGradY);

addWeighted(absGradX, .5, absGradY, .5, 0, gradMat);

imshow("Sobel", gradMat);
}

我不完全确定下一步如何进行。任何建议或意见表示赞赏。如果我错过了任何信息或者我对某事含糊不清,请告诉我。非常感谢提前!

编辑:我应该更好地解释我的应用程序的上下文,所以我为此道歉。我正在测量来自视频输入的帧上眼睛的瞳孔扩张。我已经知道瞳孔中心点的位置和瞳孔的半径。我试图找到虹膜的大小,以便可以使用从眼睛到相机的距离的变化来补偿对瞳孔大小的误解值,因为如果眼睛变得更靠近相机,瞳孔当然会出现更大而不膨胀。我也可能会尝试其他方法来解决这个问题,例如眼角,但我认为既然我已经有几个瞳孔特征,我将从虹膜开始。

再次,很抱歉之前遗漏了这个细节。谢谢!

4

2 回答 2

2

我认为您应该使用虹膜内部有黑色圆圈的事实。

这是对您的图像进行简单的黑色分割后得到的结果:

分割图像

而且看起来真正的虹膜比这个黑色圆圈大 3 到 4 倍。所以,结果如下:

结果图片

寻找源代码?就是这个:

int main()
{
    Mat src = imread("input.jpg", CV_LOAD_IMAGE_GRAYSCALE), tmp;

    imshow("Source", src);

    double minVal = 0;
    minMaxLoc(src, &minVal, NULL, NULL, NULL);

    threshold(src, tmp, minVal + 10, 255, THRESH_BINARY_INV);

    //(Optional) remove noise (small areas of white pixels)
/*
    Mat element = getStructuringElement(MORPH_ELLIPSE, Size(3, 3), Point(1, 1));
    erode(tmp, tmp, element);
    dilate(tmp, tmp, element);
*/
    vector<Vec4i> hierarchy;
    vector<vector<Point2i> > contours;
    findContours(tmp, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

    //find contour with max area
    int maxArea = 0;
    Rect maxContourRect;
    for (int i=0; i<contours.size(); i++)
    {
        int area = contourArea(contours[i]);
        Rect rect = boundingRect(contours[i]);
        double squareKoef = ((double) rect.width)/rect.height;

        //check if contour is like square (shape)
#define SQUARE_KOEF 1.5
        if (area>maxArea && squareKoef < SQUARE_KOEF && squareKoef > 1.0/SQUARE_KOEF)
        {
            maxArea = area;
            maxContourRect = rect;
        }
    }

    if (maxArea == 0)
    {
        std::cout << "Iris not found!" << std::endl;
    }
    else
    {
        Rect drawRect = Rect(maxContourRect.x-maxContourRect.width, maxContourRect.y-maxContourRect.height, maxContourRect.width*3, maxContourRect.height*3);

        rectangle(src, drawRect, Scalar(0), 1);

        imshow("Dest", src);
        waitKey();
    }
}
于 2012-10-11T17:28:08.070 回答
2

澄清您在问题中谈到的建议:

“有人建议我找到虹膜边缘以尝试从瞳孔中心向外测量梯度幅度。然后使用使用梯度最大值累积的直方图来找到虹膜宽度。我不太确定以何种方式来实现这一点,从一个特定的点开始。”

你可以具体做的是从你的瞳孔中心开始,并执行一个区域增长算法,其中你的停止条件,而不是蜜蜂,比如说,一个太不同的灰度值,是你梯度幅度的阈值。一些伪代码:

initalize list of points with center of your pupil
initialize a mask image to zero
while list of point is not empty
   point pt = pop()
   set maskImage at pt to 255
   for  pt2 in pt neighbourhood
       if (gradientMagnitude at pt2 < THRESHOLD and maskImage at pt2 == 0)
          list of points.add (pt2)
于 2012-10-12T08:41:22.107 回答