zoukankan      html  css  js  c++  java
  • JAVA应用JNI调用OpenCV实现人脸检测

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

    Java代码 复制代码 收藏代码
    1. package lveyo.bcndyl.jni.opencv;  
    2. public class JNIBase {  
    3.       
    4.     public JNIBase(){}  
    5.       
    6.     public JNIBase(String libraryName){  
    7.         loadLibrary(libraryName);  
    8.     }  
    9.       
    10.     private static void 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代码 复制代码 收藏代码
    1. package lveyo.bcndyl.jni.opencv;  
    2.  
    3. public class JNIOpencv extends JNIBase{  
    4.       
    5.     public JNIOpencv (String libraryName){  
    6.         super(libraryName);  
    7.     }  
    8.       
    9.     public JNIOpencv(){  
    10.         System.loadLibrary("jniOpenCV");  
    11.     }  
    12.  
    13.     public native int[] 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代码 复制代码 收藏代码
    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++代码 复制代码 收藏代码
    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.     const char *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.         const int 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代码 复制代码 收藏代码
    1. package lveyo.bcndyl.jni.opencv;  
    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 = "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.     }  
  • 相关阅读:
    javascript闭包函数
    取消后续内容执行
    vs安装失败,发生严重错误,错误号:Error 0x80070643
    ref
    深入类的方法
    学习过程中的三个小小程序
    SQL Server 中存储过程的练习
    SQL Server系统存储过程
    SQL-server的事务,视图和索引
    用C#,SQL Server编写的音乐播放软件
  • 原文地址:https://www.cnblogs.com/andyzhao365/p/2225507.html
Copyright © 2011-2022 走看看