3
我正在试验JavaCV(OpenCV),我很困惑以下行为。 我只是PROGRAMM:JavaCV/OpenCV cvDrawContours修改原始图像
- 抓取的图像
- 创建图像的灰度版本(保留原始图像不变)
- 阈值的灰度图像
- 查找灰度图像中的轮廓(克隆图像自cvFindContours修改图像,我们要按原样显示)
- 绘制轮廓对原始彩色图像
问题是,除非我克隆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();
}
}