目的:在页面中嵌入Applet使用opencv调用摄像头,并在applet中显示实时视频中的内容。
软件:opencv.2.4.9
jdk:jdk1.8_0_91
浏览器:IE、火狐
相关技术要点:
1、配置客户端的jdk权限,在jre的lib包目录下java.policy文件中配置需要使用到的权限,在文件最后加上以下内容:
permission java.util.PropertyPermission "java.class.path", "read";
permission java.util.PropertyPermission "sun.arch.data.model", "read";
permission java.util.PropertyPermission "file.encoding","read";
permission java.lang.RuntimePermission "loadLibrary.D:/opencv/build/java/x86/opencv_java249.dll","read"; // 32位jdk
permission java.lang.RuntimePermission "loadLibrary.D:/opencv/build/java/x64/opencv_java249.dll","read"; // 64位jdk
2、在applet添加2个按钮控件,并且添加上【开始】、【停止】的点击事件。在进行开始时启动摄像头并且运行,在停止时关闭摄像头。注意,点击事件时,如果事件没有结束,那么其他的按钮事件是无法同时响应的,所以需要使用多线程的技术进行处理。
3、在opencv中把获取到的mat转换成为bufferedImage对象,使用applet的graphics对象在applet进行渲染。
好了,废话少说,直接上代码:
package test.applet;
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import javax.swing.JButton;
import org.opencv.core.Mat;
import org.opencv.highgui.VideoCapture;
import tools.ImageUtils;
public class TestOpencvApplet extends Applet {
static boolean isStart = true;
static boolean isFristStart = true;
/*
* (non-Javadoc)
*
* @see java.awt.Container#paint(java.awt.Graphics) 每一次切入页面时,都会被调用的该方法
*/
@Override
public void paint(Graphics g) {
super.paint(g);
System.out.println("this is paint start..."+TestOpencvApplet.isStart);
System.out.println("this is paint end...");
}
@Override
public void init() {
super.init();
this.setLayout(null);
this.setSize(640,480);
//
JButton btnStart = new JButton("开始");
btnStart.setBounds(300, 430, 80, 40);
btnStart.addMouseListener(new btnListener(this, true));
this.add(btnStart);
JButton btnStop = new JButton("停止");
btnStop.setBounds(400, 430, 80, 40);
btnStop.addMouseListener(new btnListener(this, false));
this.add(btnStop);
//
System.out.println(" load library x86 start...");
// 32位版本的dll,
//String opencv249so = "D:/opencv/build/java/x86/opencv_java249.dll";
String dataModel = System.getProperty("sun.arch.data.model"); // 32还是64位
if("32".equals(dataModel)){
System.load("D:/opencv/build/java/x86/opencv_java249.dll");
}else{
System.load("D:/opencv/build/java/x64/opencv_java249.dll");
}
System.out.println(" load library end ...");
System.out.println("this is init");
}
@Override
public void destroy() {
super.destroy();
System.out.println("this is destroy");
}
@Override
public void start() {
super.start();
System.out.println("this is start");
}
public void startCamera() {
try {
VideoCapture vc = new VideoCapture();
//
System.out.println("start..capture");
//
vc.open(0);
Graphics g = this.getGraphics();
for (int i = 1; i <= 1000 && isStart ; i++) {
Mat mat = new Mat();
vc.retrieve(mat);
BufferedImage image = ImageUtils.Mat2BufferedImage(mat);
g.drawImage(image,10,10,400,400,this);
if(i%100 == 0){
System.out.println("i="+i);
}
//Thread.sleep(1000);
// save
// 坑人的地方是第一个参数是height,第二个参数是width
// Mat newMat = Mat.eye(mat.height(),mat.width(),mat.type());
// Mat newMat = new Mat();
// newMat.put(0, 0, b);
// byte[] b2 = new byte[len];
// newMat.get(0, 0, b2);
// System.out.println("newMat.channels()="+newMat.channels()+":"+newMat.type()+":"+newMat.depth());
//
}
g.dispose();
vc.release();
} catch (Exception err) {
err.printStackTrace();
}
}
@Override
public void stop() {
// TODO Auto-generated method stub
super.stop();
isStart = false;
System.out.println("this is stop");
}
}
class btnListener implements MouseListener,Runnable{
TestOpencvApplet applet ;
boolean isStartBtn;
boolean isBusy = false;
public btnListener(TestOpencvApplet applet,boolean isStartBtn) {
this.applet = applet;
this.isStartBtn = isStartBtn;
}
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent e) {
System.out.println("action start? "+isStartBtn+":"+isBusy);
TestOpencvApplet.isStart = isStartBtn;
System.out.println(System.getProperty("java.class.path"));
// 同一时间只允许一个任务
if(isStartBtn){
if(isBusy){
}else{
isBusy = true;
// 使用多线程进行,否则会等待方法结束才能响应下一次的按钮事件
Thread t = new Thread(this);
t.start();
}
}
}
@Override
public void run() {
System.out.println("this is run...");
applet.startCamera();
isBusy = false;
}
@Override
public void mouseReleased(MouseEvent e) {
}
}
另外一个工具类代码:
package tools;
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.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.highgui.Highgui;
public class ImageUtils {
/**
* @description 把BufferedImage转换成为opencv的mat
* @param in
* @return
*
* public static Mat img2Mat(BufferedImage in){ Mat out; byte[]
* data; int r, g, b; int w = in.getWidth(), h = in.getHeight();
*
* out = new Mat(h, w, CvType.CV_8UC3); data = new byte[w * h *
* (int) out.elemSize()]; int[] dataBuff = in.getRGB(0, 0, w, h,
* null, 0, w); for (int i = 0; i < dataBuff.length; i++) { data[i *
* 3] = (byte) ((dataBuff[i] >> 0) & 0xFF); data[i * 3 + 1] = (byte)
* ((dataBuff[i] >> 8) & 0xFF); data[i * 3 + 2] = (byte)
* ((dataBuff[i] >> 16) & 0xFF); } out.put(0, 0, data); return out;
* }
*/
public static Mat bufferedImage2Mat(BufferedImage in) {
BufferedImage image = new BufferedImage(in.getWidth(), in.getHeight(),
BufferedImage.TYPE_3BYTE_BGR);
// Draw the image onto the new buffer
Graphics2D g = image.createGraphics();
try {
g.setComposite(AlphaComposite.Src);
g.drawImage(in, 0, 0, null);
} finally {
g.dispose();
}
byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer())
.getData();
Mat mat = Mat.eye(image.getHeight(), image.getWidth(), CvType.CV_8UC3);
mat.put(0, 0, pixels);
return mat;
}
public static BufferedImage Mat2BufferedImage(Mat image){
BufferedImage buf = null;
MatOfByte mob = new MatOfByte();
Highgui.imencode(".jpg", image, mob);
byte[] byteArray = mob.toArray();
InputStream in = new ByteArrayInputStream(byteArray);
try {
buf = ImageIO.read(in);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return buf;
}
}