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,860
  • 5
  • 24
  • 48

2 Answers2

2

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,685
  • 5
  • 29
  • 54
  • 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 a
  • 750
  • 10
  • 19