Java opencv把mat还原成图片

您所在的位置:网站首页 opencv把矩阵转化为图像 Java opencv把mat还原成图片

Java opencv把mat还原成图片

2023-09-30 15:44| 来源: 网络整理| 查看: 265

背景:代码的原理是opencv连接摄像头,捕获到帧数据mat(矩阵),将其转成byte数组然后进行base64编码,把数据与帧的其他信息(宽、高、通道数、时间戳)写入到json对象中,Kafka把json对象以字符串是方式发送出去;消费者(接收方)是ceph集群,拿到json对象后从中提取出帧的编码数据,作为对象内容存进去。要播放视频,就要把数据读出来,然后还原。

1.遇到的问题及解决思路

从ceph读取数据的方法已经掌握了,现在问题是还原。为了运行方便,我在生产者获取数据之后做了一些实验,尝试把帧的数据还原成图片。获取的数据主要是下面两行,mat是opencv的一种类,是帧的矩阵形式,可以转化成byte[],可以再对数组编码。

//创建一个与该帧一样大的byte数组 byte[] data = new byte[(int) (mat.total() * mat.channels())]; //把数组进行base64编码,然后添加到一个json对象obj中 obj.addProperty("data", Base64.getEncoder().encodeToString(data));

而普通的Java读取和还原图片,是以IO流的方式进行的,如我们的小文件存储部分,对于图片可以用Java的FileInput(Output)Stream或者ByteArrayInputStream+ImageIO.read/write方法完成。 但是经过一系列测试,发现上述两种方法不能还原从摄像头来的帧数据。 如果用FileOutputStream,确实可以得到一个图片文件,但是打不开。 在这里插入图片描述 在这里插入图片描述

如果用ByteArrayInputStream+ImageIO.read/write,会报错image= null,在调试过程中发现bufferedImage 没有收到数据,image的内容是空的,所以后面ImageIO.write()无法生成图片。其根本原因是ImageIO.read()可读取的图片类型是有限制的,可以读取图片的格式为:[BMP, bmp, jpg, JPG, wbmp, jpeg, png, PNG, JPEG, WBMP, GIF, gif],也就是它要读的in这个数据,来源得是上述格式图片转化而来的,这样才能再还原回去。

而视频流数据和普通的图片类型文件转化得到的数据是有差别的,所以Java自带的ImageIO不能还原。还原方法应该是用opencv的函数。我曾用python opencv把视频解析成帧,用到的一些类和函数和现在的比较接近,核心是

ret,frame=videocapture.read(), cv2.imwrite(jpg,frame),

搞清楚这里 frame和Java代码里mat的关系以及videocapture.read()的返回值,应该可以解决问题。我以前还用Java opencv连接到了笔记本摄像头并直播画面,主要用的是opencv的jframe类,用它应该也能还原。应该第一种方法更好。 在这里插入图片描述

2.mat还原成图片

opencv里的imwrite()方法用于将图像保存到指定的文件,可以为各种格式的图像,有三个参数:

第一个参数const String& filename表示需要写入的文件名,必须要加上后缀,比如“123.jpg”;第二个参数InputArray img(C++)表示Mat类型的图像数据,经过实验,JAVA API里用mat;第三个参数const std::vector& params表示为特定格式保存的参数编码,它有一个默认值std::vector< int >(),所以一般情况下不用写,如果更改的话,对于不同的图片格式,其对应的值不同功能不同。

我们只需要使用前两个参数。使用方法为:imwrite("*.jpg",frame);//将摄像头获取的图像帧frame保存到一个jpg图片,这里的frame是帧的原始数据mat。java源码如下:

public static boolean imwrite(String filename, Mat img) { return imwrite_1(filename, img.nativeObj); }

由mat还原图片demo:

import org.opencv.core.*; import org.opencv.imgcodecs.*; import org.opencv.imgproc.Imgproc; public class ReadAndWrite { public static void main(String[] args) { //加载opencv System.loadLibrary(Core.NATIVE_LIBRARY_NAME); String src = "d:/Java/opencv/example.jpg"; //读取图像 Mat srcImage = Imgcodecs.imread(src); //读取灰度图像 srcImage = Imgcodecs.imread(src, Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE); Mat dstImage = srcImage.clone(); //保存图像 Imgcodecs.imwrite("d:/Java/opencv/example_write.jpg", dstImage); } }

在kafka生产者代码里,收取到一帧的mat后,用上面的方法进行还原,成功生成了图片,摄像头的画面。 在这里插入图片描述 上面的mat是生产者发送前的mat,而消费者接收到的是base64的string数组,所以在ceph里应该读出编码的字符串,解码,转成byte[],然后用这个数组创建一个mat对象,在用这个mat还原成图片。 在操作过程中,最后两行有问题,推测原因是新建的mat容量不够或者说与图片大小不一致,要用Imgproc.resize()方法设置它的大小,只要设置正确,后面Imgcodecs.imwrite()就能生成图片。

//用生产者那边的mat还原图片 Imgcodecs.imwrite("H:\\example_write.jpg", mat); // byte[] data2 = data; Mat mat2 = new Mat(); //有下面这行可以正确运行出来 // Imgproc.resize(mat2, mat2, new Size(1080, 720), 0, 0, Imgproc.INTER_CUBIC); mat2.put(0, 0, data); Imgcodecs.imwrite("H:\\example_write222.jpg", mat2);

代码目前的问题是,mat与mat2(新建的,消费者那边的)不完全一样,就生成不了。 在这里插入图片描述 如果Imgproc.resize(mat2, mat2, new Size(1080, 720), 0, 0, Imgproc.INTER_CUBIC);这行,把第一个mat2改成mat,如下图,就没问题。因此我推测是mat2大小跟数组不匹配导致的。 在这里插入图片描述

3.解决方法

前面遇到的问题是从mat还原图片时候,如果用Imgproc.resize(mat2, mat2, new Size(1080, 720), 0, 0, Imgproc.INTER_CUBIC)修改mat的大小,会发现mat2的各种成员变量有问题,最后无法还原。 最终发现不必修改大小,在消费者端创建mat2时候就能指定它的各种参数,如大小,CV_TYPE等。这样就可以还原了。

后来过了很久我又发现了一种mat还原图片的方法,opencv的mat是可以转换成Java的BufferedImage的,用Java的方法再生成图片。这种方法的好处了可以跨语言传数据,比如我是Java opencv获取到的数据,要传给python opencv使用,就可以这么做。

/** * 将Mat类型转化成BufferedImage类型 * * @param amatrix Mat对象 * @param fileExtension 文件扩展名 * @return */ public static BufferedImage Mat2Img(Mat mat, String fileExtension) { MatOfByte mob = new MatOfByte(); Highgui.imencode(fileExtension, mat, mob); // convert the "matrix of bytes" into a byte array byte[] byteArray = mob.toArray(); BufferedImage bufImage = null; try { InputStream in = new ByteArrayInputStream(byteArray); bufImage = ImageIO.read(in); } catch (Exception e) { e.printStackTrace(); } return bufImage; }

参考博客: https://blog.csdn.net/u013092293/article/details/53538138 https://blog.csdn.net/tryflys/article/details/78906157



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3