Hough circle doesn't detect eyes iris
Asked Answered
S

3

6

I want to detect eyes irises and their centers using Hough Circle algorithm.

I'm using this code:

 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" );

    }

But it doesn't detect iris in all images correctly. Specially, if the iris has a dark color like brown. How can I fix this code to detect the irises and their centers correctly?

EDIT: Here are some sample images (which I got from the web) that shows the performance of the algorithm (Please ignore the landmarks which are represented by the red squares):

In these images the algorithm doesn't detect all irises:

enter image description here

enter image description here

This image shows how the algorithm couldn't detect irises at all:

enter image description here

EDIT 2: Here is a code which uses Canny edge detection, but it causes the app to crash:

 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" );

    }

This is the error I get in the log

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)

Which is caused by this line: Imgproc.cvtColor(originalBitmap,grayMat,Imgproc.COLOR_BGR2GRAY);

Can anyone please tell me how this error can solved? Perhaps adding a canny edge detection will improve the results.

Selective answered 9/2, 2016 at 8:50 Comment(10)
You should at least share some images.Internee
@Internee thank you, please check the question I've updated it.Selective
Are these just snapshots? Because the irises don't match your maxRadius parameter? I am confused that you found anything with a max radius of 10.Degeneration
@Degeneration thanks, sorry, but I didn't understand your question regarding the images whether they are actual or snapshots, can you please elaborate more? I inputted these images to the app and it gave me the results in the question. The 1st and 3rd ones I inputted directly in the app, but the second one is captured from the front camera of the device. Do you mean that maxRadius should be 10? It's set to 10 in the code, what value is appropriate to my case?Selective
Your error comes from the fact that input to cvtColor is already single channel (CV_8UC1).Gerstein
@Gerstein I think it comes from the fact that originalBitmap is empty, I fixed it by giving it the value of the obtained bitmap, but still no irirs is detected. How to solve the single channel problem?Selective
I think you must call Utils.bitmapToMat not sure though what it really is. But if the topmost code snippet works, just call Canny there for the grayMatGerstein
Thanks, I changed the way of defining the gray mat, and I used it in canny, but still the app crashes, before it does it outputs some lines related to creating threads and some times it writes thread died, I'm running it on a background thread, does that matter? Is there a sample code that I can try as those in the question are not working properly?Selective
I cannot really write java, but a self-contained program would be best for debugging the hough/canny part. You can use Highgui.imread and imwrite for I/O.Gerstein
@Gerstein Ok, I'll try that, thanks.Selective
G
2

As you want to detect iris using hough transform (there are others), you had better studying the Canny edge detector and its parameters. cv::HoughCircles takes the Canny-hysteresis threshold in param1. Investigating Canny alone, you get the impression of good threshold range.

Maybe instead of gaussian blur, you apply a better denoising (non local means with say h=32 and window sizes 5 and 15), and also try to harmonize the image contrast, e.g., using contrast limited adaptive histogram equalization (cv::CLAHE).

Harmonization is to make sure all (highlight and shadow) eyes map to similar intensity range.

Gerstein answered 9/2, 2016 at 17:12 Comment(2)
Thanks, I tried to read a bit about canny, and even I've tried a code that uses it, but the app immediately crashes with no error message in the log when I use a code that contains canny. I've tried medianBlur, but it didn't solve the problem. What is harmonizing contrasts? And, how may it help? Can you please elaborate more? Thanks.Selective
I could find the exception that causes the app to crash, but I don't know how to solve it. I updated the question, please check it. Thanks.Selective
M
2

Hough circles work better on well defined circles. They are not good with things like iris.

After some thresholding, morphological operations or canny edge detection, feature detection methods like MSER work much better for iris detection.

Here is a similar question with a solution if you are looking for some code.

Modulus answered 17/3, 2016 at 23:1 Comment(0)
D
1

I wanted to know if those images are the images you processed or if you like took a cell phone snapshot of your screen to upload them here. Because the irises are bigger than the maximum radius you set in your code. Therefor I don't understand how you could find any iris at all. The irises in the first image have a radius of over 20. So you shouldn't be able to detect them. You should set the radii to the radius range you expect your irises to be.

Degeneration answered 9/2, 2016 at 17:13 Comment(2)
Yes, The 1st and 3rd ones are snapshots as my app layout was set to output the input image with the detected irises. The second one is an image the app stored in my mobile gallery after it has processed the input image from the front camera. Sorry I think I've posted a modified version of the code with respect to the radius as I was trying to change it. I think it was 1000. What is the usual value of an iris radius? I've tried things like 100, but it didn't work too. Thanks.Selective
I updated the question, where I added a code that uses canny detection also, can you please check it, it's giving me an exception.Selective

© 2022 - 2024 — McMap. All rights reserved.