Search code examples
javaopencvimage-processingcontourrobotics

Java error "OpenCV Assertion failed: (-215:Assertion failed) npoints >= 0 && (depth == CV_32F || depth == CV_32S)"


When I try to run this openCV code on an FTC robot:

        List<MatOfPoint> contours = new ArrayList<>();
        Imgproc.findContours(thresholded, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
        contoursAttr = contours;

        MatOfPoint biggestContour = new MatOfPoint();

        for (MatOfPoint curContour : contours) {
            if (Imgproc.contourArea(curContour) > Imgproc.contourArea(biggestContour)) {
                biggestContour = curContour;
            }
        }

I get the error in the title, namely "OpenCV Assertion failed: (-215:Assertion failed) npoints >= 0 && (depth == CV_32F || depth == CV_32S)". I've seen other answers for this question, but they almost all talk about signatures changing across versions, and are somewhat python-specific. However, given that contours is a List<MatOfPoint>, I feel like this should work??

Thanks.


Solution

  • In the first iteration of the loop, biggestContour is created using default constructor, and has the wrong OpenCV depth.

    The following code creates MatOfPoint object with default constructor:

    MatOfPoint biggestContour = new MatOfPoint();
    

    In the first iteration, the following code computes contourArea over the "new" MatOfPoint:

    if (Imgproc.contourArea(curContour) > Imgproc.contourArea(biggestContour)
    

    The result is the error "OpenCV Assertion failed... && (depth == CV_32F || depth == CV_32S)"
    The reason for getting the specific assertion is because the depth of the "new" MatOfPoint is CV_8UC1 (not CV_32F and not CV_32S).


    Suggested solution:
    Initialize biggestContour to the first contour in the list:

    MatOfPoint biggestContour = contours.get(0); //new MatOfPoint();
    
    for (MatOfPoint curContour : contours) {
        if (Imgproc.contourArea(curContour) > Imgproc.contourArea(biggestContour)) {
            biggestContour = curContour;
        }
    }        
    

    It is also a good practice to verify that contours is not empty:

    if (!contours.isEmpty())
    {
        MatOfPoint biggestContour = contours.get(0);//new MatOfPoint();
        
        for (MatOfPoint curContour : contours) {
            if (Imgproc.contourArea(curContour) > Imgproc.contourArea(biggestContour)) {
                biggestContour = curContour;
            }
        }
    }