1. 前言
近期有个人脸识别的需求,这里使用到的是OpenCV.推荐大家使用最新版本,貌似识别准确.但是由于服务器环境(jdk版本)限制,只能使用老版本才能兼容.这里以OpenCV 2.4.9
为例写一个demo.在jdk1.6环境上运行.
2. 配置环境
2.1 下载OpenCV
首先去官网下载OpenCV 2.4.9
,地址https://opencv.org/releases.html.
解压到C盘,目录为C:\opencv-2.4.9
.解压出来文件比较大,可以删除不必要的文件.
保留build/java
目录和sources/data
目录.
2.2 创建项目,添加依赖
- 创建项目
打开MyEclipse,新建一个项目opencv2
. - 添加依赖
右键选择Bulid Path
–>Add Libraries...
,弹出Add Library
窗口,选择User Library
,点击Next
,再选择右侧的User Libraries..
.按钮,然后New
一个,名字为OpenCV-2.4.9
.添加好之后,选中,再选择右侧的Add External JARs...
按钮添加C:\opencv-2.4.9\build\java
里面的opencv-249.jar
包.
之后打开jar包,选中Native library location
,点击右侧Edit
按钮进行编辑.
选择External Folder
,把C:\opencv-2.4.9\build\java\x86
(根据JDK版本确定,64位则选择x64文件夹).确定保存.
回到Add Library
窗口,选择刚刚添加的OpenCV-2.4.9
的User Library
保存.这样环境就配置好了.
3. 编写实现代码
实现类
import java.awt.Container; import java.awt.Frame; import java.awt.Graphics; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.File; import javax.imageio.ImageIO; import javax.swing.JLabel; import javax.swing.JPanel; import org.eclipse.swt.SWT; import org.eclipse.swt.awt.SWT_AWT; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.MatOfByte; import org.opencv.core.MatOfRect; import org.opencv.core.Point; import org.opencv.core.Rect; import org.opencv.core.Scalar; import org.opencv.core.Size; import org.opencv.highgui.Highgui; import org.opencv.highgui.VideoCapture; import org.opencv.imgproc.Imgproc; import org.opencv.objdetect.CascadeClassifier; public class Camera { private DaemonThread myThread = null; public Shell shell; private VideoCapture capture; private CascadeClassifier faceDetector; private JPanel panel; public Camera() { System.loadLibrary(Core.NATIVE_LIBRARY_NAME);//加载动态库 capture = new VideoCapture(0);//打开摄像头 String path = this.getClass().getResource("haarcascade_frontalface_alt2.xml").getPath();//跟Camera类在统一路径 path = new File(path).getAbsolutePath(); faceDetector = new CascadeClassifier(path); } // 摄像头显示模块 public void initComponents() { Display display = Display.getDefault(); shell = new Shell(display, SWT.EMBEDDED); shell.setBounds(0,0, 600, 400);//设置界面大小 Frame frame = SWT_AWT.new_Frame(shell); frame.setLayout(null); panel = new JPanel(); panel.setBounds((frame.getWidth() - 250) / 2, 10, 250, 300);//设置摄像头显示区域大小 frame.add(panel); //提示语 JLabel label = new JLabel("请把脸部对准摄像头,等待1-5秒"); label.setBounds((frame.getWidth() - 210) / 2, 320, 210, 30); frame.add(label); myThread = new DaemonThread(); Thread t = new Thread(myThread); myThread.runnable = true; t.start(); // start thrad shell.open(); while (!shell.isDisposed()) { while (!display.readAndDispatch()) { display.sleep(); } } t.interrupt(); } class DaemonThread implements Runnable { private Mat target = new Mat(); private Mat sub; private String path = "C:\\opencv-2.4.9\\pic\\";// 照片存储位置 protected volatile boolean runnable = false; private boolean isCollect = false; private int width, height; private Mat capImg; private MatOfByte mem; private MatOfRect faceDetections; public DaemonThread() { capImg = new Mat(); mem = new MatOfByte(); faceDetections = new MatOfRect(); } @Override public void run() { capture.set(3, 250);//摄像头分辨率,3-表示width capture.set(4, 300);//摄像头分辨率,4-表示height Graphics g = panel.getGraphics(); width = panel.getWidth(); height = panel.getHeight(); final Container parent = panel.getParent(); final JLabel label = (JLabel) parent.getComponent(1); while (runnable) { try { if (capture.grab()) { capture.retrieve(capImg); // Imgproc.cvtColor(capImg, capImg,Imgproc.COLOR_RGB2GRAY); //转变成灰色照片 //设置人脸识别参数,如果使用默认的可以直接写成 faceDetector.detectMultiScale(capImg, faceDetections); faceDetector.detectMultiScale(capImg, faceDetections, 1.2, 4, 0, new Size(80, 100), new Size(250, 300)); for (Rect rect : faceDetections.toArray()) { int h = rect.height, w = rect.width, x = rect.x, y = rect.y; if (!isCollect) { sub = capImg.submat(new Rect(x, y, w, h)); Imgproc.resize(sub, target, new Size(w, h));// 将人脸进行截图并保存 Display.getDefault().asyncExec(new Runnable() { public void run() { String photoName = path + System.nanoTime() + ".jpg"; Highgui.imwrite(photoName, target); label.setText("人脸信息已提取..."); isCollect = true;//只截取一张图 } }); } Core.rectangle(capImg, new Point(x, y), new Point(x + w, y + h), new Scalar(0, 255, 0), 2);//脸部区域 } } Highgui.imencode(".png", capImg, mem); Image im = ImageIO.read(new ByteArrayInputStream(mem.toArray())); BufferedImage buff = (BufferedImage) im; //把图像刷新到界面上 g.drawImage(buff, 0, 0, width, height, 50, 50, buff.getWidth() - 50, buff.getHeight() - 50, null); } catch (Exception ex) { System.out.println("Error:" + ex.getLocalizedMessage()); } } } } }