fastcv 2 —— fastcorner例子浅析

来源:互联网 发布:php打表格 编辑:程序博客网 时间:2024/06/08 03:48

看高通的Vuforia 或者 fastcv,或者说看所有的使用NDK编程的应用,我一般都是按照两层来看的。一个Java层,一个Native层。今天就从这两层来简单分析一下。

一.java层

我的理解是java层又可以分为application层和framework层。fastcorner的app层主要提供UI界面、camera调用,framework层提供接口函数,实现native层与java层之间的数据通信。fastcorner这个例子中有很多这样的接口函数。分别实现各自的功能,大家从函数名称或者源码注释上可以看出实现的什么功能。这里我只简单介绍几个例子。

例如在FastCVSample这个类中

public native float getCameraFPS();//获取帧速
private native void setGaussianEnable(boolean enableGaussian);//设置高斯滤波

private native int getNumCorners();//获取角点数量

还有一个最重要的方法,这个是角点检测的实现类。其中data是通过camera获取实时的视频帧的数据,w,h分别为视频帧的高和宽

public native void update( byte[] data, int w, int h );

fastcvcorner这个例子中有个很特别的地方就是,他通过OpenGL来达到对视频帧的渲染效果。这个让我想到了高通AR SDK模块中的一个模块。

Video Background Renderer

The video background renderer module renders the camera image stored in the state object. The performance of the background video rendering is optimized for specific devices.

看fastcv,结合高通ARSDK一起,你会有很多收货的。

FastCVSampleRenderer类中有这些本地的方法,例如

   public native void render();//Video Background Renderring
   public native void cleanup();//free 内存释放
   public native float getGPUFPS();//获取fps

接下来主要讲public native void update( byte[] data, int w, int h );这个方法的实现

这个是在FastCVSample.h定义的方法,其中的参数前面说过了,对于env和obj,不清楚的童鞋先去看看jni有关知识,否则看这些会比较费解的,:)

   JNIEXPORT void JNICALL Java_com_qualcomm_fastcorner_FastCVSample_update
   (
      JNIEnv*     env, 
      jobject     obj, 
      jbyteArray  img, 
      jint        w, 
      jint        h
   );

在FastCVSample.cpp中实现这个方法

jbyte*            jimgData = NULL;

jimgData = env->GetByteArrayElements( img, &isCopy );

获取视频帧的数据。

获取之后要对其进行格式转换,因为摄像头获取的是YUV420格式的,要将其转换成RGB565。这个又可以联想到高通ARSDK。

Image Converter

The pixel format converter converts from the camera format (e.g., YUV12) to a format suitable for OpenGL ES rendering (e.g., RGB565) and for tracking (e.g., luminance) internally.

转换之前,先将获取的数据

转换成uint8_t

uint8_t*  pJimgData = (uint8_t*)jimgData;

因为fcvColorYUV420toRGB565u8()与其他fastcv函数要求这种格式的。

之后判断是否采用RGB还是灰度格式?

这个也是通过本地方法来设置的

private native void setViewFinderEnable(boolean enableViewFinder);

JNIEXPORT void JNICALL 
   Java_com_qualcomm_fastcorner_FastCVSample_setViewFinderEnable
(
   JNIEnv*  env, 
   jobject  obj,
   jboolean disableViewFinder
)
{
   state.disableVF = (bool)disableViewFinder;
}

使用fcvColorYUV420toRGB565u8进行格式转换

fcvColorYUV420toRGB565u8(
         pJimgData,
         w,
         h, 
         (uint32_t*)renderBuffer );

数据格式和图像格式转换完成之后,调用

updateCorners( (uint8_t*)pJimgData, w, h );进行角点检测了。

角点检测之前对图像进行downscale操作,有点类似图形金字塔,减小计算量,之后进行高斯过滤,最后才用fast9x进行角点检测。

downscale操作:

fcvScaleDownu8( (uint8_t*)data,
                      w, 
                      h,
                      state.scaledImgBuf,
                      state.scaledImgWidth,
                      state.scaledImgHeight );

高斯过滤:

fcvFilterGaussian3x3u8( dataBuf,
                              dataBufWidth,
                              dataBufHeight,
                              state.blurredImgBuf,
                              0 );

角点检测:

fcvCornerFast9u8( (uint8_t*)dataBuf,
                     dataBufWidth, 
                     dataBufHeight,
                     0,
                     state.cornerThreshold, 
                     7,
                     state.corners,
                     MAX_CORNERS_TO_DETECT,
                     &state.numCorners );

检测之后进行角点绘制

drawCorners( state.corners, state.numCorners );

最后释放内存

env->ReleaseByteArrayElements( img, jimgData, JNI_ABORT );

最后,虽然这个例子实现的效果很简单,但是里面的内容还是很丰富的。没想到里面居然还有Video Background Renderer部分,算是个意外的惊喜吧。跟Opencv相比,实现的步骤要繁琐一点,但是效果肯定要好。所以后面打算用fastcv再实现MAR,看看跟Opencv相比怎么样,:)有兴趣的朋友可以一起讨论!

本文只无任何商业用途,特此声明!