2018.8.3 更新
opencv for java 3.40 已经带有显示Mat 图像的方法了。之前的版本没测试不知道。
昨天改完,今天就发现不需要了,真刺激。
代码:
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
public class Test2 {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat img = Imgcodecs.imread("./data/lena.jpg");
HighGui.imshow("窗口名称", img);
HighGui.waitKey(0);//按任意键关闭窗口
System.exit(0);//退出
}
}
2018.8.2 更新
发现显示的类显示图像不完整,更改了一下。
package utils;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.imgcodecs.Imgcodecs;
public class Images {
private JFrame frame;
private ImageIcon imageIcon;
private JLabel label;
public Images(int width, int height, String title) {
frame = new JFrame();
frame.setBounds(100,100,width,height);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle(title);
imageIcon = new ImageIcon();
label = new JLabel();
label.setIcon(imageIcon);
frame.getContentPane().add(label);
}
public void show(Mat mat) {
BufferedImage bImage = toBufferedImage(mat);
imageIcon.setImage(bImage);
frame.pack();
label.updateUI();
frame.setVisible(true);
}
public static void imshow(Mat mat, String title) {
Images gui = new Images(mat.width(), mat.height(),title);
gui.show(mat);
}
public static void imshow(Mat mat) {
imshow(mat, "");
}
public static void showImage(Mat mat) {
imshow(mat, "");
}
public static void showImage(Mat mat,String title) {
imshow(mat, title);
}
/**
* Mat 转成 BufferedImage
* @param source
* @return
*/
public static BufferedImage toBufferedImage(Mat source) {
// 顶一个字节数组矩阵
MatOfByte mob = new MatOfByte();
// 压缩数据到字节矩阵
Imgcodecs.imencode(".png", source, mob);
// 将矩阵转数组
byte[] byteArray = mob.toArray();
// 从数组构建一个输入流
InputStream input = new ByteArrayInputStream(byteArray);
// 从输入流中读取图像
try {
return ImageIO.read(input);
} catch (IOException e) {
return null;
}
}
}
OpenCV 是以 BGR 的顺序来表示图片的,而 Java的BufferedImage则是用RGB,所以用Swing 组件显示的时候会有问题。
但是如果只是通过转换B通道和G道的位置,那么转换成HSV或者别的格式的时候,显示的图片就可能不是本来的样子。
所以这里先将Mat转成流,再以流的形式输出到 BufferedImage。
代码:
public static BufferedImage toBufferedImage(Mat source) {
// 顶一个字节数组矩阵
MatOfByte mob = new MatOfByte();
// 压缩数据到字节矩阵
Imgcodecs.imencode(".png", source, mob);
// 将矩阵转数组
byte[] byteArray = mob.toArray();
// 从数组构建一个输入流
InputStream input = new ByteArrayInputStream(byteArray);
// 从输入流中读取图像
try {
return ImageIO.read(input);
} catch (IOException e) {
return null;
}
}
完整显示图片的工具类:
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.imgcodecs.Imgcodecs;
public class Images {
public static BufferedImage toBufferedImage(Mat source) {
// 顶一个字节数组矩阵
MatOfByte mob = new MatOfByte();
// 压缩数据到字节矩阵
Imgcodecs.imencode(".png", source, mob);
// 将矩阵转数组
byte[] byteArray = mob.toArray();
// 从数组构建一个输入流
InputStream input = new ByteArrayInputStream(byteArray);
// 从输入流中读取图像
try {
return ImageIO.read(input);
} catch (IOException e) {
return null;
}
}
/**
* 显示图片
* @param mat 要显示的 Mat图像
* @param str 窗口的名字
*/
public static void showImage(Mat mat, String str){
Windows.showWindow(toBufferedImage(mat), str);
}
/**
* 重载,懒得想窗口名的时候用
* @param mat
*/
public static void showImage(Mat mat){
Windows.showWindow(toBufferedImage(mat), null);
}
}
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Windows {
public static void showWindow(BufferedImage image, String str){
if(str==null){
str = "";
}
JFrame frame = new JFrame(str);
frame.setBounds(100,100,image.getWidth(),image.getHeight());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
frame.setVisible(true);
JLabel label = new JLabel();
label.setBounds(0,0,image.getWidth(),image.getHeight());
frame.getContentPane().add(label);
label.setIcon(new ImageIcon(image));
}
}