参考https://blog.csdn.net/zmx729618/article/details/78113268
一共4000张图片。
public static void getFace(String filePath) {
System.out.println("读取人脸......");
//人脸检测模型
CascadeClassifier faceDetector = new CascadeClassifier("C:\\OpenCV\\opencv\\sources\\data\\lbpcascades\\lbpcascade_frontalface.xml");
//定义人脸检测
MatOfRect faceDetections = new MatOfRect();
//获取图像所在的文件夹
File file = new File(filePath);
//遍历文件夹中的所有图片
for (File f : file.listFiles()) {
//读取图片
Mat image = Imgcodecs.imread(f.getAbsolutePath());
//对图像进行人脸检测
faceDetector.detectMultiScale(image, faceDetections);
//获取人脸区域
Rect[] rects = faceDetections.toArray();
//存在人脸
if (faceDetections.toArray().length > 0) {
//获得人脸区域
for (Rect rect : rects) {
Mat mat = new Mat(rect.width, rect.width, CvType.CV_8UC3);
for (int i = rect.x; i < rect.x + rect.width; i++) {
for (int j = rect.y; j < rect.y + rect.height; j++) {
mat.put(j - rect.y, i - rect.x, image.get(j, i));
}
}
//截取人脸区域
Imgproc.resize(mat, mat, new Size(64, 64), 0, 0, 0);
//保存图像
Imgcodecs.imwrite("./genki4k/files1/" + f.getName(), mat);
}
}
}
System.out.println("读取人脸完毕");
}
一共3670张图片,分十组。
且前2162张为笑脸,其余不是。
public static void getRandomFile(String filePath) {
System.out.println("图片随机分组......");
File file = new File(filePath);
File listFile[] = file.listFiles();
Random random = new Random();
//初始化标签
//前2162为笑脸
for (int i = 0; i < 3670; i++) {
String no = listFile[i].getName().substring(4, 8);
if (Integer.parseInt(no) <= 2162)
flags[Integer.parseInt(no)] = 1;
else
flags[(Integer.parseInt(no))] = 0;
}
//随机排列,连同标签一起排列
for (int i = 0; i < 3670; i++) {
int r = random.nextInt(i + 1);
File tmp = listFile[i];
listFile[i] = listFile[r];
listFile[r] = tmp;
int t = flags[i];
flags[i] = flags[r];
flags[r] = t;
}
//分组
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 367; j++) {
randomFiles[i][j] = listFile[i * 367 + j];
}
}
System.out.println("图片随机分组完毕");
}
使用Sobel算子计算梯度
public static Mat getGradient(Mat src) {
Mat grayMat = new Mat();
// 灰度
Imgproc.cvtColor(src, grayMat, Imgproc.COLOR_BGR2GRAY, 0);
//梯度计算
Mat x = new Mat(); //X 方向梯度值矩阵
Mat y = new Mat(); //Y 方向梯度值矩阵
//计算 X,Y 方向绝对梯度
Imgproc.Sobel(grayMat, x, -1, 1, 0, 3, 1, 0);
Core.convertScaleAbs(x, x);
Imgproc.Sobel(grayMat, y, -1, 0, 1, 3, 1, 0);
Core.convertScaleAbs(y, y);
//XY 综合梯度
Core.addWeighted(x, 0.5, y, 0.5, 0, grayMat);
return grayMat;
}
public static float[] getHOG(Mat src) {
//灰度以及梯度处理
src = getGradient(src);
//图像缩放
Imgproc.resize(src, src, new Size(64, 128), 0, 0, Imgproc.INTER_AREA);
HOGDescriptor hogDescriptor = new HOGDescriptor();
MatOfFloat descriptorsValues = new MatOfFloat();
MatOfPoint locations = new MatOfPoint();
//计算 Hog 特征值
hogDescriptor.compute(src, descriptorsValues, new Size(0, 0), new Size(0, 0), locations);
//特征值维数
int size = (int) (descriptorsValues.total() * descriptorsValues.channels());
float[] temp = new float[size];
descriptorsValues.get(0, 0, temp);
//特征数组
float[] resArrays = descriptorsValues.toArray();
return resArrays;
}
使用OpenCV自带的SVM算法实现
public static void train(int t) {
System.out.println("开始训练第" + (t + 1) + "组");
//定义 SVM 对象
SVM svm = SVM.create();
//训练数据 Hog 特征值
Mat dataMat = new Mat();
//标签数据
Mat labelMat = new Mat();
//SVM类型
svm.setType(SVM.C_SVC);
//线性
svm.setKernel(SVM.LINEAR);
//迭代终止条件
svm.setTermCriteria(new TermCriteria(TermCriteria.MAX_ITER, 20000, 1e-6));
//数据大小
int size = inputArr[0].length;
//创建数据和标签对象,训练九组
dataMat.create(3303, size, CvType.CV_32FC1);
labelMat.create(3303, 1, CvType.CV_32SC1);
//加载数据以及标签
for (int i = 0; i < 3303; i++) {
for (int j = 0; j < size; j++) {
dataMat.put(i, j, inputArr[i][j]);
}
labelMat.put(i, 0, resultFlag[i]);
}
System.out.println("训练......");
svm.train(dataMat, Ml.ROW_SAMPLE, labelMat);
System.out.println("训练完毕");
System.out.println("保存训练模型......");
svm.save("./output/result" + t + ".xml"); //保存 SVM 模型
dataMat.release(); //释放变量
labelMat.release(); //释放变量
System.out.println("保存训练模型完毕");
}
public static double test(int i) {
System.out.println("开始测试");
System.out.println("开始测试第" + (i + 1) + "组模型......");
//创建 SVM 模型对象
SVM svm = SVM.load("./output/result" + i + ".xml");
// TP 为正样本,并且检测结果为正样本
// FP 为正样本,并且检测结果为负样本
// TN 为负样本,并且检测结果为负样本
// FN 为负样本,并且检测结果为正样本
double TP = 0;
double FP = 0;
double TN = 0;
double FN = 0;
for (int k = 0; k < 367; k++) {
Mat testMat = new Mat();
int size=hogs[i][k].length;
testMat.create(1,size , CvType.CV_32FC1);
for (int p = 0; p < size; p++) {
testMat.put(0, p, hogs[i][k][p]);
}
float predict = svm.predict(testMat); //预测结果
if (result[i][k] == 1 && predict == 1) {
TP++; //TP 自增 1
} else if (result[i][k] == 1 && predict == 0) {
FP++; //FP 自增 1
} else if (result[i][k] == 0 && predict == 0) {
TN++; //TN 自增 1
} else if (result[i][k] == 0 && predict == 1) {
FN++; //FN 自增 1
}
}
System.out.println("第" + (i + 1) + "组模型训练完毕");
//计算正确率
System.out.println("第" + (i + 1) + "组模型训练结果");
System.out.println("TP: " + TP + "\t FP: " + FP + "\t TN: " + TN + "\t FN: " + FN);
System.out.println("准确率:" + 2 * TP / (2 * TP + FP + FN));
System.out.println();
System.out.println("测试完毕");
return 2 * TP / (2 * TP + FP + FN);
}
//创建Opencv中的视频捕捉对象
VideoCapture camera = new VideoCapture();
//open函数中的0代表当前计算机中索引为0的摄像头
camera.open(0);
同时需要设置键盘监听,按下s为保存图片,esc退出。
//创建窗口
public static JFrame createJFrame(String windowName, int width, int height) {
JFrame frame = new JFrame(windowName);
label = new JLabel();
final JScrollPane imageScrollPane = new JScrollPane(label);
//滚动条
imageScrollPane.setPreferredSize(new Dimension(width, height));
frame.add(imageScrollPane, BorderLayout.CENTER);
//自适应大小
frame.pack();
//设置窗口位置
frame.setLocationRelativeTo(null);
//窗口可见
frame.setVisible(true);
//关闭事件
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//设置键盘监听
frame.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
System.out.println(e.getKeyCode());
//按下s保存
if(e.getKeyCode()==83){
flags[2]=true;
}
//按下esc退出
else if(e.getKeyCode()==27){
flag=false;
}
}
@Override
public void keyReleased(KeyEvent e) {
}
});
return frame;
}
camera.read(img);//read方法读取摄像头的当前帧
faceDetector.detectMultiScale(img, faceDetections);
//获取人脸区域
Rect[] rects = faceDetections.toArray();
//标注人脸区域
//如果是smile则为绿色,否则为红色
if(flags[1])
Imgproc.rectangle(img, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height),
new Scalar(0, 255, 0), 2);
else
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.resize(mat, mat, new Size(64, 64), 0, 0, 0);
float hog[] = SmileTrain.getHOG(mat);
//预测结果
if (predict(hog)) {
flags[1] = true;
} else {
flags[1] = false;
}
预测函数
public static boolean predict(float hog[]){
SVM svm = SVM.load("./output/best.xml");
Mat predictMat = new Mat();
predictMat.create(1, hog.length, CvType.CV_32FC1);
predictMat.put(0, 0, hog);
float results = svm.predict(predictMat); //预测结果
if(results==1)
return true;
return false;
}
//根据是否为smile显示不同文字
if (flags[1]) {
Imgproc.putText(img, "smile", new Point(rect.x, rect.y), Imgproc.FONT_HERSHEY_COMPLEX, 2, new Scalar(0, 255, 0));
} else {
Imgproc.putText(img, "no smile", new Point(rect.x, rect.y), Imgproc.FONT_HERSHEY_COMPLEX, 2, new Scalar(0, 0, 255));
}
package smile;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.ml.Ml;
import org.opencv.ml.SVM;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.objdetect.HOGDescriptor;
import java.io.*;
import java.nio.channels.FileChannel;
import java.util.Random;
public class SmileTrain {
//每张图片的标签,1笑 0不笑
static int flags[] = new int[4002];
//训练标签
static int resultFlag[] = new int[4002];
//分组 10组每组367张
static int result[][] = new int[10][367];
//随机分组文字
static File randomFiles[][] = new File[10][367];
//每张图片的HOG值
static float inputArr[][] = new float[4002][];
//每组每张图片的HOG值
static float hogs[][][] = new float[10][367][];
public static void main(String args[]) throws IOException {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME); //加载 opencv 配置文件
//getFace("./genki4k/files/");
handleFace();
}
/**
* 在给予的图片中找到人脸并保存
*/
public static void getFace(String filePath) {
System.out.println("读取人脸......");
//人脸检测模型
CascadeClassifier faceDetector = new CascadeClassifier("C:\\OpenCV\\opencv\\sources\\data\\lbpcascades\\lbpcascade_frontalface.xml");
//定义人脸检测
MatOfRect faceDetections = new MatOfRect();
//获取图像所在的文件夹
File file = new File(filePath);
//遍历文件夹中的所有图片
for (File f : file.listFiles()) {
//读取图片
Mat image = Imgcodecs.imread(f.getAbsolutePath());
//对图像进行人脸检测
faceDetector.detectMultiScale(image, faceDetections);
//获取人脸区域
Rect[] rects = faceDetections.toArray();
//存在人脸
if (faceDetections.toArray().length > 0) {
//获得人脸区域
for (Rect rect : rects) {
Mat mat = new Mat(rect.width, rect.width, CvType.CV_8UC3);
for (int i = rect.x; i < rect.x + rect.width; i++) {
for (int j = rect.y; j < rect.y + rect.height; j++) {
mat.put(j - rect.y, i - rect.x, image.get(j, i));
}
}
//截取人脸区域
Imgproc.resize(mat, mat, new Size(64, 64), 0, 0, 0);
//保存图像
Imgcodecs.imwrite("./genki4k/files1/" + f.getName(), mat);
}
}
}
System.out.println("读取人脸完毕");
}
/**
* 把图片进行随机分组,并且设置图片的标签
*
* @param filePath
*/
public static void getRandomFile(String filePath) {
System.out.println("图片随机分组......");
File file = new File(filePath);
File listFile[] = file.listFiles();
Random random = new Random();
//初始化标签
//前2162为笑脸
for (int i = 0; i < 3670; i++) {
String no = listFile[i].getName().substring(4, 8);
if (Integer.parseInt(no) <= 2162)
flags[Integer.parseInt(no)] = 1;
else
flags[(Integer.parseInt(no))] = 0;
}
//随机排列,连同标签一起排列
for (int i = 0; i < 3670; i++) {
int r = random.nextInt(i + 1);
File tmp = listFile[i];
listFile[i] = listFile[r];
listFile[r] = tmp;
int t = flags[i];
flags[i] = flags[r];
flags[r] = t;
}
//分组
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 367; j++) {
randomFiles[i][j] = listFile[i * 367 + j];
}
}
System.out.println("图片随机分组完毕");
}
/**
* 十折方式处理初始数据
*/
public static void handleFace() {
//最好得分
double best = 0;
//最好得分模型
int index = 0;
System.out.println("处理人脸......");
int k;
for (int t = 0; t < 10; t++) {
k = 0;
getRandomFile("./genki4k/files1/");
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 367; j++) {
//读取图片
Mat originalImage = Imgcodecs.imread(randomFiles[i][j].getAbsolutePath());
//获取HOG值
inputArr[k] = getHOG(originalImage);
hogs[i][j] = inputArr[k];
//获得标签
String no = randomFiles[i][j].getName().substring(4, 8);
resultFlag[k] = flags[Integer.parseInt(no)];
result[i][j] = flags[Integer.parseInt(no)];
k++;
}
}
//训练该组数据
train(t);
double res = test(t);
if (res > best) {
best = res;
index = t;
}
}
//把最好的模型单独复制一份
File src = new File("./output/result" + index + ".xml");
File dst = new File("./output/best.xml");
try {
FileInputStream inputStream = new FileInputStream(src);
FileOutputStream outputStream = new FileOutputStream(dst);
// 得到源文件通道
FileChannel inputChannel = inputStream.getChannel();
// 得到目标文件通道
FileChannel outputChannel = outputStream.getChannel();
//将源文件数据通达连通到目标文件通道进行传输
inputChannel.transferTo(0, inputChannel.size(), outputChannel);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("处理人脸完毕");
}
public static float[] getHOG(Mat src) {
//灰度以及梯度处理
src = getGradient(src);
//图像缩放
Imgproc.resize(src, src, new Size(64, 128), 0, 0, Imgproc.INTER_AREA);
HOGDescriptor hogDescriptor = new HOGDescriptor();
MatOfFloat descriptorsValues = new MatOfFloat();
MatOfPoint locations = new MatOfPoint();
//计算 Hog 特征值
hogDescriptor.compute(src, descriptorsValues, new Size(0, 0), new Size(0, 0), locations);
//特征值维数
int size = (int) (descriptorsValues.total() * descriptorsValues.channels());
float[] temp = new float[size];
descriptorsValues.get(0, 0, temp);
//特征数组
float[] resArrays = descriptorsValues.toArray();
return resArrays;
}
public static Mat getGradient(Mat src) {
Mat grayMat = new Mat();
// 灰度
Imgproc.cvtColor(src, grayMat, Imgproc.COLOR_BGR2GRAY, 0);
//梯度计算
Mat x = new Mat(); //X 方向梯度值矩阵
Mat y = new Mat(); //Y 方向梯度值矩阵
//计算 X,Y 方向绝对梯度
Imgproc.Sobel(grayMat, x, -1, 1, 0, 3, 1, 0);
Core.convertScaleAbs(x, x);
Imgproc.Sobel(grayMat, y, -1, 0, 1, 3, 1, 0);
Core.convertScaleAbs(y, y);
//XY 综合梯度
Core.addWeighted(x, 0.5, y, 0.5, 0, grayMat);
return grayMat;
}
public static void train(int t) {
System.out.println("开始训练第" + (t + 1) + "组");
//定义 SVM 对象
SVM svm = SVM.create();
//训练数据 Hog 特征值
Mat dataMat = new Mat();
//标签数据
Mat labelMat = new Mat();
//SVM类型
svm.setType(SVM.C_SVC);
//线性
svm.setKernel(SVM.LINEAR);
//迭代终止条件
svm.setTermCriteria(new TermCriteria(TermCriteria.MAX_ITER, 20000, 1e-6));
//数据大小
int size = inputArr[0].length;
//创建数据和标签对象,训练九组
dataMat.create(3303, size, CvType.CV_32FC1);
labelMat.create(3303, 1, CvType.CV_32SC1);
//加载数据以及标签
for (int i = 0; i < 3303; i++) {
for (int j = 0; j < size; j++) {
dataMat.put(i, j, inputArr[i][j]);
}
labelMat.put(i, 0, resultFlag[i]);
}
System.out.println("训练......");
svm.train(dataMat, Ml.ROW_SAMPLE, labelMat);
System.out.println("训练完毕");
System.out.println("保存训练模型......");
svm.save("./output/result" + t + ".xml"); //保存 SVM 模型
dataMat.release(); //释放变量
labelMat.release(); //释放变量
System.out.println("保存训练模型完毕");
}
public static double test(int i) {
System.out.println("开始测试");
System.out.println("开始测试第" + (i + 1) + "组模型......");
//创建 SVM 模型对象
SVM svm = SVM.load("./output/result" + i + ".xml");
// TP 为正样本,并且检测结果为正样本
// FP 为正样本,并且检测结果为负样本
// TN 为负样本,并且检测结果为负样本
// FN 为负样本,并且检测结果为正样本
double TP = 0;
double FP = 0;
double TN = 0;
double FN = 0;
for (int k = 0; k < 367; k++) {
Mat testMat = new Mat();
int size=hogs[i][k].length;
testMat.create(1,size , CvType.CV_32FC1);
for (int p = 0; p < size; p++) {
testMat.put(0, p, hogs[i][k][p]);
}
float predict = svm.predict(testMat); //预测结果
if (result[i][k] == 1 && predict == 1) {
TP++; //TP 自增 1
} else if (result[i][k] == 1 && predict == 0) {
FP++; //FP 自增 1
} else if (result[i][k] == 0 && predict == 0) {
TN++; //TN 自增 1
} else if (result[i][k] == 0 && predict == 1) {
FN++; //FN 自增 1
}
}
System.out.println("第" + (i + 1) + "组模型训练完毕");
//计算正确率
System.out.println("第" + (i + 1) + "组模型训练结果");
System.out.println("TP: " + TP + "\t FP: " + FP + "\t TN: " + TN + "\t FN: " + FN);
System.out.println("准确率:" + 2 * TP / (2 * TP + FP + FN));
System.out.println();
System.out.println("测试完毕");
return 2 * TP / (2 * TP + FP + FN);
}
}
package smile;
import org.opencv.core.Point;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.ml.SVM;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.videoio.VideoCapture;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.util.Scanner;
public class SmilePredict {
//窗体
static JFrame frame;
//显示图片
static JLabel label;
static boolean flag = true;
// 第0个flag表示是否正在预测
// 第1个flag表示预测结果是否为smile
// 第2个flag表示是否保存当前图片
static final boolean[] flags = {
false, false, false};
public static void main(String args[]) {
//加载 opencv 配置文件
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
//创建Opencv中的视频捕捉对象
VideoCapture camera = new VideoCapture();
//open函数中的0代表当前计算机中索引为0的摄像头
camera.open(0);
//isOpened函数用来判断摄像头调用是否成功
if (!camera.isOpened()) {
System.out.println("Camera Error");
} else {
Mat img = new Mat();//创建一个输出帧
//记录以及保存的图片数量
int count =0;
//初始化窗口
frame = createJFrame("windowName", 640, 480);
//官方人脸检测模型
CascadeClassifier faceDetector = new CascadeClassifier("C:\\OpenCV\\opencv\\sources\\data\\lbpcascades\\lbpcascade_frontalface_improved.xml");
//定义人脸检测
MatOfRect faceDetections = new MatOfRect();
//循环读取摄像头内容
while (flag) {
camera.read(img);//read方法读取摄像头的当前帧
faceDetector.detectMultiScale(img, faceDetections);
//获取人脸区域
Rect[] rects = faceDetections.toArray();
//存在人脸
if (faceDetections.toArray().length > 0) {
//获得人脸区域
for (Rect rect : rects) {
Mat mat = new Mat(rect.width, rect.width, CvType.CV_8UC3);
for (int i = rect.x; i < rect.x + rect.width; i++) {
for (int j = rect.y; j < rect.y + rect.height; j++) {
mat.put(j - rect.y, i - rect.x, img.get(j, i));
}
}
//标注人脸区域
//如果是smile则为绿色,否则为红色
if(flags[1])
Imgproc.rectangle(img, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height),
new Scalar(0, 255, 0), 2);
else
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);
//是否保存当前图片
if(flags[2]){
//smile or non smile
if(flags[1])
Imgcodecs.imwrite("./output/smile/" +count+++".jpg", img);
else
Imgcodecs.imwrite("./output/non_smile/" +count+++".jpg", img);
flags[2]=false;
}
//截取人脸区域用于预测
Imgproc.resize(mat, mat, new Size(64, 64), 0, 0, 0);
//如果当前没有在预测则新开线程进行预测
if (!flags[0]) {
new Thread(new Runnable() {
@Override
public void run() {
flags[0] = true;
//获取hog特征值
float hog[] = SmileTrain.getHOG(mat);
//预测结果
if (predict(hog)) {
flags[1] = true;
} else {
flags[1] = false;
}
flags[0] = false;
}
}).start();
}
//根据是否为smile显示不同文字
if (flags[1]) {
Imgproc.putText(img, "smile", new Point(rect.x, rect.y), Imgproc.FONT_HERSHEY_COMPLEX, 2, new Scalar(0, 255, 0));
} else {
Imgproc.putText(img, "no smile", new Point(rect.x, rect.y), Imgproc.FONT_HERSHEY_COMPLEX, 2, new Scalar(0, 0, 255));
}
}
}
//重新加载窗口图片
Image loadedImage = toBufferedImage(img);
label.setIcon(new ImageIcon(loadedImage));
try {
Thread.sleep(100);//线程暂停100ms
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
System.exit(0);
}
//把Mat转为Image用于显示
public static Image toBufferedImage(Mat matrix) {
int type = BufferedImage.TYPE_BYTE_GRAY;
if (matrix.channels() > 1) {
type = BufferedImage.TYPE_3BYTE_BGR;
}
int bufferSize = matrix.channels() * matrix.cols() * matrix.rows();
byte[] buffer = new byte[bufferSize];
matrix.get(0, 0, buffer); // 获取所有的像素点
BufferedImage image = new BufferedImage(matrix.cols(), matrix.rows(), type);
final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
System.arraycopy(buffer, 0, targetPixels, 0, buffer.length);
return image;
}
//创建窗口
public static JFrame createJFrame(String windowName, int width, int height) {
JFrame frame = new JFrame(windowName);
label = new JLabel();
final JScrollPane imageScrollPane = new JScrollPane(label);
//滚动条
imageScrollPane.setPreferredSize(new Dimension(width, height));
frame.add(imageScrollPane, BorderLayout.CENTER);
//自适应大小
frame.pack();
//设置窗口位置
frame.setLocationRelativeTo(null);
//窗口可见
frame.setVisible(true);
//关闭事件
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//设置键盘监听
frame.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
System.out.println(e.getKeyCode());
//按下s保存
if(e.getKeyCode()==83){
flags[2]=true;
}
//按下esc退出
else if(e.getKeyCode()==27){
flag=false;
}
}
@Override
public void keyReleased(KeyEvent e) {
}
});
return frame;
}
public static boolean predict(float hog[]){
SVM svm = SVM.load("./output/best.xml");
Mat predictMat = new Mat();
predictMat.create(1, hog.length, CvType.CV_32FC1);
predictMat.put(0, 0, hog);
float results = svm.predict(predictMat); //预测结果
if(results==1)
return true;
return false;
}
}
通过hog特征值配合svm实现简单笑脸检测。当图片预处理的好的时候准确率很大有提升。
https://blog.csdn.net/qq_34814092/article/details/103205269
https://blog.csdn.net/zmx729618/article/details/78113268
添加链接描述