喜欢用OpenCV和Java的人往往会使用官网提供的OpenCV的包,OpenCV除了用于图像处理,本身也是一个优秀的数学库。而且对于Java而言,配置方便,编写容易,可扩展性也强。Java效率虽然低,但是核心计算部分仍然是C写的。
然而对于初学者来说,一个非常重要的函数——imshow(Mat m, string window)
在Java中被阉割掉了,这使我们观察图像输出时只能通过imwrite()
保存为图片后再查看,用起来非常不爽。因此,我动手自己实现了一个java类,实现了该函数以及waitKey(int time)
两个函数,主要使用了java的swing框架,以及obj的wait()和notify()函数实现waitKey(int time)
。其中,
函数名 | 参数 | 功能 |
---|---|---|
ImageGui(Mat m, String window) | 要显示的图像和窗口名 | 构造 |
ig.imshow() | 无 | 显示图片 |
ig.waitKey(int time); | 需要暂停的毫秒数 | 参数为0则阻塞线程且等待用户输入,不为0则等待指定毫秒数后继续运行,并返回键盘输入值 |
实现效果如下。
是不是和C++中的imshow()一样好用呢?
下面是源码。
1. ImageGui.java
package com.meng.highgui;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.python.modules.synchronize;
/**
* An Gui extention for opencv3.0 using Swing, which can't display images in java.
* @author Dechao
*
* Description:
*
* examples:
* System.loadLibrary("opencv_java300");
* Mat mat = Mat.eye(1000, 2000, CvType.CV_8UC3);
* String window_name = "mat"
* ImageGui ig = new ImageGui(mat,window_name);
* ig.imshow();
* ig.waitKey(0);
*
*/
public class ImageGui extends JPanel implements KeyListener {
public ImageGui(Mat m, String window) {
super();
init(m, window);
}
//Elements for paint.
private Mat mat;
private boolean firstPaint = true;
private BufferedImage out;
int type;
private String WINDOW = "";
private JFrame jframe = new JFrame();
byte[] data;
private void Mat2BufIm(){
mat.get(0, 0, data);
out.getRaster().setDataElements(0, 0, mat.cols(), mat.rows(), data);
}
private void init(Mat m,String window){
this.mat = m;
data = new byte[mat.cols() * mat.rows() * (int)mat.elemSize()];
WINDOW = window;
if(mat.channels() == 1)
type = BufferedImage.TYPE_BYTE_GRAY;
else
type = BufferedImage.TYPE_3BYTE_BGR;
out = new BufferedImage(mat.cols(), mat.rows(), type);
Mat2BufIm();
jframe.add(this);
jframe.setSize(mat.cols(), mat.rows());
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.setTitle(WINDOW);
jframe.addKeyListener(this);
}
@Override
public void paintComponent(Graphics g) {
g.drawImage(out, 0, 0, null);
}
public void imshow(){
if(firstPaint){
jframe.setVisible(true);
firstPaint = false;
}
Mat2BufIm();
this.repaint();
}
//Elements for waitKey.
private static Object mt = new Object();
private static int lastKey = 0;
private static int key = 0;
public static int waitKey(int millisecond){
//TODO 实现监听键盘
try {
if(millisecond == 0){
synchronized(mt){
mt.wait();
}
}
Thread.sleep(millisecond);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int ret = -1;
if(key != lastKey){
ret = key;
lastKey = key;
}
return ret;
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
// System.out.println(e.getKeyChar() + ", " + e.getKeyCode()
// + ", " + KeyEvent.getKeyText(e.getKeyCode())
// + ", isActionKey: " + e.isActionKey());
synchronized(mt){
mt.notifyAll();
}
this.key = e.getKeyCode();
}
@Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}