本例程是识别图片中的人脸,并画出识别出的人脸的位置。在网上找了很久,用java实现人脸识别技术很难找到。多是依靠JNI 调用OpenCV本地方法实现的。那么这里先来说说这种方法:
先认识一下JNI 和OpenCV
JNI是Java Native Interface的缩写,中文为JAVA本地调用。从Java 1.1开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。
OpenCV是Intel公司支持的开源计算机视觉库。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,实现了图像处理和计算机视觉方面的很多通用算法。
将源代码中的dll文件(cv097.dll,cxcore097.dll,highgui097.dll,JNI2OpenCV.dll)放入C:\WINDOWS\system32目录下。
现在开始上源码:
public class JNIOpenCV{
public JNIOpenCV() {}
static{
System.out.println("开始加载JNI2OpenCV.dll");
System.loadLibrary("JNI2OpenCV");
System.out.println("加载完成");
}
// 加载动态链接库
public native int[] detectFace(int minFaceWidth, int minFaceHeight, String cascade, String filename);
// 声明本地方法
}
public class FaceDetection {
private JNIOpenCV myJNIOpenCV;
public FaceDetection(String intputFileName,String outputFileName) {
myJNIOpenCV = new JNIOpenCV();
String filename = intputFileName;
String outputFilename = outputFileName;
String cascade = "F:\\detectface\\xml\\haarcascade_frontalface_alt2.xml";
int[] detectedFaces = myJNIOpenCV.detectFace(40, 40, cascade, filename);
int numFaces = detectedFaces.length / 4;
if(numFaces > 0){
System.out.println("有脸!有 "+ numFaces + " 张脸");
}else{
System.out.println("没有脸!");
}
for (int i = 0; i < numFaces; i++) {
System.out.println("Face " + i + ": " + detectedFaces[4 * i + 0] + " " + detectedFaces[4 * i + 1] + " " + detectedFaces[4 * i + 2] + " " + detectedFaces[4 * i + 3]);
}
int[][] RectInt=new int[numFaces][4];
for (int i = 0; i < numFaces; i++)
{
RectInt[i][0]=detectedFaces[4 * i + 0];
RectInt[i][1]=detectedFaces[4 * i + 1];
RectInt[i][2]=detectedFaces[4 * i + 2];
RectInt[i][3]=detectedFaces[4 * i + 3];
}
if(new DrawInImg(filename,outputFilename,RectInt).DrawRect())
System.out.println("File create success ! ");
else
System.out.println("File create error ! ");
}
public static void main(String args[]) {
FaceDetection myFaceDetection = new FaceDetection("F:\\detectface\\image\\tt.jpg","F:\\detectface\\image\\tt2.jpg");
}
}
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
public class DrawInImg {
private boolean isDone = false;
private String inputFileName = "";
private String outputFileName = "";
private int[][] RectInt;
public DrawInImg(String inputFileName, String outputFileName,
int[][] RectInt) {
this.inputFileName = inputFileName;
this.outputFileName = outputFileName;
this.RectInt = RectInt;
}
public boolean DrawRect() {
try {
FileInputStream fis = new FileInputStream(inputFileName);
FileOutputStream fos = new FileOutputStream(outputFileName);
BufferedImage img = ImageIO.read(fis);
Graphics g = img.getGraphics();
g.setColor(Color.GREEN);
for (int i = 0; i < RectInt.length; i++) {
for (int j = 0; j < RectInt[i].length; j++) {
g.drawRect(RectInt[i][0], RectInt[i][1], RectInt[i][2],
RectInt[i][3]);
// System.out.print(RectInt[i][j]+" ");
}
System.out.print("\r\n");
}
img.flush();
g.dispose();
ImageIO.write(img, "JPG", fos);
while (true) {
if (new File(outputFileName).exists()) {
this.isDone = true;
break;
}
}
} catch (IOException ioe) {
ioe = null;
}
return this.isDone;
}
}
注意:以上代码不能放在包下面,否则会运行不成功的。(原因是dll编译的时候没有带上包,如需包还需重新编译dll)。