我正在开发一个可检测页面边缘并检测并解析该页面QR码的应用程序。 OpenCV使用“ JavaCameraView”从摄像机提供视频,而QR解析是通过'com.google.android.gms:play-services-vision:15.0.2'
库完成的。
这可以在我的手机(带有Android 8的Huawei P9 Lite 2017)上运行,但在其他一些手机(例如,带有Android 7.1.1,API 25的Samsung SM-J510FN)上则无法使用。
我的猜测是相机返回的帧尺寸不同,这就是无法解析QR的原因(华为相机返回的帧为960x720,而三星相机返回的帧为720x720)。
以下是获取框架然后尝试检测QR的代码(然后进行边缘检测并拍摄页面图片(此处未显示)):
@Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
if (!isOpenCvFrameDimensionsObtained) {
openCvFrameHeight = inputFrame.rgba().height();
openCvFrameWidth = inputFrame.rgba().width();
isOpenCvFrameDimensionsObtained = true;
screenToOpenCvScreenWidthToFrameHeightRatio = (double) screenWidth / openCvFrameHeight;
screenToOpenCvScreenHeightToFrameWidthRatio = (double) screenHeight / openCvFrameWidth;
}
Mat gray = inputFrame.gray();
Mat dst = inputFrame.rgba();
Mat tmp = new Mat(openCvFrameHeight, openCvFrameWidth, CvType.CV_8U, new Scalar(4));
Imgproc.cvtColor(dst, tmp, Imgproc.COLOR_RGB2BGRA);
//try extracting the QR code from the frame
if (!isQrObtained) try {
Bitmap bmp;
bmp = Bitmap.createBitmap(tmp.cols(), tmp.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(tmp, bmp);
Frame frame = new Frame.Builder().setBitmap(bmp).build();
SparseArray<Barcode> barcodes = detector.detect(frame);
if (barcodes != null && barcodes.size() > 0) {
barcode = barcodes.valueAt(0);
Gson gson = new Gson();
qrDetectionResult = gson.fromJson(barcode.displayValue, QrDetectionResult.class);
runOnUiThread(() -> Toast.makeText(this, "QR Code Scanned", Toast.LENGTH_SHORT).show());
isQrObtained = true;
Log.i("Barcode", barcode.displayValue);
}
} catch (Exception e) {
Log.d("Exception", e.getMessage());
}
之所以看到代码块screenToOpenCvScreenWidthToFrameHeightRatio = (double) screenWidth / openCvFrameHeight;
screenToOpenCvScreenHeightToFrameWidthRatio = (double) screenHeight / openCvFrameWidth;
,是因为OpenCV摄像机侧向旋转,这会导致更多问题。
问题出现在这里:
SparseArray<Barcode> barcodes = detector.detect(frame);
此行实际上返回我的华为上的条形码,但在另一部手机上返回“ {}”。
有人知道为什么会这样吗?我的直觉是已收到QR,但QR失真,因此无法识别,但我不确定。更改inputFrame的大小(高度,宽度)并不能解决问题。
请注意,OpenCV中的JavaCameraView很旧,并且使用了不赞成使用的Camera(而不是较新的Camera2 API)。