背景

OpenCV 提供的 API 是直接根据路径读取图片的, 在实际生产环境中,可能大部分情况下都是直接读取网络图片

在内存就完成图片和 opencv 的 Mat 对象的转换

那么该如何读取 byte[] 的图片呢?

API

openCV 提供的 API

Mat src = Imgcodecs.imread("/static/img/17.png");

很简单的就转化为 Mat 对象

而 该方法后面还有一个参数, flags, 该参数可选项有:

IMREAD_UNCHANGED = -1,

IMREAD_GRAYSCALE = 0,

IMREAD_COLOR = 1,

IMREAD_ANYDEPTH = 2,

IMREAD_ANYCOLOR = 4,

IMREAD_LOAD_GDAL = 8,

IMREAD_REDUCED_GRAYSCALE_2 = 16,

IMREAD_REDUCED_COLOR_2 = 17,

IMREAD_REDUCED_GRAYSCALE_4 = 32,

IMREAD_REDUCED_COLOR_4 = 33,

IMREAD_REDUCED_GRAYSCALE_8 = 64,

IMREAD_REDUCED_COLOR_8 = 65,

IMREAD_IGNORE_ORIENTATION = 128;

IMREAD_UNCHANGED: 以图片原有的方式读入,不进行任何改变

IMREAD_GRAYSCALE: 以灰度图读取

IMREAD_COLOR: 以彩色图读取

过渡

为了支持 OpenCV 读取 byte[] 的图片,为此我查找了很多资料做了大量的实验,有很多失败报错了,也有读取成功的,下面我将一一列举出来….

读取失败

Converters 类

我留意到 opencv 提供的 api 里有一个 utils 包, 里面有个转换类 Converters, 可以将 Mat 和 一些 java 的基本数据类型进行互相转换,其中有这样 2 个方法: vector_uchar_to_Mat 和 vector_char_to_Mat

参数是 List

private static Mat testConvertChar2Mat(byte[] bytes){

@SuppressWarnings("unchecked")

List bs = CollectionUtils.arrayToList(bytes);

return Converters.vector_uchar_to_Mat(bs);

// return Converters.vector_char_to_Mat(bs);

}

vector_uchar_to_Mat 指有符号

转换出来的图片是一个像素的竖直线,读取失败

new Mat

Mat 对象除了转化得到,还可以 new , 再利用 Mat 的 put 方法,来创建 Mat

private static Mat testNewMat(int height, int width, byte[] bytes) throws IOException {

Mat data = new Mat(height, width, CvType.CV_8UC3);

data.put(0, 0, bytes);

return data;

}

转换出来的图片也不对,一些花花绿绿的像素点

new BufferByte

Mat 对象还有个构造方法,最后一个参数是传入 BufferByte,这时只需要在上述步骤中再将 byte[] 转化为 BufferByte

private static Mat testNewBuffer(int height, int width, byte[] bytes){

ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);

return new Mat(height, width, CvType.CV_8UC3,byteBuffer);

}

抛出异常: CvException [org.opencv.core.CvException: cv::Exception: OpenCV(4.1.0-pre) /Users/joylau/opencv4/opencv/modules/core/include/opencv2/core/mat.inl.hpp:548: error: (-215:Assertion failed) total() == 0 || data != NULL in function ‘Mat’

读取成功

BufferedImage 转换

一次我在调试代码时 发现HighGui.waitKey(); 的实现是将 Mat 对象转化为 BufferedImage 的逻辑,于是我明白了,OpenCV 里操作的 Mat 在显示的时候也需要转化为 BufferedImage

源码里有这样一段代码

public static Image toBufferedImage(Mat m) {

int type = BufferedImage.TYPE_BYTE_GRAY;

if (m.channels() > 1) {

type = BufferedImage.TYPE_3BYTE_BGR;

}

int bufferSize = m.channels() * m.cols() * m.rows();

byte[] b = new byte[bufferSize];

m.get(0, 0, b); // get all the pixels

BufferedImage image = new BufferedImage(m.cols(), m.rows(), type);

final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();

System.arraycopy(b, 0, targetPixels, 0, b.length);

return image;

}

此时,我逆向转化,将 byte[] 转 BufferedImage ,BufferedImage 再转 Mat 即可

private static byte[] getBufferedImageByte(byte[] bytes) throws IOException{

BufferedImage bImage = ImageIO.read(new ByteArrayInputStream(bytes));

return ((DataBufferByte) bImage.getRaster().getDataBuffer()).getData();

}

// 再将从 BufferedImage 得到的 byte[] 使用 new Mat 对象

private static Mat testNewMat(int height, int width, byte[] bytes) throws IOException {

Mat data = new Mat(height, width, CvType.CV_8UC3);

data.put(0, 0, bytes);

return data;

}

该方法成功读取显示了图片

于是又引发了我的思考: 为什么直接从文件读取的 byte[] 无法被转化,而 BufferedImage 中得到的 byte[] 却可以被转化

于是我将 BufferedImage 中得到的 byte[] 在使用,调用 Converters.vector_char_to_Mat 方法

可惜却失败了…..

imdecode

Imgcodecs 类中有一个编码的方法 Imgcodecs.imdecode(Mat buf, int flags)

Mat 还有个子类 MatOfByte

private static Mat testImdecode(byte[] bytes){

return Imgcodecs.imdecode(new MatOfByte(bytes), Imgcodecs.IMREAD_COLOR);

}

该方法可成功转化

而且比上一个方法的优势是:

byte[] 不需要再通过 BufferedImage 转化

不需要初始化 Mat 的长和宽

为此还可以逆向得出 Mat 转换成 byte[] 的方法

/**

* Mat转换成byte数组

*

* @param matrix 要转换的Mat

* @param fileExtension 格式为 ".jpg", ".png", etc

*/

public static byte[] mat2Byte(Mat matrix, String fileExtension) {

MatOfByte mob = new MatOfByte();

Imgcodecs.imencode(fileExtension, matrix, mob);

return mob.toArray();

}

最后

以下是全部测试代码

/**

* Created by liuf on 2019-04-01.

* cn.joylau.code

* liuf@ahtsoft.com

*/

@Slf4j

public class Byte2Mat {

public static void main(String[] args) throws Exception {

System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

// Mat mat = testImdecode(getImageByte());

// Mat mat = testConvertChar2Mat(getBufferedImageByte(getImageByte()));

// Mat mat = testNewBuffer(480,480,getImageByte());

// Mat mat = testNewMat(480,480,getImageByte());

Mat mat = testNewMat(480,480,getBufferedImageByte(getImageByte()));

log.info("{},{}",mat.rows(),mat.cols());

HighGui.imshow("byte2mat",mat);

HighGui.waitKey();

HighGui.destroyAllWindows();

}

private static byte[] getImageByte() throws IOException{

Resource resource = new FileSystemResource("/Users/joylau/work/anhui-project/traffic-service-layer/src/main/resources/static/img/1.jpg");

return IOUtils.toByteArray(resource.getInputStream());

}

private static byte[] getBufferedImageByte(byte[] bytes) throws IOException{

BufferedImage bImage = ImageIO.read(new ByteArrayInputStream(bytes));

return ((DataBufferByte) bImage.getRaster().getDataBuffer()).getData();

}

private static Mat testNewMat(int height, int width, byte[] bytes) throws IOException {

Mat data = new Mat(height, width, CvType.CV_8UC3);

data.put(0, 0, bytes);

return data;

}

private static Mat testNewBuffer(int height, int width, byte[] bytes){

ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);

return new Mat(height, width, CvType.CV_8UC3,byteBuffer);

}

private static Mat testConvertChar2Mat(byte[] bytes){

@SuppressWarnings("unchecked")

List bs = CollectionUtils.arrayToList(bytes);

return Converters.vector_uchar_to_Mat(bs);

// return Converters.vector_char_to_Mat(bs);

}

private static Mat testImdecode(byte[] bytes){

return Imgcodecs.imdecode(new MatOfByte(bytes), Imgcodecs.IMREAD_COLOR);

}

/**

* Mat转换成byte数组

*

* @param matrix 要转换的Mat

* @param fileExtension 格式为 ".jpg", ".png", etc

*/

public static byte[] mat2Byte(Mat matrix, String fileExtension) {

MatOfByte mob = new MatOfByte();

Imgcodecs.imencode(fileExtension, matrix, mob);

return mob.toArray();

}

}

留言

java图片转换为数据流_OpenCV 读取数据流图片相关推荐

  1. python将图片转换为字符_python如何将图片转换为字符图片

    简介 一个简单的python程序,将图片转换为字符图片. (为了简便,很多参数写死了,自己看着改吧. (←∀←)) 正文 原图(侵删) 结果图 源码 [更多细节]-->戳这里 #-*- codi ...

  2. php获取服务器上的图片不显示,php 读取服务器图片

    php 读取服务器图片 内容精选 换一换 本文介绍如何将开源框架的网络模型,例如Caffe.TensorFlow等框架训练好的模型,通过OMG(Offline Model Generator:离线模型 ...

  3. Java 实现图片转换为ICO以及多种格式图片之间转换

    详细信息请访问我的GitHub网站:https://github.com/HuBoZhi/image4j

  4. linux 读取png图片大小,使用libpng读取PNG图片像素数据

    附录  让我们打开pnglib下面的一个example.c /* Read a PNG file. You may want to return an error code if the read * ...

  5. c#如何wmf图片转换成png图片_每日一学:如何将png图片转换为jpg图片

    背景 最近在工作中会遇到需要将 png 图片转换为 jpg 图片的需求,主要原因也是 png 图片占的空间太大,如果图片数量上万张,可能就需要十几G的存储空间,所以希望转换为更小的 jpg 图片. 当 ...

  6. Python图片转换为PDF

    Python图片转换为PDF 这是一个用于将图片转换为PDF文档的函数集,几乎所有的步骤的目的在代码中均有详细的注释,在此不做过多阐述. 点此返回笔记目录. # coding = UTF-8# 导入P ...

  7. python导入图片数据_Python中读取图片的6种方式

    Python进行图片处理,第一步就是读取图片,这里给大家整理了6种图片的读取方式,并将读取的图片装换成numpy.ndarray()格式.首先需要准备一张照片,假如你有女朋友的话,可以用女朋友的,没有 ...

  8. JAVA 将图片转换为Base64编码

    https://www.cnblogs.com/ywlx/p/4544179.html 这里使用的jar包是commons-codec-1.10.jar; import java.io.FileInp ...

  9. java 图片转成base64编码_java语言中如何将一个图片转换为base64编码的数据呢?

    摘要: 下文讲述java语言中将图片转换为base64编码的方法分享,如下所示: 例: /* file为图片文件对象 filePath为转换后base64的存储位置 */ public static ...

最新文章

  1. Re: Programming C/C++中extern C含义深层探索
  2. linux实时线程调度bug,linux中采用用户级线程模拟实现EDF和RMS两种处理机实时调度算法之改进...
  3. 【研究】Metasploit自动攻击模块
  4. 为什么软件测试需要变革?
  5. 伤钱伤感情 10件不能和亲戚一起干的事儿
  6. 三分钟掌握Go mod常用与高级操作
  7. 当下流行的语音识别技术是不是发展错了方向?
  8. Log4net创建日志及简单扩展
  9. 刘铁猛挨踢人感言:做一个高情商的程序员
  10. 汉王ocr sdk android,汉王标准印刷体OCR SDK技术白皮书.doc
  11. outlook配置126邮箱
  12. java毕业设计——基于Java+AI的五子棋游戏设计与实现(毕业论文+程序源码)——五子棋游戏
  13. Fallout 4 辐射4 技巧统计
  14. vue通过v-for取出的一个字段是时间戳格式转换成年月日
  15. C语言学习第7天(错误处理、递归、内存管理)默认熟悉数据结构和java基础
  16. SIM800c收发短信及AT指令
  17. Android原生开发--模拟器检测工具包
  18. 微信公众号开发(二)基础接口
  19. 手把手教你用python爬取人人贷网站借款人信息
  20. gba模拟器ios_GBA4iOS GBA模拟器

热门文章

  1. 【静态站点(三)】之 Gridsome + Strapi + Vercel + Pm2 部署案例
  2. 【HTML】如何在网页中屏蔽右键 ?
  3. win7上面的ie8和chrome90简直是两个时代的产物
  4. 文件从头开始读函数_如何从头开始编写自己的Promisify函数
  5. 组件和高阶组件区别_为什么要对高阶组件使用代码拆分
  6. php weize_docs.html
  7. 基于python的智能风扇设计_智能风扇设计毕业设计
  8. 小哥哥你有98K吗?利用Python制作一款多功能变声器!
  9. jQuery框架学习第五天:事件与事件对象
  10. scikit-learn中随机森林使用详解