为什么我的程序在视频的第一帧之后终止?

时间:2015-03-20 14:31:05

标签: java opencv image-processing

我目前正在开发一个程序,它将来自网络摄像头的视频作为输入,然后检测此视频中的移动,在对象周围绘制线条以显示它们移入和移出的位置。

但是,当我运行此程序时,它只会显示一个来自我的网络摄像头的静止图像。我非常清楚为什么会发生这种情况 - 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;

                }
            }
      }
   }
}

1 个答案:

答案 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;打开一个新的JFrameImshow)。框架,它会迅速杀死你的机器,所以准备好杀死这个过程。