javacv
JavaCV es una biblioteca de desarrollo Java basada en OpenCV y FFmpeg para funciones de procesamiento de imágenes y visión por computadora. Proporciona una serie de clases y métodos que permiten a los desarrolladores utilizar fácilmente algoritmos y técnicas de visión por computadora en aplicaciones Java.
-
Integración de OpenCV y FFmpeg: JavaCV integra estrechamente OpenCV y FFmpeg, dos importantes bibliotecas de procesamiento de video y visión por computadora. Los desarrolladores pueden llamar directamente a las funciones de OpenCV y FFmpeg en código Java sin utilizar otras herramientas o bibliotecas externas.
-
Captura de imágenes y videos: JavaCV permite a los desarrolladores capturar imágenes y transmisiones de video desde cámaras y archivos de video. Con unas pocas líneas simples de código, puede introducir imágenes o videos en su aplicación Java para su procesamiento y análisis.
-
Procesamiento y análisis de imágenes: JavaCV proporciona varias funciones de análisis y procesamiento de imágenes, incluido el filtrado de imágenes, la detección de bordes, la ecualización de histogramas, etc. Los desarrolladores pueden utilizar estas funciones para mejorar y optimizar imágenes, así como extraer características de las imágenes.
-
Detección de características y descriptores: JavaCV admite varios algoritmos de detección y descriptores de características, como SIFT (Transformación de características invariantes de escala), SURF (Características robustas aceleradas) y ORB (Binario invariante de rotación). Estos algoritmos se pueden utilizar en aplicaciones como reconocimiento de objetos, comparación de imágenes y unión de imágenes.
-
Detección y reconocimiento de rostros: JavaCV proporciona funciones de detección y reconocimiento de rostros, lo que permite a los desarrolladores implementar aplicaciones relacionadas con rostros en aplicaciones Java. Puede utilizar JavaCV para detectar rostros, marcar puntos de referencia faciales y realizar reconocimiento facial.
-
Soporte de aprendizaje automático: JavaCV está integrado con el marco de aprendizaje profundo OpenCV DNN, lo que permite a los desarrolladores utilizar modelos de redes neuronales previamente entrenados en Java. Esto permite a los desarrolladores realizar fácilmente tareas de visión por computadora, como clasificación de imágenes, detección de objetos y segmentación de imágenes.
-
Procesamiento multimedia: JavaCV también es muy potente para procesar archivos de audio y vídeo. Puede leer, escribir y editar varios formatos de audio y video, y también admite el procesamiento de transmisiones de audio y video.
En resumen, JavaCV es una biblioteca de desarrollo Java potente y versátil para implementar tareas de procesamiento de imágenes y visión por computadora. Su integración y sus ricas funciones y aplicaciones facilitan a los desarrolladores procesar imágenes y vídeos y crear aplicaciones visuales excepcionales.
tutorial de código
1. Primero busque las fotos de avatar de los dos personajes y colóquelas por separado en archivos.
En segundo lugar, utilice el entrenamiento de código Java para generar archivos modelo.
Primero, importe el paquete jar dependiente de javacv a maven
<!-- https://mvnrepository.com/artifact/org.bytedeco/javacv-platform -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.5</version>
</dependency>
El código java es el siguiente:
import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.MatVector;
import org.bytedeco.opencv.opencv_core.Size;
import org.bytedeco.opencv.opencv_face.FaceRecognizer;
import org.bytedeco.opencv.opencv_face.FisherFaceRecognizer;
import java.io.File;
import java.io.IOException;
import java.nio.IntBuffer;
import java.util.LinkedList;
import java.util.List;
import static org.bytedeco.opencv.global.opencv_core.CV_32SC1;
import static org.bytedeco.opencv.global.opencv_imgcodecs.IMREAD_GRAYSCALE;
import static org.bytedeco.opencv.global.opencv_imgproc.resize;
/**
* @author willzhao
* @version 1.0
* @description 训练
* @date 2021/12/12 18:26
*/
public class FaceTrainDemo {
/**
* 从指定目录下
* @param dirs
* @param outputPath
*/
private void train(String[] dirs, String outputPath) {
int totalImageNums = 0;
// 统计每个路径下的照片数,加在一起就是照片总数
for(String dir : dirs) {
List<String> files = getAllFilePath(dir);
totalImageNums += files.size();
}
//todo截取人脸
System.out.println("total : " + totalImageNums);
// 这里用来保存每一张照片的序号,和照片的Mat对象
MatVector imageIndexMatMap = new MatVector(totalImageNums);
Mat lables = new Mat(totalImageNums, 1, CV_32SC1);
// 这里用来保存每一张照片的序号,和照片的类别
IntBuffer lablesBuf = lables.createBuffer();
// 类别序号,从1开始,dirs中的每个目录就是一个类别
int kindIndex = 1;
// 照片序号,从0开始
int imageIndex = 0;
// 每个目录下的照片都遍历
for(String dir : dirs) {
// 得到当前目录下所有照片的绝对路径
List<String> files = getAllFilePath(dir);
// 处理一个目录下的每张照片,它们的序号不同,类别相同
for(String file : files) {
// imageIndexMatMap放的是照片的序号和Mat对象
imageIndexMatMap.put(imageIndex, read(file));
// bablesBuf放的是照片序号和类别
lablesBuf.put(imageIndex, kindIndex);
// 照片序号加一
imageIndex++;
}
// 每当遍历完一个目录,才会将类别加一
kindIndex++;
}
// 实例化人脸识别类
FaceRecognizer faceRecognizer = FisherFaceRecognizer.create();
// 训练,入参就是图片集合和分类集合
faceRecognizer.train(imageIndexMatMap, lables);
// 训练完成后,模型保存在指定位置
faceRecognizer.save(outputPath);
//释放资源
faceRecognizer.close();
}
/**
* 读取指定图片的灰度图,调整为指定大小
* @param path
* @return
*/
private static Mat read(String path) {
Mat faceMat = opencv_imgcodecs.imread(path,IMREAD_GRAYSCALE);
resize(faceMat, faceMat, new Size(164, 164));
return faceMat;
}
/**
* 把指定路径下所有文件的绝对路径放入list集合中返回
* @param path
* @return
*/
public static List<String> getAllFilePath(String path) {
List<String> paths = new LinkedList<>();
File file = new File(path);
if (file.exists()) {
// 列出该目录下的所有文件
File[] files = file.listFiles();
for (File f : files) {
if (!f.isDirectory()) {
// 把每个文件的绝对路径都放在list中
paths.add(f.getAbsolutePath());
}
}
}
return paths;
}
public static void main(String[] args) throws IOException {
String base = "D:\\face_img\\";
// 存储图片的两个目录
// man目录下保存了群众演员A的所有人脸照片,
// woman目录下保存了群众演员B的所有人脸照片
String[] dirs = {base + "msk", base + "tlp"};
// 开始训练,并指定模型输出位置
new FaceTrainDemo().train(dirs, base + "faceRecognizer.xml");
}
}
Tenga en cuenta que la matriz de directorios tiene al menos dos.
Haga clic derecho en el editor de ideas para ejecutarlo y se generará un archivo modelo de faceRecognizer.xml.
El código de identificación de Java es el siguiente :
La clave de kindNameMap es el orden de la matriz de directorios en el código de entrenamiento, la primera es msk, la segunda es tlp, etc.
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_face.FaceRecognizer;
import org.bytedeco.opencv.opencv_face.FisherFaceRecognizer;
import org.bytedeco.opencv.opencv_objdetect.CascadeClassifier;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static org.bytedeco.opencv.global.opencv_imgproc.*;
/**
* @author tarzan
*/
public class FaceDemo {
public static void main(String[] args) throws IOException {
Map<Integer, String> kindNameMap=new HashMap<>(2);
kindNameMap.put(1,"msk");
kindNameMap.put(2,"tlp");
faceRecognize("D:\\face_img\\test\\msk.jpg",kindNameMap);
}
/**
* 调整后的文件宽度
*/
public final static int RESIZE_WIDTH = 164;
/**
* 调整后的文件高度
*/
public final static int RESIZE_HEIGHT = 164;
/**
* 超过这个置信度就明显有问题了
*/
public final static double MAX_CONFIDENCE = 50d;
public final static String frontalFaceModelPath="D:\\face_img\\lbpcascade_frontalface.xml";
public final static String faceRecognizerPath="D:\\face_img\\faceRecognizer.xml";
/**
* 人脸检测
*
* @param filePath 图片路径
*/
public static RectVector faceDetect(Mat grayImg) throws IOException {
// 读取opencv人脸检测器
CascadeClassifier cascade = new CascadeClassifier(frontalFaceModelPath);
// 检测到的人脸
RectVector faces = new RectVector();
//多人脸检测
cascade.detectMultiScale(grayImg, faces);
return faces;
}
/**
* 人脸识别
*
* @param kindNameMap 人物名称集合
*/
public static void faceRecognize(String filePath,Map<Integer, String> kindNameMap) throws IOException {
File file=new File(filePath);
BufferedImage image = ImageIO.read(file);
Java2DFrameConverter imageConverter = new Java2DFrameConverter();
Frame frame = imageConverter.convert(image);
//类型转换
OpenCVFrameConverter.ToMat converter = new OpenCVFrameConverter.ToMat();
Mat original = converter.convertToMat(frame);
//存放灰度图
Mat grayImg = new Mat();
//模式设置成ImageMode.Gray下不需要再做灰度 摄像头获取的是彩色图像,所以先灰度化下
cvtColor(original, grayImg, COLOR_BGRA2GRAY);
// 均衡化直方图
equalizeHist(grayImg, grayImg);
RectVector faces=faceDetect(grayImg);
// 遍历人脸
for (int i = 0; i < faces.size(); i++) {
Rect face_i = faces.get(i);
//绘制人脸矩形区域,scalar色彩顺序:BGR(蓝绿红)
rectangle(original, face_i, new Scalar(0, 255, 0, 1));
int pos_x = Math.max(face_i.tl().x() - 10, 0);
int pos_y = Math.max(face_i.tl().y() - 10, 0);
oneFaceRecognize(grayImg,face_i,kindNameMap);
// 在人脸矩形上方绘制提示文字(中文会乱码)
putText(original, "people face", new Point(pos_x, pos_y), FONT_HERSHEY_COMPLEX, 1.0, new Scalar(0, 0, 255, 2.0));
}
frame = converter.convert(original);
image = imageConverter.convert(frame);
String fileName=file.getName();
String extension=fileName.substring(fileName.lastIndexOf(".")+1);
String newFileName=fileName.substring(0,fileName.lastIndexOf("."))+"_result."+extension;
ImageIO.write(image, extension, new File(file.getParent()+File.separator+newFileName));
}
/**
* 人脸识别
*
* @param kindNameMap 人物名称集合
*/
public static String oneFaceRecognize(Mat grayImg,Rect face,Map<Integer, String> kindNameMap){
String kindName=null;
Mat mat=new Mat(grayImg, face);
Size size= new Size(RESIZE_WIDTH, RESIZE_HEIGHT);
// 核心代码,把检测到的人脸拿去识别
// 调整到和训练一致的尺寸
resize(mat, mat, size);
// 推理结果的标签
int[] labels = new int[1];
// 推理结果的置信度
double[] confidences = new double[1];
try {
// 推理(这一行可能抛出RuntimeException异常,因此要补货,否则会导致程序退出)
FaceRecognizer faceRecognizer= FisherFaceRecognizer.create();
// 加载的是训练时生成的模型
faceRecognizer.read(faceRecognizerPath);
// 设置门限,这个可以根据您自身的情况不断调整
faceRecognizer.setThreshold(MAX_CONFIDENCE);
//人脸检测
faceRecognizer.predict(mat, labels, confidences);
} catch (RuntimeException runtimeException) {
runtimeException.printStackTrace();
}
// 得到分类编号后,从map中取得名字,用来显示
if (kindNameMap.containsKey(labels[0])) {
kindName = String.format("%s, confidence : %.4f", kindNameMap.get(labels[0]), confidences[0]);
} else {
// 取不到名字的时候,就显示unknown
kindName = "unknown(" + labels[0] + ")";
}
System.out.println(kindName);
return kindName;
}
}
Haga clic derecho y ejecute.
Precauciones:
1. Es mejor no utilizar chino para la ruta del archivo.
2. No cambie el sufijo del formato de la imagen usted mismo; de lo contrario, es posible que la imagen no se pueda leer.
Artículos relacionados recomendados