霍夫圆没有检测到眼睛虹膜

Posted

技术标签:

【中文标题】霍夫圆没有检测到眼睛虹膜【英文标题】:Hough circle doesn't detect eyes iris 【发布时间】:2016-05-19 04:06:15 【问题描述】:

我想使用Hough Circle 算法检测眼睛虹膜及其中心。

我正在使用此代码:

 private void houghCircle()
    
        Bitmap obtainedBitmap = imagesList.getFirst();
                 /* convert bitmap to mat */
        Mat mat = new Mat(obtainedBitmap.getWidth(),obtainedBitmap.getHeight(),
                CvType.CV_8UC1);
        Mat grayMat = new Mat(obtainedBitmap.getWidth(), obtainedBitmap.getHeight(),
                CvType.CV_8UC1);


        Utils.bitmapToMat(obtainedBitmap, mat);

/* convert to grayscale */
        int colorChannels = (mat.channels() == 3) ? Imgproc.COLOR_BGR2GRAY : ((mat.channels() == 4) ? Imgproc.COLOR_BGRA2GRAY : 1);

        Imgproc.cvtColor(mat, grayMat, colorChannels);

/* reduce the noise so we avoid false circle detection */
        Imgproc.GaussianBlur(grayMat, grayMat, new Size(9, 9), 2, 2);

// accumulator value
        double dp = 1.2d;
// minimum distance between the center coordinates of detected circles in pixels
        double minDist = 100;

// min and max radii (set these values as you desire)
        int minRadius = 0, maxRadius = 1000;

// param1 = gradient value used to handle edge detection
// param2 = Accumulator threshold value for the
// cv2.CV_HOUGH_GRADIENT method.
// The smaller the threshold is, the more circles will be
// detected (including false circles).
// The larger the threshold is, the more circles will
// potentially be returned.
        double param1 = 70, param2 = 72;

/* create a Mat object to store the circles detected */
        Mat circles = new Mat(obtainedBitmap.getWidth(), obtainedBitmap.getHeight(), CvType.CV_8UC1);

/* find the circle in the image */
        Imgproc.HoughCircles(grayMat, circles, Imgproc.CV_HOUGH_GRADIENT, dp, minDist, param1, param2, minRadius, maxRadius);

/* get the number of circles detected */
        int numberOfCircles = (circles.rows() == 0) ? 0 : circles.cols();

/* draw the circles found on the image */
        for (int i=0; i<numberOfCircles; i++) 


/* get the circle details, circleCoordinates[0, 1, 2] = (x,y,r)
 * (x,y) are the coordinates of the circle's center
 */
            double[] circleCoordinates = circles.get(0, i);


            int x = (int) circleCoordinates[0], y = (int) circleCoordinates[1];

            Point center = new Point(x, y);

            int radius = (int) circleCoordinates[2];

    /* circle's outline */
            Core.circle(mat, center, radius, new Scalar(0,
                    255, 0), 4);

    /* circle's center outline */
            Core.rectangle(mat, new Point(x - 5, y - 5),
                    new Point(x + 5, y + 5),
                    new Scalar(0, 128, 255), -1);
        

/* convert back to bitmap */
        Utils.matToBitmap(mat, obtainedBitmap);
        MediaStore.Images.Media.insertImage(getContentResolver(),obtainedBitmap, "testgray", "gray" );

    

但它不能正确检测所有图像中的虹膜。特别是,如果虹膜有棕色等深色。如何修复此代码以正确检测虹膜及其中心?

编辑:这里有一些示例图像(我从网络上获得)显示了算法的性能(请忽略由红色方块表示的地标):

在这些图像中,算法并未检测到所有虹膜:

这张图片显示了算法是如何无法检测到虹膜的:

编辑 2:这是一个使用 Canny 边缘检测的代码,但它会导致应用程序崩溃:

 private void houghCircle()
    
        Mat grayMat = new Mat();
        Mat cannyEdges = new Mat();
        Mat circles = new Mat();
        Bitmap obtainedBitmap = imagesList.getFirst();
         /* convert bitmap to mat */
        Mat originalBitmap = new Mat(obtainedBitmap.getWidth(),obtainedBitmap.getHeight(),
                CvType.CV_8UC1);
//Converting the image to grayscale
        Imgproc.cvtColor(originalBitmap,grayMat,Imgproc.COLOR_BGR2GRAY);
        Imgproc.Canny(grayMat, cannyEdges,10, 100);
        Imgproc.HoughCircles(cannyEdges, circles,
                Imgproc.CV_HOUGH_GRADIENT,1, cannyEdges.rows() / 15); //now circles is filled with detected circles.

//, grayMat.rows() / 8);
        Mat houghCircles = new Mat();
        houghCircles.create(cannyEdges.rows(),cannyEdges.cols()
                ,CvType.CV_8UC1);
//Drawing lines on the image
        for(int i = 0 ; i < circles.cols() ; i++)
        
            double[] parameters = circles.get(0,i);
            double x, y;
            int r;
            x = parameters[0];
            y = parameters[1];
            r = (int)parameters[2];
            Point center = new Point(x, y);
//Drawing circles on an image
            Core.circle(houghCircles,center,r,
                    new Scalar(255,0,0),1);
        
//Converting Mat back to Bitmap
        Utils.matToBitmap(houghCircles, obtainedBitmap);
        MediaStore.Images.Media.insertImage(getContentResolver(),obtainedBitmap, "testgray", "gray" );

    

这是我在日志中得到的错误

FATAL EXCEPTION: Thread-28685
    CvException [org.opencv.core.CvException: cv::Exception: /hdd2/buildbot/slaves/slave_ardbeg1/50-SDK/opencv/modules/imgproc/src/color.cpp:3739: error: (-215) scn == 3 || scn == 4 in function void cv::cvtColor(cv::InputArray, cv::OutputArray, int, int)
    ]
            at org.opencv.imgproc.Imgproc.cvtColor_1(Native Method)
            at org.opencv.imgproc.Imgproc.cvtColor(Imgproc.java:4598)

这是由这一行引起的:Imgproc.cvtColor(originalBitmap,grayMat,Imgproc.COLOR_BGR2GRAY);

谁能告诉我如何解决这个错误?也许添加精明的边缘检测会改善结果。

【问题讨论】:

你至少应该分享一些图片。 @guneykayim 谢谢,请检查我更新的问题。 这些只是快照吗?因为虹膜与您的 maxRadius 参数不匹配?我很困惑你发现了最大半径为 10 的任何东西。 @Piglet 谢谢,对不起,但我不明白你关于图像是真实的还是快照的问题,你能详细说明一下吗?我将这些图像输入到应用程序中,它给了我问题中的结果。第一个和第三个我直接在应用程序中输入,但第二个是从设备的前置摄像头捕获的。你的意思是maxRadius应该是10?在代码中设置为10,我的情况适合什么值? 您的错误来自cvtColor 的输入已经是单通道(CV_8UC1)。 【参考方案1】:

霍夫圆在定义明确的圆上效果更好。他们不擅长虹膜之类的东西。

经过一些阈值化、形态学运算或精巧的边缘检测后,像 MSER 这样的特征检测方法在虹膜检测方面效果更好。

Here 是一个类似的问题,如果您正在寻找一些代码,请提供解决方案。

【讨论】:

【参考方案2】:

由于您想使用霍夫变换检测虹膜(还有其他方法),您最好学习 Canny 边缘检测器及其参数。 cv::HoughCircles 采用 param1 中的 Canny 滞后阈值。单独调查Canny,您会得到良好阈值范围的印象。

也许您可以应用更好的去噪代替高斯模糊(例如h=32 和窗口大小为 5 和 15 的非本地方法),并尝试协调图像对比度,例如,使用对比度受限的自适应直方图均衡化 (@ 987654325@)。

协调是为了确保所有(高光和阴影)眼睛映射到相似的强度范围。

【讨论】:

谢谢,我尝试阅读一些关于 canny 的内容,甚至我尝试过使用它的代码,但是当我使用包含精明。我已经尝试过 medianBlur,但它并没有解决问题。什么是协调对比?而且,它有什么帮助?你能详细说明一下吗?谢谢。 我可以找到导致应用程序崩溃的异常,但我不知道如何解决它。我更新了问题,请检查。谢谢。【参考方案3】:

我想知道这些图片是否是您处理过的图片,或者您是否喜欢将手机屏幕快照上传到此处。因为虹膜大于您在代码中设置的最大半径。因此,我根本不明白你怎么能找到任何虹膜。第一张图像中的虹膜半径超过 20。所以你应该无法检测到它们。 您应该将半径设置为您期望虹膜的半径范围。

【讨论】:

是的,第一个和第三个是快照,因为我的应用布局设置为输出带有检测到的虹膜的输入图像。第二个是应用程序在处理来自前置摄像头的输入图像后存储在我的移动图库中的图像。抱歉,我想我已经发布了关于半径的代码的修改版本,因为我试图改变它。我认为是 1000。虹膜半径的通常值是多少?我已经尝试过 100 之类的东西,但它也没有奏效。谢谢。 我更新了问题,我在其中添加了一个使用精明检测的代码,你能检查一下吗,它给了我一个例外。

以上是关于霍夫圆没有检测到眼睛虹膜的主要内容,如果未能解决你的问题,请参考以下文章

程序人生 - 猫咪瞳孔的颜色

霍夫圆检测 opencv

Python Opencv使用霍夫圆变换从二进制图像中检测圆

CV 霍夫圆参数检测圆

使用 dlib 检测眼睛地标

图像检测基于Hough变换的人眼虹膜定位matlab源码