javacv:在Java中迭代CvSeq

时间:2013-11-21 08:34:31

标签: java opencv javacv

我使用:

cvFindContours(gray, mem, contours, Loader.sizeof(CvContour.class) , CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));


结果我有CvSeq contours进行迭代(据我所知) 所以我这样使用它:

if(contours!=null) {
  for (ptr = contours; ptr != null; ptr = ptr.h_next()) {
    //..do sth with ptr
  }
}

它有效,但我不时(经常)得到:

Exception in thread "Thread-3" java.lang.NullPointerException: This pointer address is NULL.
at com.googlecode.javacv.cpp.opencv_core$CvSeq.h_next(Native Method)
at pl..filter(FullFilter.java:69)
at pl..Window$1.run(Window.java:41)
at java.lang.Thread.run(Unknown Source)


抛出异常的行是ptr.h_next()的行 我试图检查空值但它不起作用:

System.out.println("PTR="+ptr); // it's not null here!
if(ptr.h_next()==null) //exception in this line!
    System.out.println("NULL");
System.out.println(ptr.h_next());

第一行显示:       PTR=com.googlecode.javacv.cpp.opencv_core$CvSeq[address=0x0,position=0,limit=1,capacity=1,deallocator=com.googlecode.javacpp.Pointer$NativeDeallocator@66d53ea4]

我也试过调用contours.total(),但它总是抛出相同的异常 那么,在Java中使用这种C类序列的正确方法是什么?

修改 我的完整方法:

    public IplImage filter(IplImage image) {
        IplConvKernel kernel = cvCreateStructuringElementEx(2,2,1,1,CV_SHAPE_RECT, null);
        cvDilate(image, image, kernel, 1);
        kernel = cvCreateStructuringElementEx(5,5,2,2,CV_SHAPE_RECT, null);
        cvErode(image, image, kernel, 1);
        IplImage resultImage = cvCloneImage(image);
        IplImage gray = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1); 
        cvCvtColor(image, gray, CV_BGR2GRAY);
        CvMemStorage mem = CvMemStorage.create();
        CvSeq contours = new CvSeq();
        CvSeq ptr = new CvSeq();
        cvThreshold(gray, gray, 20, 255, opencv_imgproc.CV_THRESH_BINARY);
        double thresh = 20;
        Canny( gray, gray, thresh, thresh*2, 3 ,true);
        cvFindContours(gray, mem, contours, Loader.sizeof(CvContour.class) , CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));

        int i=0;
        CvRect boundbox;
        if(contours!=null) {
            for (ptr = contours; ptr != null; ptr = ptr.h_next()) { //EXCEPTION HERE!
                System.out.println((i++)+"\t"+ptr);
                cvDrawContours( resultImage, ptr, CvScalar.BLUE, CvScalar.RED, -1, 3, 8, cvPoint(0,0) );
                System.out.println("PTR="+ptr);
            }

        }       
        return resultImage;
    }

它可以正常工作一段时间并突然(可能在没有找到轮廓的情况下?)以下列异常结束:

Exception in thread "Thread-3" java.lang.NullPointerException: This pointer address is NULL.
    at com.googlecode.javacv.cpp.opencv_core$CvSeq.h_next(Native Method)
    at pl.kasprowski.eyetracker.FullFilter2.filter(FullFilter2.java:39)
    at pl.kasprowski.eyetracker.Window$1.run(Window.java:42)
    at java.lang.Thread.run(Unknown Source)

我直接用从相机拍摄的图像(每秒一次)喂养方法。

编辑:

经过一些实验后,我不时会调用cvFindContours,我会得到一个contour对象,它不是NULL,而是调用contour.h_next()或{{1}之类的任何方法像上面那样导致异常。有什么不对?或者 - 如何检查contour.total()对象是否正常?!当然我可以抓住contour,但我不认为这是解决问题的正确方法......

2 个答案:

答案 0 :(得分:2)

问题解决了。
我添加了额外的条件。而不是:

if(contours!=null) {

我写了

if(contours!=null && !contours.isNull()) {

它有效。我不确切地知道为什么它是必要的,但我认为它与Java相关< - > C语义差距。

答案 1 :(得分:0)

尝试使用cvGetSeqElem(contours, i)

示例:

for (int i = 0; i < contours.total(); i++) {
   CvRect rect = cvBoundingRect(cvGetSeqElem(contours, i),0);
    //....... Your code ....//

}