公司最近开发一款定制化的人脸识别小程序,我也是第一次用分享在这里,分享给大家:
下面这段是实现人脸捕捉的关键代码:
public static String openCapture() {
String responseResult = null;
try {
// 加载本地的OpenCV库,这样就可以用它来调用Java API
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// 读取视频文件
VideoCapture capture = new VideoCapture(0);
int height = (int) capture.get(Videoio.CAP_PROP_FRAME_HEIGHT);
int width = (int) capture.get(Videoio.CAP_PROP_FRAME_WIDTH);
if (height == 0 || width == 0) {
throw new Exception("camera not found!");
}
JFrame frame = new JFrame("camera");
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
FaceCollection panel = new FaceCollection();
frame.setContentPane(panel);
frame.setVisible(true);
frame.setSize(width + frame.getInsets().left + frame.getInsets().right,
height + frame.getInsets().top + frame.getInsets().bottom);
Mat capImg = new Mat();
Mat temp = new Mat();
while (frame.isShowing()) {
capture.read(capImg);
// 图像灰度化
Imgproc.cvtColor(capImg, temp, Imgproc.COLOR_BGRA2BGR);// 彩色COLOR_BGRA2BGR 灰色COLOR_RGB2GRAY
// 捕捉人脸
FaceDetectDto faceDetectDto = panel.detectFace(capImg);
// 图像显示
panel.setmImg(panel.mat2BI(faceDetectDto.getMat()));
// 清除重绘
panel.repaint();
// 捕捉到人脸退出捕捉
if (faceDetectDto.isFaceFlag()) {
break;
}
}
// 写入本地文件
String fileName = ConfigUtil.getPropValue("path") + DateUtils.getDate("yyyyMMdd") + System.currentTimeMillis() + ".jpg";
File file = new File(fileName);
if (!file.getParentFile().exists()) {
boolean result = file.getParentFile().mkdirs();
if (!result) {
System.out.println("创建下载文件路径失败!");
}
}
Imgcodecs.imwrite(fileName, temp);
MatOfByte mob = new MatOfByte();//Mat类型转换为二进制数组
Imgcodecs.imencode(".jpg", temp, mob);//这里可以指定 图片的格式
byte[] byteArray = mob.toArray();
//这里使用了base64,很多第三方的人脸识别的接口都用的Base64处理后的
String encode = Base64Util.encode(byteArray);
//这里的敏感信息我就处理掉了
String userInfo = getUserInfo(encode, "敏感信息", "敏感信息", 1, 80);
//后面是一些业务处理逻辑
Map result = (Map) JSON.parse(userInfo);
Map map=new HashMap();
String userInfoList = String.valueOf(result.get("userInfoList"));
if (!userInfoList.equals("[]")) {
Map partonInfo= (Map) JSON.parseArray(userInfoList).get(0);
BigDecimal scope = (BigDecimal) partonInfo.get("scope");
if (scope.doubleValue()<80.00){
responseResult=JSON.toJSONString(ResponseUtil.responseFail(0,"未查询到此人,请确认"));
}else{
map.put("partonNum",partonInfo.get("partonNum"));
map.put("type", ThreeBackTypesEnum.BARCODE_ID.getCode());
responseResult = JSON.toJSONString(ResponseUtil.responseSuccess(0, "操作成功",map));
}
}
Thread.sleep(1000 * 2); // 睡眠2秒
// 关闭视频文件
capture.release();
frame.dispose();
} catch (Exception e) {
e.printStackTrace();
}
return responseResult;
}
下面这段是实现人脸识别捕捉的代码
/**
* opencv实现人脸识别
*
* @param img
*/
public FaceDetectDto detectFace(Mat img) throws Exception {
FaceDetectDto faceDetectDto = new FaceDetectDto();
// String pathName = getHaarcascade();
// 人脸特征分类
String faceXml = StringUtils.join("config/", "haarcascade_frontalface_alt.xml");
// 眼睛特征分类
String eyeXml = StringUtils.join("config/", "haarcascade_eye.xml");
// 嘴巴特征分类
// String mouthXml = StringUtils.join("config/", "haarcascade_mcs_mouth.xml");
// 从配置文件lbpcascade_frontalface.xml中创建一个人脸识别器
CascadeClassifier faceDetector = new CascadeClassifier(faceXml);
CascadeClassifier eyeDetector = new CascadeClassifier(eyeXml);
// 在图片中检测人脸
MatOfRect faceDetections = new MatOfRect();
faceDetector.detectMultiScale(img, faceDetections);
Rect[] faceRects = faceDetections.toArray();
// 只需要捕捉一张人脸
if (faceRects != null && faceRects.length == 1) {
Rect faceRect = faceRects[0];
// 绘制矩形
Imgproc.rectangle(img, new Point(faceRect.x, faceRect.y),
new Point(faceRect.x + faceRect.width, faceRect.y + faceRect.height),
new Scalar(0, 0, 255), 2);
//绘制圆形。
//Imgproc.ellipse(frame, center, Size( faces[i].width/2, faces[i].height/2 ), 0, 0, 360, Scalar( 255, 0, 255 ), 4, 8, 0 );
// 保证人脸头像大小
if (faceRect.width > 260 && faceRect.height > 260) {
// Mat face = new Mat(img, new Range(rect.y, rect.y + rect.height), new Range(rect.x, rect.x + rect.width));
Mat faceMat = new Mat(img, faceRect);
// 在图片中检测眼睛
MatOfRect eyeDetections = new MatOfRect();
eyeDetector.detectMultiScale(faceMat, eyeDetections);
Rect[] eyeRects = eyeDetections.toArray();
if (null != eyeRects && eyeRects.length >= 2) {
for (Rect eyeRect : eyeRects) {
// 需要加上人脸框的坐标
Imgproc.rectangle(img, new Point(faceRect.x + eyeRect.x, faceRect.y + eyeRect.y),
new Point(faceRect.x + eyeRect.x + eyeRect.width, faceRect.y + eyeRect.y + eyeRect.height),
new Scalar(0, 0, 255), 2);
}
faceDetectDto.setFaceFlag(true);
}
}
}
// else {
// System.out.println("未检测到人脸或超过一张人脸!!!");
// }
faceDetectDto.setMat(img);
return faceDetectDto;
}
为了代码的完整性我将调用三方得到的信息的代码也放上来了,你可以根据自己的业务需求,进行更改。
/**
* 调用三方的到信息
*
* @return
*/
public static String getUserInfo(String image, String dbid, String deviceid, Integer user_top_num, Integer score) throws IOException {
String address = ConfigUtil.getPropValue("address");
String post = HttpUtil.readContentFromPost(address, image);
System.out.println(post);
return post;
}
图像显示
private BufferedImage mImg;
public BufferedImage getmImg() {
return mImg;
}
public void setmImg(BufferedImage mImg) {
this.mImg = mImg;
}
public BufferedImage mat2BI(Mat mat) {
int dataSize = mat.cols() * mat.rows() * (int) mat.elemSize();
byte[] data = new byte[dataSize];
mat.get(0, 0, data);
int type = mat.channels() == 1 ?
BufferedImage.TYPE_BYTE_GRAY : BufferedImage.TYPE_3BYTE_BGR;
if (type == BufferedImage.TYPE_3BYTE_BGR) {
for (int i = 0; i < dataSize; i += 3) {
byte blue = data[i + 0];
data[i + 0] = data[i + 2];
data[i + 2] = blue;
}
}
BufferedImage image = new BufferedImage(mat.cols(), mat.rows(), type);
image.getRaster().setDataElements(0, 0, mat.cols(), mat.rows(), data);
return image;
}
public void paintComponent(Graphics g) {
if (mImg != null) {
g.drawImage(mImg, 0, 0, mImg.getWidth(), mImg.getHeight(), this);
}
}