Search code examples
androidopencvface-detectioneye-detection

Pupil detection project with OpenCV & Android-Studio gets ArrayIndexOutOfBoundsException


I have to do a project for Android-studio and one of the objectives is detecting the pupils of a person. I'm trying to use OpenCV. I know there are many issues about the detection of circles or eyes in this site with OpenCV, but every time I try to execute my code, the app crashes for a particular error that nobody reports, which is:

2021-03-30 21:44:08.178 19272-19500/com.android.unipi.camerawifiprova E/AndroidRuntime: FATAL EXCEPTION: Thread-7
    Process: com.android.unipi.camerawifiprova, PID: 19272
    java.lang.ArrayIndexOutOfBoundsException: length=1; index=1

I share my code in the methods onCameraViewStarted() and onCameraFrame().

@Override
public void onCameraViewStarted(int width, int height) {
    dst = new Mat();
    matGray = new Mat();
    circles = new Mat();
}

@Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
    mRgba = inputFrame.rgba();
    Core.transpose(mRgba,mRgbaT);
    Core.flip(mRgbaT, dst,1);
    Imgproc.resize(mRgbaT,mRgbaT, mRgba.size());
    mRgba.release();
    mRgbaT.release();

    Bitmap resultBitmap;
    resultBitmap = Bitmap.createBitmap(dst.cols(), dst.rows(), Bitmap.Config.ARGB_8888);
    Utils.matToBitmap(dst, resultBitmap);

    matGray = new Mat(resultBitmap.getWidth(), resultBitmap.getHeight(), CvType.CV_8UC1);
    Utils.bitmapToMat(resultBitmap, matGray);
    int colorChannels = (matGray.channels() == 3) ? Imgproc.COLOR_BGR2GRAY
            : ((matGray.channels() == 4) ? Imgproc.COLOR_BGRA2GRAY : 1);
    Imgproc.cvtColor(matGray, matGray, colorChannels);

    circles = new Mat(resultBitmap.getWidth(), resultBitmap.getHeight(), CvType.CV_8UC1);
    Imgproc.GaussianBlur(matGray, matGray, new Size(9,9),2,2);
    double dp = 1d; 
    double minDist = 20; 
    int minRadius = 0, maxRadius = 0; 
    double param1 = 105; 
    double param2 = 40;
    Imgproc.HoughCircles(matGray, circles, Imgproc.CV_HOUGH_GRADIENT, dp, minDist,
                        param1, param2, minRadius, maxRadius);

    int numCircles = (circles.rows() == 0) ? 0 : circles.cols();
    for (int i = 0; i < numCircles; i++) {
        double[] circlePar = circles.get(0,i);
        int x = (int) circlePar[0], y = (int) circlePar[1]; // -> ArrayIndexOutOfBoundsException!!
        Point center = new Point(x,y);
        int radius = (int) circlePar[2];
        Imgproc.circle(dst,center,radius,new Scalar(0,0,255),4);
    }

    matGray.release();
    circles.release();

    return dst;

}

I print the variable circlePar: it should have three values (center coordinates and radius) instead I got only one [0.0]. Maybe the program cannot detect any circles. I try an easy task (detect one single coin on a desk), but the app still crashes for the above reason.


Solution

  • After some time, I figured it out on my own. The problem is just the following line

    circles = new Mat(resultBitmap.getWidth(), resultBitmap.getHeight(), CvType.CV_8UC1);
    

    I don't have to define the dimension of the matrix circles as the dimension of the image. After I cancel that line of code, the program works fine: I can detect circles, coins and even the iris of an eye in real time.

    The result of the method HoughCircles is a matrix of dimension 1xN, where N is the number of detected circles and every element of the matrix is a vector of three data: the coordinates of the center and the radius.

    I know that Hough is not the best method to detect the position of the pupil, but for my project is fine.

    One more thing. In order to get the gray image we could just use the method inputFrame.gray() but do not forget to transpose that image too.

    matGray = inputFrame.gray();
    Core.transpose(matGray,matGray);
    Core.flip(matGray,matGray,1);