2012-07-27 139 views
3

我正在试验JavaCV(OpenCV),我很困惑以下行为。 我只是PROGRAMM:JavaCV/OpenCV cvDrawContours修改原始图像

  1. 抓取的图像
  2. 创建图像的灰度版本(保留原始图像不变)
  3. 阈值的灰度图像
  4. 查找灰度图像中的轮廓(克隆图像自cvFindContours修改图像,我们要按原样显示)
  5. 绘制轮廓对原始彩色图像

问题是,除非我克隆grabbedImage(请参见注释行),否则将修改灰度图像并绘制轮廓。此外,它好像在grabbedImage上绘制了多个轮廓。

我也试着给循环添加一个睡眠,它修复了这个问题。难道是我多次获得相同(修改)grabbedImage?我检查了Java引用,它不同,但它可能是相同的缓冲区?

有什么想法?

谢谢

package com.mdarveau.opencvtest; 

import static com.googlecode.javacv.cpp.opencv_core.*; 
import static com.googlecode.javacv.cpp.opencv_imgproc.*; 

import com.googlecode.javacpp.Loader; 
import com.googlecode.javacv.CanvasFrame; 
import com.googlecode.javacv.FrameGrabber; 
import com.googlecode.javacv.cpp.opencv_core.CvContour; 
import com.googlecode.javacv.cpp.opencv_core.CvMemStorage; 
import com.googlecode.javacv.cpp.opencv_core.CvScalar; 
import com.googlecode.javacv.cpp.opencv_core.CvSeq; 
import com.googlecode.javacv.cpp.opencv_core.IplImage; 
import com.googlecode.javacv.cpp.opencv_objdetect; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     // Preload the opencv_objdetect module to work around a known bug. 
     Loader.load(opencv_objdetect.class); 

     FrameGrabber grabber = FrameGrabber.createDefault(1); 
     grabber.start(); 

     IplImage grabbedImage = grabber.grab(); 
     int width = grabbedImage.width(); 
     int height = grabbedImage.height(); 

     IplImage grayImage = IplImage.create(width, height, IPL_DEPTH_8U, 1); 

     CvMemStorage storage = CvMemStorage.create(); 

     CanvasFrame filterProbe = new CanvasFrame("Filtered", CanvasFrame.getDefaultGamma()/grabber.getGamma()); 
     CanvasFrame enhancedProbe = new CanvasFrame("Enhanced", CanvasFrame.getDefaultGamma()/grabber.getGamma()); 

     while (filterProbe.isVisible() && enhancedProbe.isVisible() && (grabbedImage = grabber.grab()) != null) { 
      cvClearMemStorage(storage); 

      // Convert to grayscale image... 
      cvCvtColor(grabbedImage, grayImage, CV_BGR2GRAY); 
      // UNCOMMENT FIXES THE PROBLEM grabbedImage = grabbedImage.clone(); 

      // Let's find some contours! but first some thresholding... 
      cvThreshold(grayImage, grayImage, 128, 255, CV_THRESH_BINARY); 

      // To check if an output argument is null we may call either isNull() or equals(null). 
      CvSeq contour = new CvSeq(null); 
      // cvFindContours modifies the image so clone it first since we want to keep the grayscale version 
      cvFindContours(grayImage.clone(), storage, contour, Loader.sizeof(CvContour.class), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); 
      while (contour != null && !contour.isNull()) { 
       if (contour.elem_size() > 0) { 
        CvSeq points = cvApproxPoly(contour, Loader.sizeof(CvContour.class), storage, CV_POLY_APPROX_DP, cvContourPerimeter(contour) * 0.02, 0); 
        cvDrawContours(grabbedImage, points, CvScalar.BLUE, CvScalar.BLUE, -1, 1 /*CV_FILLED*/, CV_AA); 
       } 
       contour = contour.h_next(); 
      } 

      filterProbe.showImage(grayImage); 
      enhancedProbe.showImage(grabbedImage); 
     } 
     filterProbe.dispose(); 
     enhancedProbe.dispose(); 
     grabber.stop(); 
    } 
} 

回答

1

这是cvFindContours()预期的行为:

功能修改图像而提取的轮廓。