最近在弄:使用第三方SDK检测给定图片上人脸个数,现在已告一段落,现在想要把自己做的过程中的心得体会以及走过哪些弯路,理一理。
拿到第三方给的SDK,目录里面包含libs,sourceCode和readme三个,如下图1中所示
1. 没读懂readme以及对没读懂的原因进行分析
readme里面内容解释:
第一条:使用现成的so库文件和jar包。如何使用,
place the following files under /libs
libs/halibutsdk.jar
第二条:源码: 如果要自己build的话
sourceCode/jni/facedetection/*
第二条的意思是如果你想要自己动手生成so库文件的话,使用的源码在目录 sourceCode/jni/face
detection/*和sourceCode/src/com/arcsoft/facedetection/*
第三条:给出一个主流程,确切的说是调用流程。
//***********************************************************************************************************************
现在的版本采用的就是readme里面第一条描述的方法:使用现成的so库文件和jar包.
测试工程的目录如下:
仔细观察此目录,发现测试工程中并没有jni文件夹,只是按照readme里面第一条指示:在对应目录下放置相应的so库和jar包。现在在MainActivity.java里面就可以调用libface_detection.so里面的方法了,当然前提是要把so加载进来,此程序中加载so的代码在halibutsdk.jar里面。
想用so就得有jni目录,并不完全是这样的,这得分情况:
在此之前先抛出一个问题:
jni目录是用来干嘛的或者说为什么要建jni目录?
jni目录是用来生成so的。
第一种:得自己动手生成so,此时就需要自己在工程中建立jni目录,编写Android.mk文件,还要把相应的c/c++文件,头文件,jni头文件以及jni头文件对应的c/c++实现文件等等,也就是说要把生成so库所需要的东西都放在jni目录下,然后使用ndk生成so。
第二种:手头有现成的so,也就是说有人提供了一个so,就是我这里的这种情况,这种情况就会方面很多,节省了生成so的过程。此时只需要把so加载进来,在程序中直接调用库中的方法就可以了。
通过上述分析就解释了为什么没读懂readme文件,原因就在于认为“想用so就得有jni目录”
想用so就得有jni目录”、CEO催的又挺紧的情况下可能会动手建立Jni目录,写Android.mk等,钻到生成so的道路上来,还好我一直坚持:一定要想清楚了再动手,少走了弯路。还有当时CEO催的紧,让自己乱了阵脚,以后不能这样,要稳住。
2. 使用OpenCV读取图片内容
读取图片内容的代码本应该放在一个回调函数里,但是一开始并不知道,而是把代码放在了onCreate里面,这就导致出各种各种的错误,然后我就一直看控制台上报的错误信息,然后一直改BUG,完全没有意识到代码放错位置了,而且控制台上报读取图片代码错误后,我直接百度查看解决方法,但是此时的解决方法不是把相应代码放在回调函数里面,然后修改过后不报读取错误了,但是还报其他错误,我就接着改。这时候我们头儿看我的代码,他直接打断点,定位哪句话出错了,定位到是读取图片的这句代码Mat image = Highgui.imread(strFilePath);出错了后,然后又知道imread是OpenCV的东西,就去找OpenCV中的samples,看OpenCV是如何读入图片的,几乎运行了 OpenCV中的所有sample,发现没有一个是针对一张图片进行检测的(OpenCV是用来检测人脸的),都是直接从摄像头取数据,找不到是针对一张图片的,然后就看OpenCV中sample里的代码,发现了 BaseLoaderCallback回调函数,然后就把onCreate里面的代码拷贝到该回调函数内,运行后,读取图片内容的那句代码断点调试过了,而且还能看到读取到的图片对象image中有数据。
通过上面的过程我想反问自己一句:我为什么没有很强的意识要去看OpenCV里面的例子呢?而且当我看了OpenCV里面的例子后,为什么没有寻找到任何的蛛丝马迹呢?
3. 代码不动的前提下,有些图片上有人脸但检测不到,有些图片就可以正确检测到图片上人脸数。
我用公司提供的一大推图片,都不能正确的检测到人脸数,图片尺寸相对小的,报SDK中初始化错误;图片尺寸相对大些的,检测到人脸是0,但是图片上明明有1张脸啊,我分析来分析去,差点动手要用sourceCode里面的jni重新生成so,但是又想到公司有人说联想那边已经跑通了,那就说明这个so是能用的啊,然后我就自己拍了一张照片,然后检测这张照片上的人脸数,居然显示检测到1张脸。等到我把检测大量图片的代码添加到工程后,就分析为什么公司提供的图片检测不到人脸(提供的图片上有人脸)。