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());
}
}
}
}
}