Visionフレームワークを使ってQRコードの認識を行ってみたのですが、QRCodeの中心座標は取得できるのですが端4点の座標を取得する方法がわかりません。
調べてみても出てこないのでvisionでは4点を追うことはできないのでしょうか?
swift
1import UIKit 2import AVFoundation 3import Vision 4 5class ViewController: UIViewController { 6 7 @IBOutlet weak var previewImageView: UIImageView! 8 9 override func viewDidLoad() { 10 super.viewDidLoad() 11 setupCamera() 12 } 13 override func viewDidAppear(_ animated: Bool) { 14 super.viewDidAppear(animated) 15 } 16 17 override func viewDidDisappear(_ animated: Bool) { 18 super.viewDidDisappear(animated) 19 self.avCaptureSession.stopRunning() 20 } 21 22 /// カメラのセットアップ 23 private func setupCamera() { 24 self.avCaptureSession.sessionPreset = .photo 25 26 let device = AVCaptureDevice.default(.builtInUltraWideCamera,for: .video, position: .back) 27 let input = try! AVCaptureDeviceInput(device: device!) 28 self.avCaptureSession.addInput(input) 29 30 let videoDataOutput = AVCaptureVideoDataOutput() 31 videoDataOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as String : Int(kCVPixelFormatType_32BGRA)] 32 videoDataOutput.alwaysDiscardsLateVideoFrames = true 33 videoDataOutput.setSampleBufferDelegate(self, queue: .global()) 34 35 self.avCaptureSession.addOutput(videoDataOutput) 36 self.avCaptureSession.startRunning() 37 } 38 39 /// コンテキストに矩形を描画 40 private func drawRect(_ rect: CGRect, context: CGContext) { 41 context.setLineWidth(4.0) 42 context.setStrokeColor(UIColor.green.cgColor) 43 context.stroke(rect) 44 45 } 46 47 /// QR識情報の配列取得 (非同期) 48 private func getQRObservations(pixelBuffer: CVPixelBuffer, completion: @escaping (([VNBarcodeObservation])->())) { 49 let request = VNDetectBarcodesRequest { (request, error) in 50 guard let results = request.results as? [VNBarcodeObservation] else { 51 completion([]) 52 return 53 } 54 completion(results) 55 } 56 let handler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:]) 57 try? handler.perform([request]) 58 59 } 60 61 /// 正規化された矩形位置を指定領域に展開 62 private func getQRUnfoldRect(normalizedRect: CGRect, targetSize: CGSize) -> CGRect { 63 return CGRect( 64 x: normalizedRect.minX * targetSize.width, 65 y: normalizedRect.minY * targetSize.height, 66 width: normalizedRect.width * targetSize.width, 67 height: normalizedRect.height * targetSize.height 68 69 ) 70 } 71 /// QR出位置に矩形を描画した image を取得 72 private func getQRRectsImage(sampleBuffer :CMSampleBuffer, barcodeObservations: [VNBarcodeObservation]) -> UIImage? { 73 74 guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { 75 return nil 76 } 77 78 CVPixelBufferLockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0)) 79 80 guard let pixelBufferBaseAddres = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0) else { 81 CVPixelBufferUnlockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0)) 82 return nil 83 } 84 85 let width = CVPixelBufferGetWidth(imageBuffer) 86 let height = CVPixelBufferGetHeight(imageBuffer) 87 let bitmapInfo = CGBitmapInfo(rawValue: 88 (CGBitmapInfo.byteOrder32Little.rawValue | CGImageAlphaInfo.premultipliedFirst.rawValue) 89 ) 90 91 guard let newContext = CGContext( 92 data: pixelBufferBaseAddres, 93 width: width, 94 height: height, 95 bitsPerComponent: 8, 96 bytesPerRow: CVPixelBufferGetBytesPerRow(imageBuffer), 97 space: CGColorSpaceCreateDeviceRGB(), 98 bitmapInfo: bitmapInfo.rawValue 99 ) else 100 { 101 CVPixelBufferUnlockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0)) 102 return nil 103 } 104 105 let imageSize = CGSize(width: width, height: height) 106 let faseRects = barcodeObservations.compactMap { 107 getQRUnfoldRect(normalizedRect: $0.boundingBox, targetSize: imageSize) 108 } 109 faseRects.forEach{ self.drawRect($0, context: newContext) } 110 111 CVPixelBufferUnlockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0)) 112 113 guard let imageRef = newContext.makeImage() else { 114 return nil 115 } 116 let image = UIImage(cgImage: imageRef, scale: 1.0, orientation: UIImage.Orientation.right) 117 118 return image 119 } 120} 121 122extension ViewController : AVCaptureVideoDataOutputSampleBufferDelegate{ 123 /// カメラからの映像取得デリゲート 124 func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { 125 126 guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { 127 return 128 } 129 130 getQRObservations(pixelBuffer: pixelBuffer) { [weak self] barcodeObservations in 131 guard let self = self else { return } 132 let image = self.getQRRectsImage(sampleBuffer: sampleBuffer, barcodeObservations: barcodeObservations) 133 DispatchQueue.main.async { [weak self] in 134 self?.previewImageView.image = image 135 } 136 } 137 138 } 139}
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/11/03 08:59