JAVA应用JNI调用OpenCV实现人脸检测(2)--原创

这篇博客展示了如何使用Java的JNI技术调用OpenCV库实现人脸检测。通过加载DLL,Java代码与C++代码交互,进行图像处理和面部检测。C++部分涉及到OpenCV的图像加载、灰度化、直方图均衡化以及Haar级联分类器进行对象检测。

Java代码:

public class FindViolajones {


public DET_PARAMS DetParams=new DET_PARAMS();
private native int[] fViolaJonesFindFace1(String sImage,String sDataDir);
private native void CloseViolaJones ();
static {
System.loadLibrary("ViolaJones");
}

C++代码:

// ViolaJones.cpp : Defines the entry point for the DLL application.
//
#include "string.h"
#include "stdafx.h"
#include <jni.h>  
#include "cv.h"  
#include "highgui.h" 
#include "com_vio_FindViolajones.h"




// accurate but slow: these values are recommended in opencvref_cv.htm
static const double SCALE_FACTOR   = 1.1;
static const int    MIN_NEIGHBORS  = 3;
static const int    DET_FLAGS = 0;


static const char *CASCADE_NAME = "haarcascade_frontalface_alt2.xml";


static CvHaarClassifierCascade *pgCascade;
static CvMemStorage *pgStorage;
/*
 * Class:     com_vio_FindViolajones
 * Method:    fViolaJonesFindFace1
 * Signature: (Ljava/lang/String;[C)[I
 */
JNIEXPORT jintArray JNICALL Java_com_vio_FindViolajones_fViolaJonesFindFace1
  (JNIEnv *env, jobject obj, jstring sImage, jstring sDatadir)
{
const char * str_sImage ,* str_sDatadir;
jintArray faceArray;
str_sImage =  env->GetStringUTFChars(sImage, false); 
str_sDatadir = env->GetStringUTFChars(sDatadir,false);
jint faceBuf[4];
if (!pgCascade) // first time? if so, must init detector data structures
    {
char sCascadePath[256];
    strcpy(sCascadePath,str_sDatadir);
strcat(sCascadePath,"//");
strcat(sCascadePath,CASCADE_NAME);
    pgCascade = (CvHaarClassifierCascade*)cvLoad(sCascadePath, 0, 0, 0);
    if(!pgCascade)
    printf("can't load %s", sCascadePath);
    pgStorage = cvCreateMemStorage(0);
    if (!pgStorage)
    printf("out of memory (cvCreateMemStorage failed)");

    env->ReleaseStringUTFChars(sDatadir, str_sDatadir);
}
    cvClearMemStorage(pgStorage);
    IplImage* pImage = cvLoadImage(str_sImage, CV_LOAD_IMAGE_GRAYSCALE);
    cvResize(pImage, pImage, CV_INTER_LINEAR);
    cvEqualizeHist(pImage, pImage);


    CvSeq* pFaces = cvHaarDetectObjects(pImage, pgCascade, pgStorage,
                    SCALE_FACTOR, MIN_NEIGHBORS, DET_FLAGS,
                    cvSize((pImage->width)/4,
                    (pImage->width)/4));




    if (pFaces->total)  // success?
        {
    // get most central face


faceArray = env-> NewIntArray(4*pFaces->total);
    int iSelectedFace = 0;
    double MaxOffset = FLT_MAX; // max abs dist from face center to image center
    for (int iFace = 0; iFace < pFaces->total; iFace++)
        {
        CvRect* r = (CvRect*)cvGetSeqElem(pFaces, iFace);
        double Offset = fabs(r->x + r->width/2.0 - pImage->width/2.0);
        if (Offset < MaxOffset)
            {
            MaxOffset = Offset;
            iSelectedFace = iFace;
            }
        }
    CvRect* r = (CvRect*)cvGetSeqElem(pFaces, iSelectedFace);


    // convert x and y (OpenCV coords at corner of face box) to cartesian
    // coords (with x,y at center of face box)


    int x = r->x - pImage->width/2 + r->width/2;
    int y = pImage->height/2 - r->y - r->height/2;


    int width = r->width;
    int height = r->height;


faceBuf[0]=x;
faceBuf[1]=y;
faceBuf[2]=width;
faceBuf[3]=height;


env->SetIntArrayRegion(faceArray,0,4,faceBuf); 
    }
    cvReleaseImage(&pImage);
    cvReleaseMemStorage( &pgStorage );


    env->ReleaseStringUTFChars(sImage, str_sImage);  
    env->ReleaseStringUTFChars(sDatadir, str_sDatadir); 


    return faceArray;   // return true on success


}


/*
 * Class:     com_vio_FindViolajones
 * Method:    CloseViolaJones
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_vio_FindViolajones_CloseViolaJones
  (JNIEnv *, jobject)
{
if (pgCascade)
    {
    cvReleaseHaarClassifierCascade(&pgCascade);
    cvReleaseMemStorage(&pgStorage);
    pgCascade = NULL;
    }
}


BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
)
{
    return TRUE;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值