JAVA应用JNI调用OpenCV实现人脸检测

摘要:
1.JAVA的JNI部分调用JNI基类JAVA代码packagelveyo.bcndyl。jni-opencv;publicclassJNIBase{publicJNIBase(){}publicJNIB ase(StringlibraryName){loadLibrary(library Name);}privatestaticvoidloadLibrary(StringlibraryName){

1.JAVA的JNI部分 调用JNI的基类

Java代码 复制代码收藏代码JAVA应用JNI调用OpenCV实现人脸检测第3张
  1. package lveyo.bcndyl.jni.opencv;  
  2. publicclass JNIBase {  
  3.       
  4.     public JNIBase(){}  
  5.       
  6.     public JNIBase(String libraryName){  
  7.         loadLibrary(libraryName);  
  8.     }  
  9.       
  10.     privatestaticvoid loadLibrary(String libraryName){
  11.         System.loadLibrary(libraryName);  
  12.     }  
  13.  
package lveyo.bcndyl.jni.opencv;
public class JNIBase {
	
	public JNIBase(){}
	
	public JNIBase(String libraryName){
		loadLibrary(libraryName);
	}
	
	private static void loadLibrary(String libraryName){
		System.loadLibrary(libraryName);
	}

}

实现这个基类

Java代码 复制代码收藏代码JAVA应用JNI调用OpenCV实现人脸检测第3张
  1. package lveyo.bcndyl.jni.opencv;  
  2.  
  3. publicclass JNIOpencv extends JNIBase{  
  4.       
  5.     public JNIOpencv (String libraryName){  
  6.         super(libraryName);  
  7.     }  
  8.       
  9.     public JNIOpencv(){  
  10.         System.loadLibrary("jniOpenCV");  
  11.     }  
  12.  
  13.     publicnativeint[] detectFace(int minFaceWidth, int minFaceHeight,  
  14.                                    String cascade, String filename);  
  15.  
package lveyo.bcndyl.jni.opencv;

public class JNIOpencv extends JNIBase{
	
	public JNIOpencv (String libraryName){
		super(libraryName);
	}
	
	public JNIOpencv(){
		System.loadLibrary("jniOpenCV");
	}

    public native int[] detectFace(int minFaceWidth, int minFaceHeight,
                                   String cascade, String filename);

}

类中定义了一个detectFace方法,是要用C来实现的。
编译好这个类后,要用在命令行用javah命令生成需要的.h的头文件:

引用
javah lveyo.bcndyl.jni.opencv.JNIOpencv

会生成一个名为lveyo_bcndyl_jni_opencv_JNIOpencv.h的头文件:

C代码 复制代码收藏代码JAVA应用JNI调用OpenCV实现人脸检测第3张
  1. /* DO NOT EDIT THIS FILE - it is machine generated */ 
  2. #include <jni.h>  
  3. /* Header for class lveyo_bcndyl_jni_opencv_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:     lveyo_bcndyl_jni_opencv_JNIOpencv
  12. * Method:    detectFace
  13. * Signature: (IILjava/lang/String;Ljava/lang/String;)[I
  14. */ 
  15. JNIEXPORT jintArray JNICALL Java_lveyo_bcndyl_jni_opencv_JNIOpencv_detectFace  
  16.   (JNIEnv *, jobject, jint, jint, jstring, jstring);  
  17.  
  18. #ifdef __cplusplus  
  19. }  
  20. #endif  
  21. #endif 
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class lveyo_bcndyl_jni_opencv_JNIOpencv */

#ifndef _Included_lveyo_bcndyl_jni_opencv_JNIOpencv
#define _Included_lveyo_bcndyl_jni_opencv_JNIOpencv
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     lveyo_bcndyl_jni_opencv_JNIOpencv
 * Method:    detectFace
 * Signature: (IILjava/lang/String;Ljava/lang/String;)[I
 */
JNIEXPORT jintArray JNICALL Java_lveyo_bcndyl_jni_opencv_JNIOpencv_detectFace
  (JNIEnv *, jobject, jint, jint, jstring, jstring);

#ifdef __cplusplus
}
#endif
#endif

2.C程序部分 按照http://www.opencv.org.cn/index.php/Template:Install安装OpenCV并配置相应的开发环境,我这里用的是VS2005,同时要将JDK中的include目录和include/win32目录都加入到VS2005的Include Files中。 新建一个win32 MFC DLL项目jniOpenCV,把刚才生成的lveyo_bcndyl_jni_opencv_JNIOpencv.h头文件加入到项目,并且修改jniOpenCV.cpp文件:

C++代码 复制代码收藏代码JAVA应用JNI调用OpenCV实现人脸检测第3张
  1. #include "stdafx.h"  
  2. #include <jni.h>  
  3. #include "lveyo_bcndyl_jni_opencv_JNIOpencv.h"  
  4. #include "cv.h"  
  5. #include "highgui.h"  
  6.  
  7. JNIEXPORT jintArray JNICALL Java_lveyo_bcndyl_jni_opencv_JNIOpencv_detectFace  
  8.   (JNIEnv *env, jobject obj, jint width, jint height, jstring cascade, jstring filename)  
  9. {  
  10.     constchar *str_cascade, *str_filename;  
  11.     str_cascade = env->GetStringUTFChars(cascade, false);  
  12.     str_filename = env->GetStringUTFChars(filename, false);  
  13.  
  14.     jintArray faceArray;  
  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.  
  31.         constint total = faces->total;  
  32.  
  33.         faceArray = env-> NewIntArray(4*total);  
  34.         jint faceBuf[4];  
  35.           
  36.         for( int i = 0; i < total; i++ )  
  37.         {  
  38.             CvRect face_rect = *(CvRect*)cvGetSeqElem( faces, i );  
  39.             int pointX = face_rect.x;  
  40.             int pointY = face_rect.y;  
  41.             int faceWidth = face_rect.width;  
  42.             int faceHeight = face_rect.height;  
  43.  
  44.             //printf("i %d, x %d, y %d, width %d, height %d\n",  
  45.                         //        i,pointX,pointY,faceWidth,faceHeight);  
  46.  
  47.  
  48.             faceBuf[0] = pointX;  
  49.             faceBuf[1] = pointY;  
  50.             faceBuf[2] = faceWidth;  
  51.             faceBuf[3] = faceHeight;  
  52.  
  53.  
  54.             env->SetIntArrayRegion(faceArray,i*4,4,faceBuf);  
  55.               
  56.         }  
  57.           
  58.         cvReleaseMemStorage( &storage );  
  59.         cvReleaseImage( &image );  
  60.     }  
  61.     cvReleaseHaarClassifierCascade( &cv_cascade );  
  62.       
  63.  
  64.     env->ReleaseStringUTFChars(cascade, str_cascade);  
  65.     env->ReleaseStringUTFChars(filename, str_filename);  
  66.     return faceArray;  
#include "stdafx.h"
#include <jni.h>
#include "lveyo_bcndyl_jni_opencv_JNIOpencv.h"
#include "cv.h"
#include "highgui.h"

JNIEXPORT jintArray JNICALL Java_lveyo_bcndyl_jni_opencv_JNIOpencv_detectFace
  (JNIEnv *env, jobject obj, jint width, jint height, jstring cascade, jstring filename)
{
	const char *str_cascade, *str_filename;
	str_cascade = env->GetStringUTFChars(cascade, false);
	str_filename = env->GetStringUTFChars(filename, false);

	jintArray faceArray;
	CvHaarClassifierCascade *cv_cascade = (CvHaarClassifierCascade*)cvLoad( str_cascade );
	IplImage *image = cvLoadImage( str_filename, 1 );
	
	if(image!=0){

		CvMemStorage* storage = cvCreateMemStorage(0);
		CvSeq* faces;

		//double t = (double)cvGetTickCount();
		/* use the fastest variant */
		faces = cvHaarDetectObjects( image, cv_cascade, storage, 1.2, 2,
                                   CV_HAAR_DO_CANNY_PRUNING, cvSize(width, height) );
		//t = (double)cvGetTickCount() - t;
        //printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );
		

		const int total = faces->total;

		faceArray = env-> NewIntArray(4*total);
		jint faceBuf[4];
		
		for( int i = 0; i < total; i++ )
		{
			CvRect face_rect = *(CvRect*)cvGetSeqElem( faces, i );
			int pointX = face_rect.x;
			int pointY = face_rect.y;
			int faceWidth = face_rect.width;
			int faceHeight = face_rect.height;

			//printf("i %d, x %d, y %d, width %d, height %d\n",
                        //        i,pointX,pointY,faceWidth,faceHeight);


			faceBuf[0] = pointX;
			faceBuf[1] = pointY;
			faceBuf[2] = faceWidth;
			faceBuf[3] = faceHeight;


			env->SetIntArrayRegion(faceArray,i*4,4,faceBuf);
			
		}
		
		cvReleaseMemStorage( &storage );
		cvReleaseImage( &image );
	}
	cvReleaseHaarClassifierCascade( &cv_cascade );
    

	env->ReleaseStringUTFChars(cascade, str_cascade);
	env->ReleaseStringUTFChars(filename, str_filename);
	return faceArray;
}

编译生成jniOpenCV.dll。此处的检测代码是根据OpenCV的文档和示例程序修改,由于本人对c++程序不是很熟练,所以对此段代码是否会有潜在危险和内存泄露不是很肯定,还请熟悉c使用的朋友帮忙检查一下。
别忘记将生成的jniOpenCV.dll文件复制到%JAVA_HOME%/bin中,如果在没安装OpenCV的机器上运行,还需要将OpenCV安装目录中bin目录下所有dll文件一起复制到%JAVA_HOME%/bin中。
3.实现JAVA的调用

Java代码 复制代码收藏代码JAVA应用JNI调用OpenCV实现人脸检测第3张
  1. package lveyo.bcndyl.jni.opencv;  
  2.  
  3. publicclass Test {  
  4.  
  5.     publicstaticvoid main(String[] args) {  
  6.           
  7.         //初始化JNI调用类JNIOpencv  
  8.         JNIOpencv open = new JNIOpencv("jniOpenCV");  
  9.  
  10.         //要检测的图片文件  
  11.         String filename = "d:/80010.jpg";  
  12.  
  13.         //OpenCv提供的人间的特征文件  
  14.         String cascade = "d:/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.                 System.out.println(temp);  
  27.             }  
  28.         }  
  29.     }  

免责声明:文章转载自《JAVA应用JNI调用OpenCV实现人脸检测》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇深入浅出Node.js(上)bat脚本学习下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

SqlAlchemy

SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。 Dialect用于和数据API进行交流,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作,如: 1 MySQL-Python 2...

使用WMI控制Windows进程 和服务

1.使用WMI控制Windows进程 本文主要介绍两种WMI的进行操作:检查进程是否存在、创建新进行 代码如下: using System; using System.Collections.Generic; using System.Text; using System.Management; using System.Threa...

[ PyQt入门教程 ] PyQt5中数据表格控件QTableWidget使用方法

如果你想让你开发的PyQt5工具展示的数据显得整齐、美观、好看,显得符合你的气质,可以考虑使用QTableWidget控件。之前一直使用的是textBrowser文本框控件,数据展示还是不太美观。其中QTableWidget是PyQt5程序中常用的显示数据表格的控件,显示的基本效果如下,有点素。。 下面开始介绍QTableWidget常用的方法以及如何使...

MVC中 DropDownList编辑默认选中的使用

MVC DropDownList编辑默认选中   DropDownList则与TextBox等控件不同,它使用的是select标记。它需要两个值:在下拉框中显示的列表,和默认选项。而自动绑定一次只能绑定一个属性,因此你需要根据需要选择是绑定列表,还是默认选项。 DropDownList扩展方法的各个重载版本“基本上”都会传递到这个方法上: ? pu...

EFCore梳理

一、CodeFirst模式 官网:https://docs.microsoft.com/zh-cn/ef/core/get-started/overview/first-app?tabs=visual-studio 下面进行一个简单的示例。 代码:https://github.com/qiuxianhu/EFCoreSummary 1、创建一个.NETCo...

Springboot 在项目启动时将数据缓存到全局变量

有写字典数据不会频繁更新,但是会频繁查询,想要减少数据库链接次数,把内容缓存到项目的全局变量中,提高方法查询速度 import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.util.HashMap; import java.util.Li...