在页面中嵌入Applet使用opencv调用摄像头,并显示实时摄像头内容

目的:在页面中嵌入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;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值