参考博客:https://www.cnblogs.com/cq-jiang/p/7823462.html
项目需求,Android客户端作为AirPlay接收端,在开启airPlay的时候后台开启摄像头,当捕捉到人脸的时候将这一帧图像传到face++进行人脸分析。airPlay接收端可集成xindawn的airplay,GitHub地址 https://github.com/xindawndev/xindawn-android-airplay-mirroring-sdk。
1.后台开启摄像头
基本都是将预览界面的Activity主题设为透明,并将view大小设为1dp。
<style name="touming" parent="android:Theme.NoTitleBar">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">@android:style/Animation</item>
<item name="android:windowContentOverlay">@null</item>
</style>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="1dp"
android:layout_height="1dp"
android:background="@color/transparent"
android:orientation="vertical">
2.打开摄像头
Android主板不像手机,外接USB摄像头不能保证是前置或者是后置,需要注意异常捕获。
try {
mCamera = Camera.open(CameraInfo.CAMERA_FACING_BACK);// 可以根据ID使用不同的摄像头
} catch (Exception e) {
e.printStackTrace();
}
if (mCamera == null) {
try {
mCamera = Camera.open(CameraInfo.CAMERA_FACING_FRONT);// 可以根据ID使用不同的摄像头
} catch (Exception e) {
e.printStackTrace();
}
}
3.摄像头预览尺寸
摄像头会支持不同的预览尺寸,需要根据项目自行确定,由于我的项目需求是不需要预览的,所以setPreview固定写了0。
mCamera.setPreviewCallback(this);
Camera.Parameters parameters = mCamera.getParameters();
List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();//获得相机预览所支持的大小。
Camera.Size size1 = previewSizes.get(0);//default 2,4
parameters.setPreviewSize(size1.width, size1.height);
mCamera.setParameters(parameters);
mCamera.startPreview();
4. 获得预览流识别是否有人脸
onPreviewFrame里的数据流是nv21格式的,直接转成bitmap会失败,所以要先转成yuvimage再转成bitmap
Camera.Size size = mtCamera.getParameters().getPreviewSize();
YuvImage yuvImage = new YuvImage(mData, ImageFormat.NV21, size.width, size.height, null);
mData = null;
yuvImage.compressToJpeg(new Rect(0, 0, size.width, size.height), 100, mBitmapOutput);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;//必须设置为565,否则无法检测
// 转换成图片bitmap = BitmapFactory.decodeByteArray(mBitmapOutput.toByteArray(), 0,mBitmapOutput.toByteArray().length, options);
if(bitmap!=null){
mBitmapOutput.reset();
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), mMatrix, false);
}
在这里我遇到一个问题,我用的Android主板转换的bitmap有问题,图片全是绿色,最后联系主板厂商给了一个新的so文件解决的,遇到同样问题的同志们可以尝试一下联系主板厂商,so文件目录为system/lib(还有一个lib64)/hw/camera.uranus.so。
Android自带API识别人脸:
FaceDetector.Face[] faces = mFaceHelper.findFaces(bitmap);
ogMsg = logMsg + ",==识别人脸时间:"+(System.currentTimeMillis()- endTime)+",mOrienta:"+mOrienta+",w:"+mBitmap.getWidth()+",h:"+mBitmap.getHeight()+",degrees:"+degrees;// width:"+mBitMap.getWidth()+",height:"+mBitMap.getHeight()+",
MyLogger.getInstall().i(TAG+logMsg);
FaceDetector.Face facePostion = null;
int index = 0;
if(faces!=null){
for (FaceDetector.Face face : faces) {
if (face == null) {
bitmap.recycle();
bitmap = null;
mBitmapOutput.close();
mBitmapOutput = null;
MyLogger.getInstall().e("无人脸");
break;
} else {
MyLogger.getInstall().e("有人脸");
break;
}
}
}
5.使用face++进行人脸分析
这里我使用的是上传图片进行分析,okhttp同时提交表单和文件
HashMap<String, String> requestParam=new HashMap<String, String>();
requestParam.put("api_key", "xxxxxxx");
requestParam.put("api_secret", "xxxxxxx");
requestParam.put("return_landmark", "1");
requestParam.put("return_attributes", "gender,age,smiling,eyestatus,headpose,blur,eyestatus,emotion,facequality,ethnicity,beauty,mouthstatus,eyegaz e,skinstatus");
PostUtils.sendPostRequest(requestParam,new File("mnt/sdcard/1.png"),
"https://api-cn.faceplusplus.com/facepp/v3/detect", new Callback() {
@Overridepublic void onResponse(Call arg0, Response arg1) throws IOException {
// TODO Auto-generated method stub
String data=arg1.body().string();
System.out.println("-------"+data);
}
@Override
public void onFailure(Call arg0, IOException arg1) {
// TODO Auto-generated method stub
}
});
public class PostUtils {
private static OkHttpClient okHttpClient;
//异步调用
public static void sendPostRequest(HashMap<String, String> requestParam,File file,String url,Callback callback){
if (okHttpClient==null) {
okHttpClient = new OkHttpClient();
}
MultipartBody.Builder builder=new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
Set<Entry<String,String>> entrySet = requestParam.entrySet();
for (Entry<String, String> entry : entrySet) {
builder.addFormDataPart(entry.getKey(), entry.getValue());
}
builder.addFormDataPart("image_file", file.getName(), RequestBody.create(MediaType.parse("file/*"), file));
Request request=new Request.Builder()
.url(url)
.post(builder.build())
.build();
okHttpClient.newCall(request).enqueue(callback);
}
}
有什么问题还请大家多多指正~~~