org.bytedeco.javacv.Java2DFrameUtils
中有封装好的方法:
package org.bytedeco.javacv;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.opencv.opencv_core.IplImage;
import org.bytedeco.opencv.opencv_core.Mat;
/**
* Convenience class for performing various conversions between Mat, IplImage,
* BufferedImage and Frame objects. Methods are synchronized because the
* underlying JavaCV converters aren't safe for concurrent access.
*
* All created Frame, Mat, IplImages and BufferedImages are cloned internally
* after creation so that their memory locations remain valid after the
* converters which created them are garbage collected. This is safer for the
* called, but may be slower.
*
* If performance is critical, use the *FrameConverter classes directly, after
* reading about the image validity constraints (eg, images data is only valid
* until next call to the converter).
*
* @see <a href="https://groups.google.com/forum/#!topic/javacv/sSgY9e-IDRA">Java2DFrameConverter crashes JVM</a>
* @see FrameConverter
*
* @author Sam West, Joel Wong, Sep 2016.
*
*/
public class Java2DFrameUtils {
private static OpenCVFrameConverter.ToIplImage iplConv = new OpenCVFrameConverter.ToIplImage();
private static OpenCVFrameConverter.ToMat matConv = new OpenCVFrameConverter.ToMat();
private static Java2DFrameConverter biConv = new Java2DFrameConverter();
/**
* Clones (deep copies the data) of a {@link BufferedImage}. Necessary when
* converting to BufferedImages from JavaCV types to avoid re-using the same
* memory locations.
*
* @param source
* @return
*/
public static BufferedImage deepCopy(BufferedImage source) {
return Java2DFrameConverter.cloneBufferedImage(source);
}
public synchronized static BufferedImage toBufferedImage(IplImage src) {
return deepCopy(biConv.getBufferedImage(iplConv.convert(src).clone()));
}
public synchronized static BufferedImage toBufferedImage(Mat src) {
return deepCopy(biConv.getBufferedImage(matConv.convert(src).clone()));
}
public synchronized static BufferedImage toBufferedImage(Frame src) {
return deepCopy(biConv.getBufferedImage(src.clone()));
}
public synchronized static IplImage toIplImage(Mat src){
return iplConv.convertToIplImage(matConv.convert(src)).clone();
}
public synchronized static IplImage toIplImage(Frame src){
return iplConv.convertToIplImage(src).clone();
}
public synchronized static IplImage toIplImage(BufferedImage src){
return iplConv.convertToIplImage(biConv.convert(src)).clone();
}
public synchronized static Mat toMat(IplImage src){
return matConv.convertToMat(iplConv.convert(src).clone());
}
public synchronized static Mat toMat(Frame src){
return matConv.convertToMat(src).clone();
}
public synchronized static Mat toMat(BufferedImage src){
return matConv.convertToMat(biConv.convert(src)).clone();
}
public synchronized static Frame toFrame(IplImage src){
return iplConv.convert(src).clone();
}
public synchronized static Frame toFrame(Mat src){
return matConv.convert(src).clone();
}
public synchronized static Frame toFrame(BufferedImage src){
return biConv.convert(src).clone();
}
}
原文地址:https://my.oschina.net/yifanxiang/blog/3084480
最近在研究使用opencv对普通图片进行扣章的功能,在python上实现了,然后想使用在java上,java在选择jar包时选择了javacv(当然还有更原生的opencv,但由于考虑到后面可能会用到ffmpeg所以还是使用javacv) 到javacv的官网(http://bytedeco.org)上看了下,果然很强大,很多其它的包也有比如:numpy,tensorflow等python中使用到的库。 我是在javacv的sample中找到的相关方法。
/**
* BufferImage转byte[]
* @param original
* @return
*/
public static byte[] bufImg2Bytes(BufferedImage original){
ByteArrayOutputStream bStream = new ByteArrayOutputStream();
try {
ImageIO.write(original, "png", bStream);
} catch (IOException e) {
throw new RuntimeException("bugImg读取失败:"+e.getMessage(),e);
}
return bStream.toByteArray();
}
/**
* byte[]转BufferImage
* @param imgBytes
* @return
*/
public static BufferedImage bytes2bufImg(byte[] imgBytes){
BufferedImage tagImg = null;
try {
tagImg = ImageIO.read(new ByteArrayInputStream(imgBytes));
return tagImg;
} catch (IOException e) {
throw new RuntimeException("bugImg写入失败:"+e.getMessage(),e);
}
}
/**
* BufferedImage 转 mat
* 参考https://github.com/bytedeco/javacv-examples/blob/master/OpenCV_Cookbook/src/main/scala/opencv_cookbook/OpenCVUtils.scala
* @param original
* @return
*/
public static Mat bufImg2Mat (BufferedImage original) {
OpenCVFrameConverter.ToMat openCVConverter = new OpenCVFrameConverter.ToMat();
Java2DFrameConverter java2DConverter = new Java2DFrameConverter();
Mat mat= openCVConverter.convert(java2DConverter.convert(original));
return mat;
}
/**
* mat转BufferedImage
* 参考https://github.com/bytedeco/javacv-examples/blob/master/OpenCV_Cookbook/src/main/scala/opencv_cookbook/OpenCVUtils.scala
* @param matrix
* @return
*/
public static BufferedImage mat2BufImg (Mat matrix) {
Mat tempMat=new Mat();
cvtColor(matrix,tempMat,COLOR_BGRA2RGBA);//先要转bgra->rgba
OpenCVFrameConverter.ToMat openCVConverter = new OpenCVFrameConverter.ToMat();
Java2DFrameConverter java2DConverter = new Java2DFrameConverter();
return java2DConverter.convert(openCVConverter.convert(tempMat));
}
需要说明的opencv中的默认读取的颜色是bgr不是rgb,所以在mat转BufferImage时需要先cvtColor转换一下。
还有更简单的:Java2DFrameUtils 这个类,封装好了。
在使用中发现问题如果BufferedImage为4通道时转Mat会有问题要单独处理,Mat转BufferedImage颜色为蓝色时会有问题建议imwrite后直接用java读
BufferedImage为4通道时是ARGB