我目前正在开发一个程序,它将来自网络摄像头的视频作为输入,然后检测此视频中的移动,在对象周围绘制线条以显示它们移入和移出的位置。
但是,当我运行此程序时,它只会显示一个来自我的网络摄像头的静止图像。我非常清楚为什么会发生这种情况 - if语句if (!(matFrame.empty()))
被评估为false,因此else
语句会运行,将keepProcessing
更改为false
。然后,这将终止while循环,只留下ims.showImage(matFrame);
作为输出。
我无法找到为什么会发生这种情况,所以我希望有人可以帮助我。我已经发布了下面的代码,以便您检查问题。我也尝试用视频运行它以确保这不是我的网络摄像头的故障,我发现了同样的问题。谢谢你的时间。
public class CaptureVideo {
public static void main(String[] args) throws InterruptedException {
// load the Core OpenCV library by name
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// create video capture device object
VideoCapture cap = new VideoCapture();
// try to use the hardware device if present
int CAM_TO_USE = 0;
// create a new image object
Mat matFrame = new Mat();
Mat previousFrame = new Mat();
Mat diffFrame = new Mat();
// try to open first capture device (0)
try {
cap.open(CAM_TO_USE);
} catch (Exception e1) {
System.out.println("No webcam attached");
// otherwise try opening a video file
try{
cap.open("files/video.mp4");
} catch (Exception e2) {
System.out.println("No video file found");
}
}
// if the a video capture source is now open
if (cap.isOpened())
{
// create a new window object
Imshow ims = new Imshow("From video source ... ");
boolean keepProcessing = true;
// add a flag to check whether the first frame has been read
boolean firstFrame = true;
while (keepProcessing)
{
// save previous frame before getting next one, but
// only do this if the first frame has passed
if (!firstFrame)
previousFrame = matFrame.clone();
// grab the next frame from video source
cap.grab();
// decode and return the grabbed video frame
cap.retrieve(matFrame);
// if the frame is valid (not end of video for example)
if (!(matFrame.empty()))
{
// if we are on the first frame, only show that and
// set the flag to false
if (firstFrame) {
ims.showImage(matFrame);
firstFrame = false;
}
// now show absolute difference after first frame
else {
Core.absdiff(matFrame, previousFrame, diffFrame);
ims.showImage(diffFrame);
}
// now convert it to grey and threshold it
Mat grey = new Mat();
Imgproc.cvtColor(diffFrame, grey, Imgproc.COLOR_BGR2GRAY);
Imgproc.adaptiveThreshold(grey, diffFrame, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C,
Imgproc.THRESH_BINARY_INV, 7, 10);
// now clean it up using some morphological operations
Size ksize = new Size(15,15);
Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, ksize);
Imgproc.morphologyEx(diffFrame, diffFrame, Imgproc.MORPH_CLOSE, kernel);
// find the all the contours from the binary image using the edge to contour
// stuff we looked at in lectures
List<MatOfPoint> contours = new Vector<MatOfPoint>();
Imgproc.findContours(diffFrame, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
// draw the contours on image 2 in red
Imgproc.drawContours(matFrame, contours, -1, new Scalar(0,0,255));
// find the largest contour by area
double maxArea = 0;
int maxAreaIndex = 0;
for (int i = 0; i < contours.size(); i++) {
double area = Imgproc.contourArea(contours.get(i), false);
if ( area > maxArea )
{
maxArea = area;
maxAreaIndex = i;
}
}
// draw the largest contour in red
Imgproc.drawContours(matFrame, contours, maxAreaIndex, new Scalar(0,255,0));
// create a new window objects
Imshow ims_diff = new Imshow("Difference");
// display images
ims_diff.showImage(diffFrame);
// display image with a delay of 40ms (i.e. 1000 ms / 25 = 25 fps)
Thread.sleep(40);
} else {
keepProcessing = false;
}
}
}
}
}
答案 0 :(得分:1)
您应该在控制台或输出窗口上看到异常:
OpenCV Error: Assertion failed (scn == 3 || scn == 4) in cv::cvtColor, file ..\..\..\..\opencv\modules\imgproc\src\color.cpp, line 3739 Exception in thread "main" CvException [org.opencv.core.CvException: cv::Exception: ..\..\..\..\opencv\modules\imgproc\src\color.cpp:3739: error: (-215) scn == 3 || scn == 4 in function cv::cvtColor ] at org.opencv.imgproc.Imgproc.cvtColor_1(Native Method) at org.opencv.imgproc.Imgproc.cvtColor(Imgproc.java:4598) at CaptureVideo.main(CaptureVideo.java:87)
其中引用第87行(在我的源文件中):
Imgproc.cvtColor(diffFrame, grey, Imgproc.COLOR_BGR2GRAY);
问题在于diffFrame
尚未初始化,因此它已被轰炸。通过添加此块,我能够让它在本地工作:
// decode and return the grabbed video frame
cap.retrieve(matFrame);
// *** START
if (firstFrame) {
firstFrame = false;
continue;
}
// *** End
// if the frame is valid (not end of video for example)
if (!(matFrame.empty()))
这样做的效果是第一帧不会被绘制,但后续的帧将会被绘制。此外,稍后的代码将为每个&#34; diff&#34;打开一个新的JFrame
(Imshow
)。框架,它会迅速杀死你的机器,所以准备好杀死这个过程。