JavaCV / OpenCV cvDrawContours修改原始图像

时间:2012-07-27 03:16:51

标签: opencv javacv

我正在尝试JavaCV(OpenCV),我对以下行为感到困惑。 我的程序简单:

  1. 抓取图片
  2. 创建图像的灰度版本(保持原始图像不变)
  3. 阈值灰度图像
  4. 在灰度图像中查找轮廓(克隆图像,因为cvFindContours会修改图像,我们希望按原样显示)
  5. 在原始彩色图像上绘制轮廓
  6. 问题在于,除非我克隆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 个答案:

答案 0 :(得分:1)

这是cvFindContours()的预期行为:

  

该功能在提取轮廓时修改图像。