水表有多个红色指针,也有一个黑色的梅花型指针。
如下图是一种典型的水表,有4个红色的指针,4个中最上面那个红色是最快速的。中间部分的黑色齿轮转动更快。
我们基于安卓手机做的水表检测有多种模式,在固定的时间内进行检测,一种模式是检测红色指针的旋转角度(圈数),另一种模式是检测黑色梅花轮转过的齿数。
通常手机相机的帧率是30fps,根据香农采样定律,帧率实际上决定了对旋转仪表的分辨率。30fps可以满足大部分情况的要求。如果想测试水表的超大流速,30帧率是不足以分辨的,会带来误差。水表检测以前常用的还是基于工业相机+PC机的模式,工业相机虽然像素较低,但帧率较高。然而,手机作为一种新型计算方式,具有不可比拟的优势,正如我的小文所论述的:工业机器视觉的趋势--以手机为终端
那么,安卓手机有没有可能使用更高的帧率呢?答案是肯定的。
虽然可以,也不是那么容易。第一个是需要找到合适的手机,从成本的角度,如果大量部署不能太贵,所幸检测用的手机并不需要很多高级功能,比如不需要5G——甚至4G也不需要,只需要自带的WiFi在局域网内和控制机通信即可。要找到并不容易,有的手机号称可以60fps,实际并不行,经过多台不同手机的试验,仅发现 OPPO K9s 5G 可以支持。
需要修改 JavaCamera2View.java,如果想把代码写的通用一些,应该先检测相机是否具有60fps的能力:
if (mCameraID != null) {
// 2022-05-19 bluesen added 60fps check
for (String idStr : camList) {
Log.i("Range idStr", idStr);
CameraCharacteristics chars = manager.getCameraCharacteristics(idStr);
int deviceLevel = chars.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
// must return: INFO_SUPPORTED_HARDWARE_LEVEL_FULL, =1
Log.i(LOGTAG, "deviceLevel: " + deviceLevel);
Range<Integer>[] fpsRanges = chars.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
for (Range<Integer> range : fpsRanges) {
Log.i("Range", range.toString());
if (range.getUpper() == 60){
mMaxFps = 60;
}
}
// 60fps check end
}
Log.i(LOGTAG, "Opening camera: " + mCameraID);
manager.openCamera(mCameraID, mStateCallback, mBackgroundHandler);
}
但这段代码不会起作用,因为返回的帧率并没有60的数值。
还好,即使没有,OPPO K9s 仍然可以强行设置为60fps,我的代码mMaxFps我已经强制设成整数值 60,下面是调用安卓sdk进行实际设置 :
// 2022-05-19 bluesen.zhu added 60fps set
if(mMaxFps >= 60) {
Range<Integer> rang = new Range<Integer>(mMaxFps, mMaxFps);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, rang);
Log.i(LOGTAG, "set CONTROL_AE_TARGET_FPS_RANGE 60");
}
// 60fps set end.
然后我们在设置机捕获控件的时候打开show_fps,这样就会在控件的左上角以蓝色小字显示当前实际的帧率:
<org.opencv.android.JavaCamera2View
android:layout_width="fill_parent"
android:layout_height="fill_parent"
app:show_fps="true"
android:id="@+id/main_surface" />
运行的时候会发现帧率在60左右,完全达到了要求。