javacv中byte[]、BufferImage、Mat的互转

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

猜你喜欢

转载自blog.csdn.net/jiduochou963/article/details/105097468