Java中OpenCV椭圆检测的问题

时间:2014-02-22 23:48:55

标签: java c++ opencv image-processing javacv

我们尝试将c ++代码从Detection of coins (and fit ellipses) on an image转换为Java。当我们用参数

启动程序时
2 PathToThePicture

它崩溃了这个错误:

 OpenCV Error: Bad argument (Array should be CvMat or IplImage) in cvGetSize, file       
 ..\..\..\..\opencv\modules\core\src\array.cpp, line 1238
 Exception in thread "main" java.lang.RuntimeException: ..\..\..\..\opencv\modules       
 \core\src\array.cpp:1238: error: (-5) Array should be CvMat or IplImage in function   
 cvGetSize

 at com.googlecode.javacv.cpp.opencv_core.cvGetSize(Native Method)
 at DetectEllipse.main(DetectEllipse.java:65)

这是转换后的Java代码:

import static com.googlecode.javacv.cpp.opencv_core.CV_FILLED;
import static com.googlecode.javacv.cpp.opencv_core.CV_RGB;
import static com.googlecode.javacv.cpp.opencv_core.CV_WHOLE_SEQ;
import static com.googlecode.javacv.cpp.opencv_core.cvCreateImage;
import static com.googlecode.javacv.cpp.opencv_core.cvCreateMemStorage;
import static com.googlecode.javacv.cpp.opencv_core.cvDrawContours;
import static com.googlecode.javacv.cpp.opencv_core.cvGetSize;
import static com.googlecode.javacv.cpp.opencv_core.cvPoint;
import static com.googlecode.javacv.cpp.opencv_core.cvScalar;
import static com.googlecode.javacv.cpp.opencv_core.cvXorS;
import static com.googlecode.javacv.cpp.opencv_core.cvZero;
import static com.googlecode.javacv.cpp.opencv_highgui.cvLoadImage;
import static com.googlecode.javacv.cpp.opencv_highgui.cvSaveImage;
import static com.googlecode.javacv.cpp.opencv_imgproc.CV_CHAIN_APPROX_SIMPLE;
import static com.googlecode.javacv.cpp.opencv_imgproc.CV_RETR_CCOMP;
import static com.googlecode.javacv.cpp.opencv_imgproc.CV_THRESH_BINARY;
import static com.googlecode.javacv.cpp.opencv_imgproc.cvContourArea;
import static com.googlecode.javacv.cpp.opencv_imgproc.cvDilate;
import static com.googlecode.javacv.cpp.opencv_imgproc.cvFindContours;
import static com.googlecode.javacv.cpp.opencv_imgproc.cvThreshold;

import com.googlecode.javacpp.Loader;
import com.googlecode.javacv.cpp.opencv_core.CvContour;
import com.googlecode.javacv.cpp.opencv_core.CvMemStorage;
import com.googlecode.javacv.cpp.opencv_core.CvRect;
import com.googlecode.javacv.cpp.opencv_core.CvScalar;
import com.googlecode.javacv.cpp.opencv_core.CvSeq;
import com.googlecode.javacv.cpp.opencv_core.IplImage;

public class DetectEllipse{

    public static final double M_PI = 3.14159265358979323846;
    public static final double MIN_AREA = 100.00;
    public static final double MAX_TOL = 100.00;

    private static int[] array = { 0 };
    //
    // We need this to be high enough to get rid of things that are too small
    // too
    // have a definite shape. Otherwise, they will end up as ellipse false
    // positives.
    //
    //
    // One way to tell if an object is an ellipse is to look at the relationship
    // of its area to its dimensions. If its actual occupied area can be
    // estimated
    // using the well-known area formula Area = PI*A*B, then it has a good
    // chance of
    // being an ellipse.
    //
    // This value is the maximum permissible error between actual and estimated
    // area.
    //

    public static void main(String[] args) {
        IplImage src = cvLoadImage(args[1], 0);
        // the first command line parameter must be file name of binary
        // (black-n-white) image
        if (Integer.parseInt(args[0]) == 2) {
            IplImage dst = cvCreateImage(cvGetSize(src), 8, 3);
            CvMemStorage storage = cvCreateMemStorage(0);
            CvSeq contour = new CvContour();
            // maybe: = new CvSeq(0)
            cvThreshold(src, src, 1, 255, CV_THRESH_BINARY);
            //
            // Invert the image such that white is foreground, black is
            // background.
            // Dilate to get rid of noise.
            //
            cvXorS(src, cvScalar(255, 0, 0, 0), src, null);
            cvDilate(src, src, null, 2);

            cvFindContours(src, storage, contour,
                    Loader.sizeof(CvContour.class), CV_RETR_CCOMP,
                    CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));
            cvZero(dst);

            for (; contour.flags() != 0; contour = contour.h_next()) {
                // if not working: use contour.isNull()
                double actual_area = Math.abs(cvContourArea(contour,
                        CV_WHOLE_SEQ, 0));
                if (actual_area < MIN_AREA)
                    continue;

                //
                // FIXME:
                // Assuming the axes of the ellipse are vertical/perpendicular.
                //
                CvRect rect = ((CvContour) contour).rect();
                int A = rect.width() / 2;
                int B = rect.height() / 2;
                double estimated_area = Math.PI * A * B;
                double error = Math.abs(actual_area - estimated_area);
                if (error > MAX_TOL)
                    continue;
                System.out.printf("center x: %d y: %d A: %d B: %d\n", rect.x()
                        + A, rect.y() + B, A, B);

                CvScalar color = CV_RGB(
                        tangible.RandomNumbers.nextNumber() % 255,
                        tangible.RandomNumbers.nextNumber() % 255,
                        tangible.RandomNumbers.nextNumber() % 255);
                cvDrawContours(dst, contour, color, color, -1, CV_FILLED, 8,
                        cvPoint(0, 0));
            }

            cvSaveImage("coins.png", dst, array);
        }
    }

}

任何人都可以帮忙使用吗?提前谢谢!

1 个答案:

答案 0 :(得分:1)

可能cvGetSize(src)正在进行崩溃。当srcnull时会发生这种情况。

换句话说,没有加载/找到图像(可能路径错了?)。

将来,您可以通过测试图像是否已成功加载来避免此类问题:

IplImage src = cvLoadImage(args[1], 0);
if (src == null) 
{
    System.out.println("!!! Unable to load image: " + args[1]);
    return;
}