为什么我的程序在视频的第一帧之后终止?
Why does my program terminate after the first frame of the video?
我目前正在开发一个程序,该程序将来自网络摄像头的视频作为输入,然后检测该视频中的移动,在对象周围画线以显示它们移动的位置。
但是,当我 运行 这个程序时,它所做的一切都是从我的网络摄像头中显示一张静止图像。我很清楚为什么会发生这种情况 - if 语句 if (!(matFrame.empty()))
被评估为 false,因此 else
语句 运行s,将 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;
}
}
}
}
}
您应该会在控制台或输出中看到异常 window:
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()))
这样做的效果是第一帧不画,后面的画。此外,稍后的代码将为每个 "diff" 帧打开一个新的 JFrame
(Imshow
),这将很快杀死你的机器,所以准备好杀死进程。
我目前正在开发一个程序,该程序将来自网络摄像头的视频作为输入,然后检测该视频中的移动,在对象周围画线以显示它们移动的位置。
但是,当我 运行 这个程序时,它所做的一切都是从我的网络摄像头中显示一张静止图像。我很清楚为什么会发生这种情况 - if 语句 if (!(matFrame.empty()))
被评估为 false,因此 else
语句 运行s,将 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;
}
}
}
}
}
您应该会在控制台或输出中看到异常 window:
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()))
这样做的效果是第一帧不画,后面的画。此外,稍后的代码将为每个 "diff" 帧打开一个新的 JFrame
(Imshow
),这将很快杀死你的机器,所以准备好杀死进程。