java實現base64及圖片路徑轉換mat的方法

最近項目中涉及到了圖像算法識別,涉及到傳遞mat,於是就有了這樣的一篇博客

由於對外接口要求對方提供的是base64編碼的jpg圖像數據,但是算法需要的是Mat類型的數據,這樣就需要引入opencv_java來實現這樣的轉換。
實際上整個過程就需要幾個步驟:
1.實現base64的解碼;
2.將解碼後的數據轉換爲BufferedImage;
3.將BufferedImage轉換爲Mat類型數據;

前兩步都很好實現,難點在第三步上,我們就具體講講第三步的實現

1.首先,maven項目引入幾個pom依賴:

		<dependency>
			<groupId>org.bytedeco</groupId>
			<artifactId>javacv</artifactId>
			<version>1.4.4</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.bytedeco/javacpp -->
		<dependency>
			<groupId>org.bytedeco</groupId>
			<artifactId>javacpp</artifactId>
			<version>1.4.4</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/opencv/opencv -->
		<dependency>
			<groupId>opencv</groupId>
			<artifactId>opencv</artifactId>
			<version>1.1.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.bytedeco.javacpp-presets/opencv -->
		<!-- <dependency> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>opencv</artifactId> 
			<version>4.0.1-1.4.4</version> </dependency> -->
		<dependency>
			<groupId>org.bytedeco.javacpp-presets</groupId>
			<artifactId>opencv</artifactId>
			<version>2.4.11-0.11</version>
		</dependency>
		<!-- 需要自己安裝配置opencv -->
		<dependency>
			<groupId>org</groupId>
			<artifactId>opencv</artifactId>
			<version>2413</version>
		</dependency>

除最後一個pom依賴外,其餘的應該都能夠從maven倉庫中下載得到。
那我們就來講下如何獲得最後一個maven依賴。
1.1)首先,我們來到opencv的官網:https://opencv.org/releases.html
選擇自己需要下載的平臺及版本,因爲要和公司算法做兼容,所以我選用的是2.4.13版本,window下安裝配置極其簡單,將下載得到的.exe文件解壓縮,然後將到opencv\build\java下即可得到需要的jar包,再然後將jar包轉換爲maven庫裏的依賴就可以了。
具體命令我就不放在這了,拿一個通用的模板命令掛在這,按自己實際去轉換吧。

mvn install:install-file -Dfile=XX.jar -DgroupId=org -DartifactId=opencv -Dversion=2413 -Dpackaging=jar

1.2)引入了pom依賴之後,windows下還需要opencv\build\java
下需要的opencv的dll文件,將86(32位系統)或64(64位系統)下的
opencv_java2413.dll文件引入到系統的jdk的bin目錄下
1.3)上邊的是windows的例子,實際很多情況下代碼是在GPU的linux服務器上運行的,那麼就需要下載linux平臺下的文件,在服務器上使用Cmake編譯安裝,安裝之後得到的會是.so文件,將對應的.so文件移入到/usr/lib下即可。
如果不移動就需要將將.so文件的具體路徑放入到/etc/profile配置文件中,然後使用source命令更新系統配置。

準備工作都做完了,剩下的就是代碼了

首先,需要從系統的環境中加載需要的opencv文件
static {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
}
其次,就是代碼的具體實現了,包含了BufferedImage與mat(2413不支持mat轉BufferedImage,但是4.0.1版本支持,具體的各位自己去探索吧)數據的互轉及轉opencv的rect方法。
【注】代碼是按照.jpg處理的,需要變更的東西還是各位按需求自定義吧。

import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;

import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Rect;

import sun.misc.BASE64Decoder;

public class Java2MatTools {
/**
	 * 加載文件 opencv_java401.dll(windows)/libopencv_java401.so文件
	 * (windows將文件放到jdk的bin目錄下;linux爲了簡單起見可以放到/usr/lib下面)
	 */
	static {
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
	}
	/**
	 * 路徑圖片轉爲base64
	 * 
	 * @param imagePath
	 * @return
	 * @throws IOException
	 */
	public static Mat imagePath2Mat(String imagePath) throws IOException {
		// 註釋部分模擬傳入base64數據
		BufferedImage image = ImageIO.read(new FileInputStream(imagePath));
		Mat matImage = Java2MatTools.BufImg2Mat(image, BufferedImage.TYPE_3BYTE_BGR, CvType.CV_8UC3);// CvType.CV_8UC3
		// 小型圖片可以輸出 查看下
//		System.out.println(matImage.dump());
//		mat = matImage.dump();
		return matImage;
	}
	/**
	 * base64轉Mat
	 * 
	 * @param base64
	 * @return
	 * @throws IOException
	 */
	public static Mat base642Mat(String base64) throws IOException {
		// 對base64進行解碼
		BASE64Decoder decoder = new BASE64Decoder();
		byte[] origin = decoder.decodeBuffer(base64);
		InputStream in = new ByteArrayInputStream(origin); // 將b作爲輸入流;
		BufferedImage image = ImageIO.read(in);
		Mat matImage = Java2MatTools.BufImg2Mat(image, BufferedImage.TYPE_3BYTE_BGR, CvType.CV_8UC3);// CvType.CV_8UC3
		return matImage;
	}
	/**
	 * 
	 * @param base64
	 * @throws IOException 
	 */
	public static Rect base642Rect(String base64) throws IOException {
		BASE64Decoder decoder = new BASE64Decoder();
		byte[] origin = decoder.decodeBuffer(base64);
		InputStream in = new ByteArrayInputStream(origin); // 將b作爲輸入流;
		BufferedImage image = ImageIO.read(in);
		return new Rect(0,0,image.getWidth(),image.getHeight());
	}
	
	/**
	 * 
	 * @param base64
	 * @throws IOException 
	 */
	public static Rect BufferedImage2Rect(BufferedImage image) throws IOException {
		return new Rect(0,0,image.getWidth(),image.getHeight());
	}
	/**
	 * 
	 * @param base64
	 * @throws IOException 
	 */
	public static BufferedImage base642BufferedImage(String base64) throws IOException {
		BASE64Decoder decoder = new BASE64Decoder();
		byte[] origin = decoder.decodeBuffer(base64);
		InputStream in = new ByteArrayInputStream(origin); // 將b作爲輸入流;
		return ImageIO.read(in);
	}

	/**
	 * BufferedImage轉換成Mat
	 * 
	 * @param original 要轉換的BufferedImage
	 * @param imgType  bufferedImage的類型 如 BufferedImage.TYPE_3BYTE_BGR
	 * @param matType  轉換成mat的type 如 CvType.CV_8UC3
	 */
	public static Mat BufImg2Mat(BufferedImage original, int imgType, int matType) {
		if (original == null) {
			throw new IllegalArgumentException("original == null");
		}

		// Don't convert if it already has correct type
		if (original.getType() != imgType) {

			// Create a buffered image
			BufferedImage image = new BufferedImage(original.getWidth(), original.getHeight(), imgType);

			// Draw the image onto the new buffer
			Graphics2D g = image.createGraphics();
			try {
				g.setComposite(AlphaComposite.Src);
				g.drawImage(original, 0, 0, null);
			} finally {
				g.dispose();
			}
		}

		byte[] pixels = ((DataBufferByte) original.getRaster().getDataBuffer()).getData();
		Mat mat = Mat.eye(original.getHeight(), original.getWidth(), matType);
		mat.put(0, 0, pixels);
		return mat;
	}

	/**
	 * Mat轉換成BufferedImage
	 * 
	 * @param matrix        要轉換的Mat
	 * @param fileExtension 格式爲 ".jpg", ".png", etc
	 * @return
	 *//*
	public static BufferedImage Mat2BufImg(Mat matrix, String fileExtension) {
		// convert the matrix into a matrix of bytes appropriate for
		// this file extension
		MatOfByte mob = new MatOfByte();
		Imgcodecs.imencode(fileExtension, matrix, 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;
	}*/

	/**
	 * Mat轉換保存成Image
	 * 
	 * @param matrix        要轉換的Mat
	 * @param fileExtension 格式爲 ".jpg", ".png", etc
	 * 
	 * @return
	 */
/*	public static void Mat2Img(Mat matrix, String fileExtension, String pathAndName) {
		// convert the matrix into a matrix of bytes appropriate for
		// this file extension
		MatOfByte mob = new MatOfByte();
		Imgcodecs.imencode(fileExtension, matrix, 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);
			writeImageFile(bufImage, pathAndName);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}*/

	/**
	 * 將bufferdimage轉換爲圖片
	 * 
	 * @param bi
	 * @param pathAndName
	 * @throws IOException
	 */
	public static void writeImageFile(BufferedImage bi, String pathAndName) throws IOException {
		File outputfile = new File(pathAndName);
		ImageIO.write(bi, "jpg", outputfile);
	}

}

ok,完事。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章