使用Vision Framework进行实时矩形检测时无法识别全部矩形的问题求助
问题排查与修复方案
1. 核心致命bug:帧处理逻辑错误
你在captureOutput回调中对矩形检测请求加了2秒延迟,而AVCapture输出的CMSampleBuffer是会被系统快速复用释放的,延迟2秒后你拿到的pixelBuffer已经是无效/被覆盖的数据,自然无法正确检测矩形。同时每帧都添加一个延迟2秒的任务,会导致2秒后大量检测请求并发执行,严重占用性能,进一步降低识别准确率。
- 修复方案:直接删除该延迟逻辑,拿到sampleBuffer后立刻执行检测请求。
2. 矩形检测参数配置缺失
你当前仅配置了3个参数,还有2个关键参数使用了系统默认值,严重限制了小矩形、远矩形的识别:
minimumSize:系统默认值为0.2,意味着只有面积占整个预览画面20%以上的矩形才会被识别,远处的SET卡片远达不到这个阈值,建议调整到0.02~0.05区间minimumConfidence:系统默认值为0.5,可根据识别效果适当调低到0.3,降低识别门槛- 可选调整:
quadratureTolerance如果拍摄角度倾斜较大,可适当调高到60度,允许更大的透视角度偏差
- 修复后配置代码:
func setupVision() { let rectanglesDetectionRequest = VNDetectRectanglesRequest(completionHandler: self.handleRectangles) rectanglesDetectionRequest.maximumObservations = 0 rectanglesDetectionRequest.quadratureTolerance = 60.0 rectanglesDetectionRequest.minimumAspectRatio = 0.64 // 新增关键参数 rectanglesDetectionRequest.minimumSize = 0.03 rectanglesDetectionRequest.minimumConfidence = 0.3 self.requests = [rectanglesDetectionRequest] }
3. 检测与跟踪时序逻辑错误
你当前的逻辑是先触发检测请求,然后立刻执行跟踪逻辑,此时检测请求还未执行完成,self.rectanglesss里存储的还是上一轮的旧检测结果,新识别到的矩形无法被加入跟踪队列。
- 修复方案:将跟踪逻辑移到检测请求的完成回调
handleRectangles中,更新self.rectanglesss后再执行跟踪任务,避免跟踪旧数据。
4. 修复后完整帧处理代码
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return } let exifOrientation = self.exifOrientationFromDeviceOrientation() // 删除原来的2秒延迟逻辑,直接执行检测 var requestOptions: [VNImageOption : Any] = [:] if let cameraIntrinsicData = CMGetAttachment(sampleBuffer, kCMSampleBufferAttachmentKey_CameraIntrinsicMatrix, nil) { requestOptions = [.cameraIntrinsics: cameraIntrinsicData] } DispatchQueue.global(qos: .userInitiated).async { let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, orientation:exifOrientation, options: requestOptions) do { try imageRequestHandler.perform(self.requests) } catch { print(error) } } // 跟踪逻辑保持,但是要保证self.rectanglesss在handleRectangles中实时更新 var arr = Array<VNTrackRectangleRequest>() for obs in self.rectanglesss{ let trackRequest = VNTrackRectangleRequest(rectangleObservation: obs, completionHandler: self.handleSequenceRequestUpdate) trackRequest.trackingLevel = .accurate arr.append(trackRequest) } do { try self.sequenceHandler.perform(arr, on: pixelBuffer, orientation: exifOrientation) } catch { print(error) } }
内容的提问来源于stack exchange,提问作者Subhash Sharma
相关产品推荐
相关产品推荐

