3

i have just started to learn openCV in java and i have setup my Eclipse IDE with all OpenCV java dependencies.

Now i have a task in hand to extract a single frame from a video file which i have recorded in .avi file format.

i searched from this link and used the code given there as below,

package vasanth;

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.highgui.Highgui;
import org.opencv.highgui.VideoCapture;

public class Vasanth {

public static void main(String[] args) {
    // TODO Auto-generated method stub
    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    VideoCapture camera = new VideoCapture("G:\\PICTURES\\roxtar vassy\\early days in APSCE.wmv");



/*  if(!camera.isOpened()){
        System.out.println("Error");
    } */


        Mat frame = new Mat();  

        while(true){
            System.out.println("Looping.. \n");
            if (camera.read(frame)){
                System.out.println("Frame Obtained");
                System.out.println("Captured Frame Width " + 
                frame.width() + " Height " + frame.height());
                Highgui.imwrite("camera.jpg", frame);

                System.out.println("OK");
                break;
            }
        }   
    }

}

when i execute this, the program is looping at inifinitely at this line

camera.read(frame)

i also tried running this code without he loop and was successfully in getting the camera.jpg file on my system but the file was corrupted. I understand that this frame was not completely extracted with all the pixels and hence seems corrupted.

So the problem here is why does camera.read(frame) this always return false and the loop never breaks?

I have waited for more than 10 minutes. All i want to do is extract one single frame and it is not happening with this method.

As per what i have searched on google i understant there is a tool called ffmpeg which takes a video file as input and give me frames. But i want to achieve this functionality with my own java code running on Eclipse for starters.

Vasanth Nag K V
  • 4,648
  • 5
  • 23
  • 42

2 Answers2

1

There are couple of issues I faced while reproducing your issue, so let me guide you through them.

  1. First of all, you use the old version of the framework. The current one is 3.2, so consider upgrading. I used the newest version.

  2. You should not comment out the camera.isOpened() check since if the camera is not opened there is no sense to proceed. I assume, that your app couldn't pass that check, so you decided to skip that :) But in order to open the camera properly you should either do this or this. The first link worked for me (the only change is that for 3.2 version the path is \opencv\build\x64\vc14\bin and I had to reboot computer)

The code is pretty much the same as you have so far with only difference for the latest version:

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.videoio.VideoCapture;

import javax.swing.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.WritableRaster;
import java.nio.file.Paths;

public class Vasanth {

    public static void main(String[] args) {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        String filePath = "G:\\PICTURES\\roxtar vassy\\early days in APSCE.wmv";
        if (!Paths.get(filePath).toFile().exists()){
             System.out.println("File " + filePath + " does not exist!");
             return;
        }

        VideoCapture camera = new VideoCapture(filePath);

        if (!camera.isOpened()) {
            System.out.println("Error! Camera can't be opened!");
            return;
        }
        Mat frame = new Mat();

        while(true){
            if (camera.read(frame)){
                System.out.println("Frame Obtained");
                System.out.println("Captured Frame Width " +
                        frame.width() + " Height " + frame.height());
                Imgcodecs.imwrite("camera.jpg", frame);
                System.out.println("OK");
                break;
            }
        }

        BufferedImage bufferedImage = matToBufferedImage(frame);
        showWindow(bufferedImage);
        camera.release();
    }

    private static BufferedImage matToBufferedImage(Mat frame) {
        int type = 0;
        if (frame.channels() == 1) {
            type = BufferedImage.TYPE_BYTE_GRAY;
        } else if (frame.channels() == 3) {
            type = BufferedImage.TYPE_3BYTE_BGR;
        }
        BufferedImage image = new BufferedImage(frame.width(), frame.height(), type);
        WritableRaster raster = image.getRaster();
        DataBufferByte dataBuffer = (DataBufferByte) raster.getDataBuffer();
        byte[] data = dataBuffer.getData();
        frame.get(0, 0, data);

        return image;
    }

    private static void showWindow(BufferedImage img) {
        JFrame frame = new JFrame();
        frame.getContentPane().add(new JLabel(new ImageIcon(img)));
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setSize(img.getWidth(), img.getHeight() + 30);
        frame.setTitle("Image captured");
        frame.setVisible(true);
    }
}

Note, that in order to demonstrate that this piece of code works I use simple Swing JFrame:

enter image description here

Community
  • 1
  • 1
Enigo
  • 3,351
  • 5
  • 29
  • 51
  • thanks for your time on this Enigo, so you are saying the only change to get this working is the version upgrade and the path to native Open cv libs? and also, how much time did it take to capture this frame for you? – Vasanth Nag K V Mar 01 '17 at 10:00
  • @VasanthNagKV exactly! To be honest, I think that it should work even for the version you're using if you add everything correctly [this](http://stackoverflow.com/q/11699298/5151575) may help. I tested with really short video (5 secs length) and the image was captured instantly. – Enigo Mar 01 '17 at 10:50
  • do you feel that the time taken to capture a single frame depends on the entire video length? – Vasanth Nag K V Mar 01 '17 at 12:01
  • well, I don't know for sure, but I think it should not. Since, according to docs this method just reads next frame, total size of frames should not matter. Unfortunately, I don't have any long videos to test it. – Enigo Mar 01 '17 at 13:20
  • i have tried running your code on my machine and i see its stuck at the point u commented on in your answer if (!camera.isOpened()) { System.out.println("Error! Camera can't be opened!"); return; } why is this?? i checked on the links u gave but not muh i understood – Vasanth Nag K V Mar 01 '17 at 16:24
  • One more thing to check is that the file actually exists (see updated answer). Have you done everything that I suggested? Especially [this](http://stackoverflow.com/a/29920295/5151575). If camera cannot be opened the most probable problem is missing libs. – Enigo Mar 01 '17 at 18:50
  • i have made the changes as per the link u shared, i added the libs path to the system path env variable and restarted eclipse, still its the same result, i assume in this flow the ffmget lib will be used from this path, and this lib file is also present why is it still not working is what i wonder – Vasanth Nag K V Mar 01 '17 at 20:24
  • I had to restart the system if that matters. Have you upgraded the version? 'cos the link I've shared is about 3.x version. – Enigo Mar 02 '17 at 05:07
  • restarted the system and Bam !! it works !! thanks Enigo ! and i have awarded the 50 points bounty too :) – Vasanth Nag K V Mar 03 '17 at 14:41
  • Anyone stuck on this could also try coping opencv_ffmpegXXX_64.dll from opencv/build/java/x64 or from opencv\build\x64\vc14\bin. I don't know why this works but it worked for me after trying https://stackoverflow.com/a/29920295/677185 and https://github.com/opencv/opencv/issues/4974 – vincent mathew Feb 09 '18 at 20:27
0

I was facing the same issue which is camera.isOpened() returning false. This is how I resolved it.

String filePath = "C:\\Aslam_Face_Detection.mp4";
VideoCapture camera = new VideoCapture(filePath);
camera.open(filePath); // This is the line I added
camera.isOpened(); // returns true. worked.
Aslam anwer
  • 715
  • 9
  • 18