科大讯飞开发者平台上对外开放了语音和人脸识别的SDK。现在分享的人脸识别功能。
讯飞人脸识别的demo中有的在线人脸识别、离线人脸识别和视频检测三个功能。为了更好的理解,我就简单介绍这三个功能的作用。
人脸识别:主要的功能有人脸注册、人脸检测和人脸验证。在线和离线只是实现的方式不一样,其作用都一样的。
视频检测:就是开启摄像头,检测摄像头的画面是否是一个人脸。
对于这三个功能在它的demo中都很详细,这里就不多说。我现在分享的是先用视频检测功能获取到摄像头数据(某一帧的数据),然后用这张数据去进行人脸识别。
步骤1.集成SDK(见讯飞官方Doc)。
在看文档时,我并没有看到讯飞给开发者提供的返回的json格式。所以为了偷懒,可以将FaceRect、FaceUtil和ParseResult类拷过来(可以自己打印后解析)。
步骤2.拷贝FaceRect、FaceUtil和ParseResult类到自己的工程里。
步骤3.具体实现;假设已经成功完成了步骤1和步骤2。
新建一个PreviewActivity用来预览和实现验证功能。这个PreviewActivity的代码大部分都是来自讯飞FaceDemo的com.iflytek.facedemo.VideoDemo类,因为这个类实现了预览和人脸检测功能,这里只需要加上验证功能就可以了。验证有在线和离线,这里就说下在线验证的了。在线验证是要借助com.iflytek.cloud.FaceRequest这个类。照着文档建一个FaceRequest,mFaceRequest = new FaceRequest(this);设置参数之后调用mFaceRequest.sendRequest(mImageData, mRequestListener)就可以了。
那个这个参数要设置什么参数呢?人脸注册和其他功能需要的参数都不一样(详情见官方文档),但是都需要一个保存了图片数据的byte[]数组。这篇博客最主要的分享的也是怎
么样来获取这个byte[]。
细心的人也许很容易发现我们在设置相机callback时(mCamera.setPreviewCallback()),可以在onPreviewFrame()回调中获取到一个byte[],但是,这真的是我们需要的那个数
据吗?没错,这个数据确实是相机一帧的数据。但是如果尝试用这个数据来进行处理的话(人脸注册或是验证),你会发现并没有成功,再尝试用这个数据去转成bitmap的话,返
回的null。问题又是在哪呢?
不要急,答案马上揭晓。我们再留意一下相机的设置。
Parameters params=mCamera.getParameters();
params.setPreviewFormat(ImageFormat.NV21);
params.setPreviewSize(PREVIEW_WIDTH,PREVIEW_HEIGHT);
mCamera.setParameters(params);
发现什么了吗?是的,我们现在采集到的一帧的格式是NV21的,并不是RGB或者ARGB。
问题已经出来了,那么只要将NV21的数据转RGB就行了。这里有个网上找的方法。
public static int[] convertYUV420_NV21toRGB8888(byte[] data, int width, int height) {
int size = width * height;
int offset = size;
int[] pixels = new int[size];
int u, v, y1, y2, y3, y4;
// i percorre os Y and the final pixels
// k percorre os pixles U e V
for (int i = 0, k = 0; i < size; i += 2, k += 2) {
y1 = data[i] & 0xff;
y2 = data[i + 1] & 0xff;
y3 = data[width + i] & 0xff;
y4 = data[width + i + 1] & 0xff;
u = data[offset + k] & 0xff;
v = data[offset + k + 1] & 0xff;
u = u - 128;
v = v - 128;
pixels[i] = convertYUVtoRGB(y1, u, v);
pixels[i + 1] = convertYUVtoRGB(y2, u, v);
pixels[width + i] = convertYUVtoRGB(y3, u, v);
pixels[width + i + 1] = convertYUVtoRGB(y4, u, v);
if (i != 0 && (i + 2) % width == 0)
i += width;
}
return pixels;
}
private static int convertYUVtoRGB(int y, int u, int v) {
int r, g, b;
r = y + (int) 1.402f * v;
g = y - (int) (0.344f * u + 0.714f * v);
b = y + (int) 1.772f * u;
r = r > 255 ? 255 : r < 0 ? 0 : r;
g = g > 255 ? 255 : g < 0 ? 0 : g;
b = b > 255 ? 255 : b < 0 ? 0 : b;
return 0xff000000 | (b << 16) | (g << 8) | r;
}
转出之后再转图片(bitmap)就行了,有部分相机方向不对需要相应的设置图片的方向,图片方向对验证或者注册很重要。旋转图片的方法有很多很多人也知道,这里就不再赘述了。
在线视频的主要技术是不是就是数据格式呢?哈哈!
demo传不上,不知道为什么会传不上。