最近在开发一款人脸比对的项目,使用RxJava1.x实现的比对逻辑
场景如下:
定时抓取摄像头预览图片进行比对 符合条件时使用 takeUntil操作符停止发射数据 然后使用timer过一定时间后重启比对 但是每次重启后都会获取上次最后一张图片去比对 不晓得原因是什么 在每次重启前都清空了订阅事件的
直接上代码:
/**
* 比对程序
*/
@Override
public void detect() {
// 1. 过滤 数据库中的人脸数量不为空 若为空不能有效比对 直接过滤掉
if (mPersonList.isEmpty()) return;
mSubscription = Observable
.interval(0, 500, TimeUnit.MILLISECONDS)
.onBackpressureDrop() // 使用背压策略:总是接收最新的
// 2. 获得预览图片
.map(new Func1<Long, Bitmap>() {
@Override
public Bitmap call(Long aLong) {
KLog.e("aLong:" + aLong);
return mView.takePhoto();
}
})
// 3. 过滤掉为null的图片
.filter(new Func1<Bitmap, Boolean>() {
@Override
public Boolean call(Bitmap bitmap) {
return bitmap != null;
}
})
// 4. 将图片保存在对象DetectSuccessInfo
.flatMap(new Func1<Bitmap, Observable<DetectSuccessInfo>>() {
@Override
public Observable<DetectSuccessInfo> call(Bitmap bitmap) {
DetectSuccessInfo detectSuccessInfo = new DetectSuccessInfo();
detectSuccessInfo.setDetectBitmap(bitmap);
return Observable.just(detectSuccessInfo);
}
})
.observeOn(Schedulers.io()) // 运行在子线程
// 5. 提取图片中的人脸特征 无人脸时特征值为----""
.flatMap(new Func1<DetectSuccessInfo, Observable<DetectSuccessInfo>>() {
@Override
public Observable<DetectSuccessInfo> call(DetectSuccessInfo
successInfo) {
String[] feature_ = FeatureUtils.extractFeature_(successInfo
.getDetectBitmap());
successInfo.setRect(feature_[0]);
successInfo.setFeature(feature_[1]);
return Observable.just(successInfo);
}
})
// 6. 过滤条件:图片提取的人脸特征不为空
.filter(new Func1<DetectSuccessInfo, Boolean>() {
@Override
public Boolean call(DetectSuccessInfo successInfo) {
return !TextUtils.isEmpty(successInfo.getFeature());
}
})
// 7. 标定人脸相框
.doOnEach(new Action1<Notification<? super DetectSuccessInfo>>() {
@Override
public void call(Notification<? super DetectSuccessInfo> notification) {
DetectSuccessInfo successInfo = (DetectSuccessInfo) notification
.getValue();
Bitmap bitmap = successInfo.getDetectBitmap();
int[] result = StringUtils.split2Int(successInfo.getRect());
mView.convertCoordinate(result[0], result[1], result[2],
result[3], bitmap.getWidth(), bitmap.getHeight());
}
})
// 8. 过滤条件:和数据库查询的人脸集合中的每一个人脸进行比对 选取最大值且有匹配成功的对象
.map(new Func1<DetectSuccessInfo, DetectSuccessInfo>() {
@Override
public DetectSuccessInfo call(DetectSuccessInfo successInfo) {
float[] fea = StringUtils.split2Float(successInfo.getFeature());
List<Object> objects = FeatureUtils.matchWithDbData(mPersonList,
fea);
if (!objects.isEmpty()) {
successInfo.setScore((Float) objects.get(0));
successInfo.setPerson((Person) objects.get(1));
successInfo.setSuc_time(System.currentTimeMillis());
}
return successInfo;
}
})
// 9. 过滤 只有分数大于阈值的才可以继续进行 小于则继续下一次循环开始抓取图片
.filter(new Func1<DetectSuccessInfo, Boolean>() {
@Override
public Boolean call(DetectSuccessInfo successInfo) {
KLog.e("filter:" + successInfo.getScore());
return successInfo.getScore() >= 50;
}
})
// 10. 判断匹配成功的唯一标准DetectSuccessInfo score属性且大于阈值
// 成功则停止发送数据
.takeUntil(new Func1<DetectSuccessInfo, Boolean>() {
@Override
public Boolean call(DetectSuccessInfo successInfo) {
KLog.e("takeUntil:" + successInfo.getScore());
return successInfo.getScore() >= 50;
}
})
// 11. 每次匹配成功 开启子线程入库
.doOnNext(new Action1<DetectSuccessInfo>() {
@Override
public void call(final DetectSuccessInfo successInfo) {
Schedulers.io().createWorker().schedule(new Action0() {
@Override
public void call() {
DetectRecord record = new DetectRecord();
record.setDetectScore(String.valueOf(successInfo.getScore
()));
record.setDetectTime(successInfo.getSuc_time());
record.setPerson_id(successInfo.getPerson().get_id());
record.setDetectImage(ImageUtils.BitmapToBytes(successInfo
.getDetectBitmap()));
mDaoManager.insertRecord(record);
KLog.e("保存比对数据入库");
}
});
}
})
.subscribeOn(AndroidSchedulers.mainThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<DetectSuccessInfo>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
KLog.e("Error:" + e.getMessage());
}
@Override
public void onNext(DetectSuccessInfo successInfo) {
// 12. 匹配成功刷新页面
mView.me_succeed(successInfo);
}
@Override
public void onStart() {
super.onStart();
mView.resetUI();
}
});
KLog.e("detect----subscription:" + mSubscription);
addSubscribe(mSubscription);
}
重启代码:
/**
* 比对成功后延时1.5秒重新开始匹配
*/
@Override
public void reStart() {
Subscription subscription = Observable.timer(1500, TimeUnit.MILLISECONDS)
.compose(SchedulersCompat.<Long>applyIoSchedulers())
.subscribe(new Action1<Long>() {
@Override
public void call(Long aLong) {
cleanSubscribe(mSubscription);
// 重新开始匹配
mView.resetUI();
detect();
}
});
addSubscribe(subscription);
}
在线求大神指点!!!