之前写Java人脸识别爬虫的时候遇到的问题,最先的时候是用tempfile的形式去解决识别的问题,每个爬虫线程爬取图片到本地,保存为tempfile,而后opencv再读取出来作处理和识别,可是这样涉及磁盘io,爬虫性能异常缓慢,因此后面思考了一段时间琢磨出来再内存里面对图像进行转化,本质上,图像数据对Java来讲都是bytes[]串,因此个人转化过程的思路,就是把byte串取出来,从新组装。
opencv Mat转BufferImagejava
public static BufferedImage toBufferedImage(Mat matrix) { int type = BufferedImage.TYPE_BYTE_GRAY; if (matrix.channels() > 1) { type = BufferedImage.TYPE_3BYTE_BGR; } int bufferSize = matrix.channels() * matrix.cols() * matrix.rows(); byte[] buffer = new byte[bufferSize]; matrix.get(0, 0, buffer); // get all pixel from martix BufferedImage image = new BufferedImage(matrix.cols(), matrix.rows(), type); final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); System.arraycopy(buffer, 0, targetPixels, 0, buffer.length); return image; }
BufferImage转为opencv Mat数组
public static Mat bufferToMartix(BufferedImage image) { Mat mat = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3); byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); if (mat != null) { try { mat.put(0, 0, data); } catch (Exception e) { return null; } } return mat; }
byte数组转opencv Mat函数
public static Mat bufferToMartix(byte[] image) throws IOException { BufferedImage bImage = ImageIO.read(new ByteArrayInputStream(image)); byte[] bytes = ((DataBufferByte) bImage.getRaster().getDataBuffer()).getData(); Mat data = new Mat(bImage.getHeight(), bImage.getWidth(), CvType.CV_8UC3); data.put(0, 0, bytes); return data; }
有意思的是,当我让一个BufferedImage嵌套为性能
//这里假设b_image里面包含有图像数据 BufferedImage b_image=b_image=new BufferedImage(); Mat matrix=toBufferedImage(bufferToMartix(b_image))
的时候,JVM几率死掉报出Core Error,因而我分离了这两个函数避免嵌套使用,没有去深究这个问题,猜想这可能与JVM的GC(垃圾回收)有关系,并且就算不出现JVM致命错误,这样出来的图像也是有问题的,会缺失不少数据,而后变成一堆噪声和一片白,直观感受就是toBufferedImage调用结束后图像数据内存就被释放掉了,当bufferToMartix从后面执行的时候取了一样大小的内存区块当作图像,随机产生了JVM致命内存冲突,或者不冲突可是数据混乱的问题,由于不是专业Java这个地方还待研究。线程