I want to do some image analysis on a video that's stored in .mp4 format. Therefore I need a way to just get the images of this movie in Java.
I goolged a lot and found some libraries like jcodec and jaad. BUT I wasn't able to get the things running with these libraries. And as I found out, there were examples (at least I found none) that showed my usecase.
Can you help me? Do you know any library that can do what I need and is running at least on Win7 64 bit.
Or do you know how to accomplish this with jcodec?
edit:
As I wrote, I tried it with jcodec. I found out how to get the data of a frame, but not how I can get it into something like a BufferedImage or so. I expect that these data isn't in a simple RGB format but in any compressed format or so. (Am I right with that?) I don't know to to decode this data.
You can get the data of a frame with jcodec as follows (at least as far as I understand this):
public static void main(String[] args) throws IOException, MP4DemuxerException {
String path = "videos/video-2011-09-21-20-07-21.mp4";
MP4Demuxer demuxer1 = new MP4Demuxer(new FileInput(new File(path)));
DemuxerTrack videoTrack = demuxer1.getVideoTrack();
Packet firstFrame = videoTrack.getFrames(1);
byte[] data = firstFrame.getData();
}
I also found the following:
http://code.google.com/p/jcodec/source/browse/trunk/src/test/java/org/jcodec/containers/mp4/DitherTest.java?r=70
But this isn't working (has compile errors) with the downloadable jar-package.
you could use jcodec(https://github.com/jcodec/jcodec) in the followinf program i am extracting frames from a video.
/*
* To extract frames from a mp4(avc) video
*
*/
package avc_frame;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.jcodec.api.FrameGrab;
import org.jcodec.api.JCodecException;
public class Avc_frame {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException, JCodecException {
long time = System.currentTimeMillis();
for (int i = 50; i < 57; i++) {
BufferedImage frame = FrameGrab.getFrame(new File("/Users/jovi/Movies/test.mp4"), i);
ImageIO.write(frame, "bmp", new File("/Users/jovi/Desktop/frames/frame_"+i+".bmp"));
}
System.out.println("Time Used:" + (System.currentTimeMillis() - time)+" Milliseconds");
}
}
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FrameGrabber.Exception;
public class Read{
public static void main(String []args) throws IOException, Exception
{
FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber("C:/Users/Digilog/Downloads/Test.mp4");
frameGrabber.start();
IplImage i;
try {
i = frameGrabber.grab();
BufferedImage bi = i.getBufferedImage();
ImageIO.write(bi,"png", new File("D:/Img.png"));
frameGrabber.stop();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Related
I am trying to convert the image to a searchable pdf using tesseract. The below command line option working fine for me.
Exploring a similar option in java. But not sure what to pass in the arguments. Below is my java code
import java.io.File;
import java.util.Arrays;
import java.util.List;
import net.sf.saxon.expr.instruct.ValueOf;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;
public class Mask2 {
public static void main(String[] args) {
File image = new File("D:\\ML\\Java\\img3.PNG");
Tesseract tesseract = new Tesseract();
tesseract.setDatapath("C://Program Files//Tesseract-OCR//tessdata");
tesseract.setLanguage("eng");
tesseract.setPageSegMode(1);
tesseract.setOcrEngineMode(1);
try {
// Not sure what to pass in arguments
tesseract.createDocumentsWithResults()
} catch (TesseractException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Any Suggestions / Solutions would be much helpful.
you can create a list of renderFormats like this ( you can add others)
List<RenderedFormat> renderFormats = new ArrayList<RenderedFormat>();
renderFormats.add(RenderedFormat.PDF);
and then you can pass the path of the input filename (PDF or IMG), the path of the output filename with no extension, and the render format you want to use.
tesseract.createDocuments("a/b/c/inputfile.PNG", "a/b/c/outputfile", renderFormats);
Ciao!
My final goal is to convert a file from ANSI to UTF-8. To do so, I use some code with Java :
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class ConvertFromAnsiToUtf8 {
public static void main(String[] args) throws IOException {
try {
Path p = Paths.get("C:\\shared_to_vm\\test_encode\\test.csv");
ByteBuffer bb = ByteBuffer.wrap(Files.readAllBytes(p));
CharBuffer cb = Charset.forName("windows-1252").decode(bb);
bb = Charset.forName("UTF-8").encode(cb);
Files.write(p, bb.array());
} catch (Exception e) {
System.out.println(e);
}
}
}
The code works perfectly when I test it on small files. My file is convert from ANSI to UTF-8 and all characters are recognize and well encoded. But as soon as I try to use it on the file I need to convert, I get the error java.lang.OutOfMemoryError: Java heap space.
So far as my understanding goes, I got like 1.5 million lines in my file so I am pretty sure I create too many objects with my application.
Of course, I have checked what this error means and how I could solve it (like here or here for example) but is improving the memory capacity of my JVM the only way to solve it ? And if it is, how much more should i use ?
Any kind of help (tip, advice, link or else) would be greatly appreciated !
Don't read the whole file at once:
ByteBuffer bb = ByteBuffer.wrap(Files.readAllBytes(p));
Instead, try to read line-by-line:
Files.lines(p, Charset.forName("windows-1252")).forEach(line -> {
// Convert your line, write to file
});
Stream the input, convert the character encoding, and write the output as you go. This way, you don't need to read the entire file into memory, but only as much as you want.
If you want to minimize the number of (slowish) system calls, you could use a similar approach, but explicitly create a BufferedInputStream with a larger internal buffer, and then wrap that in an InputStreamReader. But the simple approach shown here is unlikely to be a critical point in many applications.
private static final Charset WINDOWS1252 = Charset.forName("windows-1252");
private static final int DEFAULT_BUF_SIZE = 8192;
public static void transcode(Path input, Path output) throws IOException {
try (Reader r = Files.newBufferedReader(input, WINDOWS1252);
Writer w = Files.newBufferedWriter(output, StandardCharsets.UTF_8, StandardOpenOption.CREATE_NEW)) {
char[] buf = new char[DEFAULT_BUF_SIZE];
while (true) {
int n = r.read(buf);
if (n < 0) break;
w.write(buf, 0, n);
}
}
}
If you have a large file, which is larger then available random access memory you should convert characters chunk-by-chunk.
Following you can found the example:
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class Iconv {
private static void iconv(Charset toCode, Charset fromCode, Path src, Path dst) throws IOException {
CharsetDecoder decoder = fromCode.newDecoder();
CharsetEncoder encoder = toCode.newEncoder();
try (ReadableByteChannel source = FileChannel.open(src, StandardOpenOption.READ);
WritableByteChannel destination = FileChannel.open(dst, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING,
StandardOpenOption.WRITE);) {
ByteBuffer readBytes = ByteBuffer.allocate(4096);
while (source.read(readBytes) > 0) {
readBytes.flip();
destination.write(encoder.encode(decoder.decode(readBytes)));
readBytes.clear();
}
}
}
public static void main(String[] args) throws Exception {
iconv(Charset.forName("UTF-8"), Charset.forName("Windows-1252"), Paths.get("test.csv") , Paths.get("test-utf8.csv") );
}
}
My code here is compiling correctly, but I am running into the problem that my ArrayList of BufferedImages is always empty. Honestly I don't have any knowledge regarding ImageIO or the likes!
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.imageio.IIOException;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import net.sf.javavp8decoder.imageio.WebPImageReader;
import net.sf.javavp8decoder.imageio.WebPImageReaderSpi;
class MyProj{
public static void main(String[] args) throws IOException{
System.out.println("Main");
ArrayList<BufferedImage> collectedImg=getFrames();
}
static ArrayList<BufferedImage> getFrames() throws IIOException{
File MyWebM= new File("/users/case3/mcclusm4/workspace/LineTech/src/goal.webm");
ArrayList<BufferedImage> frames = new ArrayList<BufferedImage>();
try{
ImageReader ir = new WebPImageReader(new WebPImageReaderSpi());
ir.setInput(ImageIO.createImageInputStream(MyWebM));
for(int i = 0; i < ir.getNumImages(true); i++)
frames.add(ir.read(i));
}catch(IOException e){}
return frames;
}
}
First of all dont catch Exception and do nothing:
catch (Exception e) {}
Now when an exception is catched it silently fails without any information.
Change catch to print stacktrace: e.printStackTrace() and post it.
Disclaimer: I have never tested the code in question myself. But...
From looking at the source code of net.sf.javavp8decoder.imageio.WebPImageReader it cannot decode WebM files. It only supports single frame WebP files.
If you stop swallowing the exception and ignoring it, as suggested by #robocoder, you should get an IIOException with the message "Bad WEBP signature!".
I have images of codes that I want to decode. How can I use zxing so that I specify the image location and get the decoded text back, and in case the decoding fails (it will for some images, that's the project), it gives me an error.
How can I setup zxing on my Windows machine? I downloaded the jar file, but I don't know where to start. I understand I'll have to create a code to read the image and supply it to the library reader method, but a guide how to do that would be very helpful.
I was able to do it. Downloaded the source and added the following code. Bit rustic, but gets the work done.
import com.google.zxing.NotFoundException;
import com.google.zxing.ChecksumException;
import com.google.zxing.FormatException;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.DecodeHintType;
import com.google.zxing.Reader;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.Result;
import com.google.zxing.LuminanceSource;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import java.util.*;
import com.google.zxing.qrcode.QRCodeReader;
class qr
{
public static void main(String args[])
{
Reader xReader = new QRCodeReader();
BufferedImage dest = null;
try
{
dest = ImageIO.read(new File(args[0]));
}
catch(IOException e)
{
System.out.println("Cannot load input image");
}
LuminanceSource source = new BufferedImageLuminanceSource(dest);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Vector<BarcodeFormat> barcodeFormats = new Vector<BarcodeFormat>();
barcodeFormats.add(BarcodeFormat.QR_CODE);
HashMap<DecodeHintType, Object> decodeHints = new HashMap<DecodeHintType, Object>(3);
decodeHints.put(DecodeHintType.POSSIBLE_FORMATS, barcodeFormats);
decodeHints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
Result result = null;
try
{
result = xReader.decode(bitmap, decodeHints);
System.out.println("Code Decoded");
String text = result.getText();
System.out.println(text);
}
catch(NotFoundException e)
{
System.out.println("Decoding Failed");
}
catch(ChecksumException e)
{
System.out.println("Checksum error");
}
catch(FormatException e)
{
System.out.println("Wrong format");
}
}
}
The project includes a class called CommandLineRunner which you can simply call from the command line. You can also look at its source to see how it works and reuse it.
There is nothing to install or set up. It's a library. Typically you don't download the jar but declare it as a dependency in your Maven-based project.
If you just want to send an image to decode, use http://zxing.org/w/decode.jspx
i have axis m1114 ip camera
i want to display live streaming as well as record streaming using java. i tried following code but frame rate is very low
please suggest some api gives me more frame rate and recording functionality.
import java.io.File;
import java.net.URL;
import com.googlecode.javacpp.Loader;
import com.googlecode.javacv.*;
import com.googlecode.javacv.cpp.*;
import static com.googlecode.javacv.cpp.opencv_core.*;
import static com.googlecode.javacv.cpp.opencv_imgproc.*;
import static com.googlecode.javacv.cpp.opencv_calib3d.*;
import static com.googlecode.javacv.cpp.opencv_objdetect.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import demo.authenticator.MyAuthenticator;
import java.net.Authenticator;
import java.net.MalformedURLException;
import org.jcodec.api.SequenceEncoder;
public class Demo {
public static void main(String[] args) throws IOException {
CanvasFrame CamWindow = new CanvasFrame("Camera");
int i=0,j=0;
URL url = null ;
SequenceEncoder encoder=new SequenceEncoder(new File("video.mp4"));
try {
// Create a new URL object from the URL-string of our camera.
url = new URL("http://192.168.168.92/axis-cgi/jpg/image.cgi");
} catch (MalformedURLException m) {
m.getMessage();
}
// Check if this camera requires authentication.
// If so, then create and set the authenticator object.
MyAuthenticator authenticator = new MyAuthenticator("root",
"pass");
Authenticator.setDefault(authenticator);
Long stime=System.currentTimeMillis();
while(true){
i++;
//InputStream is = url.openStream();
BufferedImage image = ImageIO.read(url);
CamWindow.showImage(image);
// is.close();
/* if(i<100)
{
encoder.encodeImage(image);
}
else
{
if(j==0)
{
encoder.finish();
j++;
System.out.println("video saved");
System.out.println((System.currentTimeMillis()-stime)/1000+"seconds");
}
}*/
System.out.println((System.currentTimeMillis()-stime));
}
}
}
The Axis camera API is here: http://www.axis.com/files/manuals/vapix_video_streaming_52937_en_1307.pdf
You need to use this:
http:///axis-cgi/mjpg/video.cgi
instead of the image URL you have now. Getting a still image from the Axis camera will be very choppy. You need to use the Motion JPEG feed it spits out.
I have also gone through for these solutions and one of the good API i found is WEBCAM-Capture. I rate it good for some reasons
It is updated
It is open source
Many Examples
And most IMPORTANT its support from its developers is fast and accurate rather than other Camera supporting APIs.
Hope this would help you.