java實現opencv人臉識別(二)
Java下使用opencv進行人臉檢測
工作需要,研究下人臉識別,發現opencv比較常用,儘管能檢測人臉,但識別率不高,多數是用來獲取攝像頭的視訊流的,提取裡面的視訊幀,實現人臉識別時通常會和其他框架搭配使用,比如face_recognition、SeetaFace Engine、Facenet。不過這裡先簡單介紹下opencv在java下的使用(網上大多都是C++的demo,這裡是使用其java介面,還提供了python的介面)。
這裡簡單說下opencv(版本為340)的安裝
window下直接執行opencv-3.4.0-vc14_vc15.exe即可,java下用到的只有裡面的opencv-340.jar和opencv_java340.dll,官網下載或者直接下載java部分。
1、 將build\java\opencv-340.jar匯入到專案中,
2、 根據作業系統版本,將build\java\x64\opencv_java340.dll放在%JAVA_HONE%\bin下(這裡只要放在System.getProperty("java.library.path")下目錄即可)。
3、 在程式碼中使用System.loadLibrary(Core.NATIVE_LIBRARY_NAME);載入。
在sources\data下都是模型檔案,opencv使用這些xml建模(CascadeClassifier)分析人臉,這裡只用到haar下的正臉和人眼模型檔案。
下面的demo修改自網上的例子,原為單獨檢測人臉,發現會將只有鼻子的部分也識別為人臉,所以修改為使用兩個CascadeClassifier同時檢測人臉和人眼,同時存在才確認為人臉目標,提高準確率,不過識別的時間較原來的長。
Demo
package opencv;
import org.opencv.core.*;
import org.opencv.core.Point;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.videoio.VideoCapture;
import org.opencv.videoio.Videoio;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Random;
public class MyDemo extends JPanel {
private BufferedImage mImg;
/**
* 轉換影象
* @param mat
* @return
*/
private 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;
}
@Override
public void paint(Graphics g){
if(mImg!=null){
g.drawImage(mImg, 0, 0, mImg.getWidth(),mImg.getHeight(),this);
}
}
/**
* opencv實現人臉識別,同時檢測到人臉和人眼時才截圖
* @param img
*/
public static Mat detectFace(Mat img) {
System.out.println("Running DetectFace ... ");
// 從配置檔案lbpcascade_frontalface.xml中建立一個人臉識別器,該檔案位於opencv安裝目錄中
CascadeClassifier faceDetector = new CascadeClassifier("C:\\env\\opencv\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");
CascadeClassifier eyeDetector = new CascadeClassifier("C:\\env\\opencv\\opencv\\sources\\data\\haarcascades\\haarcascade_eye.xml");
// 在圖片中檢測人臉
MatOfRect faceDetections = new MatOfRect();
faceDetector.detectMultiScale(img, faceDetections);
//System.out.println(String.format("Detected %s faces", faceDetections.toArray().length));
Rect[] rects = faceDetections.toArray();
Random r = new Random();
if(rects != null && rects.length >= 1){
for (Rect rect : rects) {
//畫矩形
Imgproc.rectangle(img, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height),
new Scalar(0, 0, 255), 2);
// Imgproc.circle(img, new Point(rect.x + rect.width, rect.y + rect.height), cvRound((rect.width + rect.height) * 0.25),
// new Scalar(0, 0, 255), 2);
//識別人眼
Mat faceROI = new Mat(img, rect );
MatOfRect eyesDetections = new MatOfRect();
eyeDetector.detectMultiScale( faceROI, eyesDetections);
System.out.println("Running DetectEye ... "+ eyesDetections);
if( eyesDetections.toArray().length > 1){
save(img, rect, "C:\\Users\\TR\\Desktop\\demo\\test\\"+r.nextInt(2000)+".jpg");
}
}
}
return img;
}
/**
* opencv將人臉進行截圖並儲存
* @param img
*/
private static void save(Mat img, Rect rect, String outFile){
Mat sub = img.submat(rect);
Mat mat = new Mat();
Size size = new Size(300, 300);
Imgproc.resize(sub, mat, size);
Imgcodecs.imwrite(outFile, mat);
}
public static void main(String[] args) {
try{
//載入opencv庫
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!");
}
//使用Swing生成GUI
JFrame frame = new JFrame("camera");
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
MyDemo panel = new MyDemo();
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();
//Random r = new Random();
while(frame.isShowing()){
//獲取視訊幀
capture.read(capImg);
//轉換為灰度圖
Imgproc.cvtColor(capImg, temp, Imgproc.COLOR_RGB2GRAY);
//識別人臉
Mat image = detectFace(capImg);
//轉為影象顯示
panel.mImg = panel.mat2BI(image);
panel.repaint();
}
capture.release();
frame.dispose();
}catch(Exception e){
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
System.out.println(sw.toString());
}
finally{
System.out.println("Exit");
}
}
}
---------------------
作者:Cceking
來源:CSDN
原文:https://blog.csdn.net/cceking/article/details/80868314
版權宣告:本文為博主原創文章,轉載請附上博文連結!