水表有多个红色指针,也有一个黑色的梅花型指针。
如下图是一种典型的水表,有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
[] fpsRanges = chars.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES); - for (Range
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
rang = new Range(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左右,完全达到了要求。