Java 条形码Google Vision API检查检测到的条形码是否在区域内
我无法检测条形码是否在指定区域内。出于测试目的,相机源预览和曲面视图具有相同的大小Java 条形码Google Vision API检查检测到的条形码是否在区域内,java,android,barcode,Java,Android,Barcode,我无法检测条形码是否在指定区域内。出于测试目的,相机源预览和曲面视图具有相同的大小1440x1080,以防止相机和视图之间的缩放。即使我看到QR码不在代表图像的框中,我也会得到肯定的检查。怎么了 假阳性检查 贫乏 公共类扫描活动扩展了AppCompatActivity{ 私有静态最终字符串标记=“ScannerActivity”; private SurfaceView mSurfaceView;//其大小在XML中强制为1440x1080 私人摄像源mCameraSource; privat
1440x1080
,以防止相机和视图之间的缩放。即使我看到QR码不在代表图像的框中,我也会得到肯定的检查。怎么了
假阳性检查
贫乏
公共类扫描活动扩展了AppCompatActivity{
私有静态最终字符串标记=“ScannerActivity”;
private SurfaceView mSurfaceView;//其大小在XML中强制为1440x1080
私人摄像源mCameraSource;
private ScannerOverlay mScannerOverlay;//其大小在XML中强制为1440x1080
@凌驾
创建时受保护的void(Bundle savedInstanceState){
//..创建和初始化视图
// ...
BarcodeDetector BarcodeDetector=新的BarcodeDetector.Builder(此)
.setBarcodeFormats(条形码.所有_格式)
.build();
mCameraSource=new CameraSource.Builder(此为条形码检测器)
.setRequestedPreviewSize(14401080)
.setRequestedFps(20.0f)
.setFacing(摄像机源.摄像机面向后)
.setAutoFocusEnabled(真)
.build();
条形码检测器.setProcessor(新检测器.Processor(){
@凌驾
公开无效释放(){
}
@凌驾
公共空隙接收检测(检测器。检测){
parseDetections(detections.getDetectedItems());
}
});
}
专用检测(SparseArray条形码){
对于(int i=0;i{
Toast.makeText(这个“GOT DETECTION:+barcode.displayValue,Toast.LENGTH_SHORT.show”);
});
}
}
}
专用布尔值isInsideBox(条形码){
Rect barcodeBoundingBox=条形码.getBoundingBox();
Rect scanbundingbox=mScannerOverlay.getBox();
布尔checkResult=barcodeBoundingBox.left>=scanBoundingBox.left&&
barcodeBoundingBox.right=扫描边界框.top&&
barcodeBoundingBox.bottom对您的问题的解释很简单,但解决方案的解释并不简单
用户界面中框的坐标与每个预览帧上想象的框的坐标基本不同。必须将坐标从用户界面框转换为scanBoundingBox
我打开了一个实现了您试图实现的相同用例的源代码。在这个示例中,我采用了另一种方法,在将每个帧输入到Google Vision之前,我先将框切掉,这也更有效,因为Google Vision不必分析整张图片,也不必浪费大量CPU…我决定按w裁剪帧振打条形码检测器,但我不知道为什么,但裁剪帧旋转90度,即使smarphone是垂直方向
箱式探测器类
剪切的帧是旋转的
听起来很奇怪,但基于你的例子,我会试试。你听说过聚焦处理器吗?我读到它可以用于过滤。只是看了一下,但这不是你想要的,你想要的是裁剪每个帧的框,并检查框内是否能识别QR码当然,你是对的,但我不会如果有任何其他更简单的方法可以达到相同的结果,请拨打电话-检查条形码是否在方框中。正如我在您的示例项目中看到的,您在Google Vision上花费了很多时间,所以我以专家的身份问您,是否可以使用本文中的方法来实现我的目的?或者在比较有效坐标时仍然会出现错误?确定您是cA也可以使用这种方法,你只需要获得正确的坐标变换。如果你将整个图像而不是其中的一部分输入检测器,这是效率低下的,这就是为什么我认为裁剪方法是更好的做法。谢谢你的回答,如果我对这个问题有更多的问题,我将在这里提问。
public class ScannerActivity extends AppCompatActivity {
private static final String TAG = "ScannerActivity";
private SurfaceView mSurfaceView; // Its size is forced to 1440x1080 in XML
private CameraSource mCameraSource;
private ScannerOverlay mScannerOverlay; // Its size is forced to 1440x1080 in XML
@Override
protected void onCreate(Bundle savedInstanceState) {
// .. create and init views
// ...
BarcodeDetector barcodeDetector = new BarcodeDetector.Builder(this)
.setBarcodeFormats(Barcode.ALL_FORMATS)
.build();
mCameraSource = new CameraSource.Builder(this, barcodeDetector)
.setRequestedPreviewSize(1440, 1080)
.setRequestedFps(20.0f)
.setFacing(CameraSource.CAMERA_FACING_BACK)
.setAutoFocusEnabled(true)
.build();
barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
@Override
public void release() {
}
@Override
public void receiveDetections(Detector.Detections<Barcode> detections) {
parseDetections(detections.getDetectedItems());
}
});
}
private void parseDetections(SparseArray<Barcode> barcodes) {
for (int i = 0; i < barcodes.size(); i++) {
Barcode barcode = barcodes.valueAt(i);
if (isInsideBox(barcode)) {
runOnUiThread(() -> {
Toast.makeText(this, "GOT DETECTION: " + barcode.displayValue, Toast.LENGTH_SHORT).show();
});
}
}
}
private boolean isInsideBox(Barcode barcode) {
Rect barcodeBoundingBox = barcode.getBoundingBox();
Rect scanBoundingBox = mScannerOverlay.getBox();
boolean checkResult = barcodeBoundingBox.left >= scanBoundingBox.left &&
barcodeBoundingBox.right <= scanBoundingBox.right &&
barcodeBoundingBox.top >= scanBoundingBox.top &&
barcodeBoundingBox.bottom <= scanBoundingBox.bottom;
Log.d(TAG, "isInsideBox: "+(checkResult ? "YES" : "NO"));
return checkResult;
}
}
public class BoxDetector extends Detector<Barcode> {
private Detector<Barcode> mDelegate;
private int mBoxWidth;
private int mBoxHeight;
// Debugging
private CroppedFrameListener mCroppedFrameListener;
public BoxDetector(Detector<Barcode> delegate, int boxWidth, int boxHeight) {
mDelegate = delegate;
mBoxWidth = boxWidth;
mBoxHeight = boxHeight;
}
public void setCroppedFrameListener(CroppedFrameListener croppedFrameListener) {
mCroppedFrameListener = croppedFrameListener;
}
@Override
public SparseArray<Barcode> detect(Frame frame) {
int frameWidth = frame.getMetadata().getWidth();
int frameHeight = frame.getMetadata().getHeight();
// I assume that box is centered.
int left = (frameWidth / 2) - (mBoxWidth / 2);
int top = (frameHeight / 2) - (mBoxHeight / 2);
int right = (frameWidth / 2) + (mBoxWidth / 2);
int bottom = (frameHeight / 2) + (mBoxHeight / 2);
YuvImage yuvImage = new YuvImage(frame.getGrayscaleImageData().array(), ImageFormat.NV21, frameWidth, frameHeight, null);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(left, top, right, bottom), 100, outputStream);
byte[] jpegArray = outputStream.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(jpegArray, 0, jpegArray.length);
Frame croppedFrame = new Frame.Builder()
.setBitmap(bitmap)
.setRotation(frame.getMetadata().getRotation())
.build();
if(mCroppedFrameListener != null) {
mCroppedFrameListener.onNewCroppedFrame(croppedFrame.getBitmap(), croppedFrame.getMetadata().getRotation());
}
return mDelegate.detect(croppedFrame);
}
public interface CroppedFrameListener {
void onNewCroppedFrame(Bitmap bitmap, int rotation);
}
}
BarcodeDetector barcodeDetector = new BarcodeDetector.Builder(this)
.setBarcodeFormats(Barcode.ALL_FORMATS)
.build();
BoxDetector boxDetector = new BoxDetector(
barcodeDetector,
mBoxSize.getWidth(),
mBoxSize.getHeight());
boxDetector.setCroppedFrameListener(new BoxDetector.CroppedFrameListener() {
@Override
public void onNewCroppedFrame(final Bitmap bitmap, int rotation) {
Log.d(TAG, "onNewCroppedFrame: new bitmap, rotation: "+rotation);
runOnUiThread(new Runnable() {
@Override
public void run() {
mPreview.setImageBitmap(bitmap);
}
});
}
});