您的位置:首页 > 编程语言 > Java开发

Java调用OpenCV人脸识别

2015-02-06 13:55 501 查看
1.J***A的JNI部分
调用JNI的基类
Java代码

1. package com;
2. public class JNIBase
3. {
4. public JNIBase(){}
5.
6. public JNIBase(String libraryName)
7. {
8. loadLibrary(libraryName);
9. }
10.
11. private static void loadLibrary(String libraryName)
12. {
13. System.loadLibrary(libraryName);
14. }
15.}


实现这个基类
Java代码

1. package com;
2.
3. public class JNIOpencv extends JNIBase
4. {
5. public JNIOpencv (String libraryName)
6. {
7. super(libraryName);
8. }
9.
10. public JNIOpencv()
11. {
12. System.loadLibrary("jniOpenCV");
13. }
14.
15. public native int[] detectFace(int minFaceWidth, int minFaceHeight,
16. String cascade, String filename);
17.}


类中定义了一个detectFace方法,是要用C来实现的。

编译好这个类后,要用在命令行用javah命令生成需要的.h的头文件:
D:\Develop\Workspace\MyEclipse Professional2014\OpenCVTest\src>javah
-jni com.JNIOpencv
其中:
工程路径:D:\Develop\Workspace\MyEclipseProfessional 2014\OpenCVTest\src>
命令:javah

生成文件类型:-jni

类名:com.JNIOpencv

会生成一个名为com_JNIOpencv.h的头文件:
C代码

1. /* DO NOT EDIT THIS FILE - it is machine generated */
2. #include <jni.h>

3. /* Header for class com_JNIOpencv */

4.
5. #ifndef _Included_lveyo_bcndyl_jni_opencv_JNIOpencv
6. #define _Included_lveyo_bcndyl_jni_opencv_JNIOpencv
7. #ifdef __cplusplus
8. extern "C" {
9. #endif
10./*

11. * Class: com_JNIOpencv

12. * Method: detectFace
13. * Signature: (IILjava/lang/String;Ljava/lang/String;)[I
14. */

15.JNIEXPORT jintArray JNICALL Java_com_JNIOpencv_detectFace

16. (JNIEnv *, jobject, jint, jint, jstring, jstring);
17.
18.#ifdef __cplusplus
19.}
20.#endif
21.#endif


2.C程序部分

在VS2013中配置opencv,同时要将JDK中的include目录和include/win32目录都加入到VS2013的Include Files中。
VS中在项目上右键打开属性 -> C/C++ -> 常规-> 附加包含目录: 添加jni对应的头文件

新建一个win32 MFC DLL项目jniOpenCV,把刚才生成的com_JNIOpencv.h头文件加入到项目,并且修改jniOpenCV.cpp文件:
C++代码

1. #include "stdafx.h"
2. #include <jni.h>
3. #include "com_JNIOpencv.h"
4. #include "opencv/cv.h"
5. #include "opencv/highgui.h"
6.
7. JNIEXPORTjintArrayJNICALL
Java_com_JNIOpencv_detectFace
8. (JNIEnv *env, jobject obj, jint width, jint height, jstring cascade, jstring filename)
9. {
10. const char *str_cascade, *str_filename;
11. str_cascade = env->GetStringUTFChars(cascade, false);
12. str_filename = env->GetStringUTFChars(filename, false);
13.
14. jintArray faceArray =
NULL;
15. CvHaarClassifierCascade *cv_cascade = (CvHaarClassifierCascade*)cvLoad( str_cascade );
16. IplImage *image = cvLoadImage( str_filename, 1 );
17.
18. if(image!=0)
19. {
20. CvMemStorage* storage = cvCreateMemStorage(0);
21. CvSeq* faces;
22.
23. //double t = (double)cvGetTickCount();
24. /* use the fastest variant */
25. faces = cvHaarDetectObjects( image, cv_cascade, storage, 1.2, 2,
26. CV_HAAR_DO_CANNY_PRUNING, cvSize(width, height) );
27. //t = (double)cvGetTickCount() - t;
28. //printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );
29.
30. const int total = faces->total;
31.
32. faceArray = env-> NewIntArray(4*total);
33. jint faceBuf[4];
34.
35. for( int i = 0; i < total; i++ )
36. {
37. CvRect face_rect = *(CvRect*)cvGetSeqElem( faces, i );
38. int pointX = face_rect.x;
39. int pointY = face_rect.y;
40. int faceWidth = face_rect.width;
41. int faceHeight = face_rect.height;
42.
43. //printf("i %d, x %d, y %d, width %d, height %d\n",
44. // i,pointX,pointY,faceWidth,faceHeight);
45.
46. faceBuf[0] = pointX;
47. faceBuf[1] = pointY;
48. faceBuf[2] = faceWidth;
49. faceBuf[3] = faceHeight;
50.
51. env->SetIntArrayRegion(faceArray,i*4,4,faceBuf);
52.
53. }
54.
55. cvReleaseMemStorage( &storage );
56. cvReleaseImage( &image );
57. }
58. cvReleaseHaarClassifierCascade( &cv_cascade );
59.
60. env->ReleaseStringUTFChars(cascade, str_cascade);
61. env->ReleaseStringUTFChars(filename, str_filename);
62. return faceArray;
63.}



编译生成jniOpenCV.dll。此处的检测代码是根据OpenCV的文档和示例程序修改。将生成的jniOpenCV.dll文件复制到%J***A_HOME%/bin中,如果在没安装OpenCV的机器上运行,还需要将OpenCV安装目录中bin目录下所有dll文件一起复制到%J***A_HOME%/bin中。



3.实现J***A的调用

其中haarcascade_frontalface_alt2.xml文件在安装的opencv\sources\data\ haarcascades中,将其复制到代码中指定的文件夹中。图片也复制到相应文件夹中。

Java代码

1. package com;
2.
3. public class Test
4. {
5. public static void main(String[] args)

6. {

7. //初始化JNI调用类JNIOpencv
8. JNIOpencv open = new JNIOpencv("jniOpenCV");
9.
10. //要检测的图片文件
11. String filename = "res/image/1.jpg";
12.
13. //OpenCv提供的人间的特征文件
14. String cascade = "res/haarcascade_frontalface_alt2.xml";
15.
16. //人脸检测,前两个参数为可检测的最小人脸的宽度和高度
17. //返回值为人脸在图中的坐标和宽高,{x, y, width, height}
18. int[] faces = open.detectFace(40, 40, cascade, filename);
19. if(faces != null && faces.length!=0)
20. {
21. //返回的人脸总数
22. System.out.println( "faces " + faces.length/4 );
23.
24. //分别输出每个人脸的坐标信息
25. for (int temp : faces)
26. {
27. System.out.println(temp);
28. }
29. }
30. }
31.}



配置JRE环境:

1. 工程名右键 -> Build Path -> Configure Build Path -> Libraries 调整JRE SystemLibrary 为32位的可用Library。

2. 工程名右键 -> Run As -> Run Configurations -> Libraries -> JRE调整Runtime JRE与步骤1中一致。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: