2017-12-21 53 views
1

受け取ったVNRectangleObservationのCGPoints(bottomLeft、 bottomRight、topLeft、topRight)を別の座標系(画面上のビューの座標など)に変換する必要があります。VNRectangleObservationポイントを他の座標系に変換する

私は要求を定義します。

:私は結果を受け取る後半completionHandlerで

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { 

    guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {return} 
    var requestOptions:[VNImageOption:Any] = [:] 
    if let cameraIntrinsicData = CMGetAttachment(sampleBuffer, kCMSampleBufferAttachmentKey_CameraIntrinsicMatrix, nil) { 
     requestOptions = [.cameraIntrinsics:cameraIntrinsicData] 
    } 
    let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, orientation: CGImagePropertyOrientation(rawValue:6)!, options: requestOptions) 
    do { 
     try imageRequestHandler.perform(self.requests) 
    } catch { 
     print(error) 
    } 

} 

:私は、デリゲートの呼び出しでカメラからsampleBufferを取得

// Rectangle Request 
    let rectangleDetectionRequest = VNDetectRectanglesRequest(completionHandler: handleRectangles) 
    rectangleDetectionRequest.minimumSize = 0.5 
    rectangleDetectionRequest.maximumObservations = 1 

、および検出要求を行います

func handleRectangles (request:VNRequest, error:Error?) { 

    guard let results = request.results as? [VNRectangleObservation] else { return } 

    let flipTransform = CGAffineTransform(scaleX: 1, y: -1).translatedBy(x: 0, y: -self.previewView.frame.height) 
    let scaleTransform = CGAffineTransform.identity.scaledBy(x: self.previewView.frame.width, y: self.previewView.frame.height) 

    for rectangle in results { 
     let rectangleBounds = rectangle.boundingBox.applying(scaleTransform).applying(flipTransform) 
     // convertedTopLeft = conversion(rectangle.topLeft) 
     // convertedTopRight = conversion(rectangle.topRight) 
     // convertedBottomLeft = conversion(rectangle.bottomLeft) 
     // convertedBottomRight = conversion(rectangle.bottomRight) 
    } 
} 

これはCGRectであるboundingBoxで動作しますが、CGPを変換する必要があります代わりに別のビューの座標系に変換します。 問題は、sampleBuffer:CMSampleBufferの座標系からpreviewView座標系への変換を取得する方法がわかりません。

ありがとうございます!

答えて

0

を助け願っています。

let transform = CGAffineTransform.identity 
     .scaledBy(x: 1, y: -1) 
     .translatedBy(x: 0, y: -size.height) 
     .scaledBy(x: size.width, y: size.height) 

    let convertedTopLeft = rectangle.topLeft.applying(transform) 
    let convertedTopRight = rectangle.topRight.applying(transform) 
    let convertedBottomLeft = rectangle.bottomLeft.applying(transform) 
    let convertedBottomRight = rectangle.bottomRight.applying(transform) 
0

あなたはカメラのレイヤーを使用し、レイヤーはAVCaptureVideoPreviewLayerとします。 (https://developer.apple.com/documentation/avfoundation/avcapturevideopreviewlayer)。 したがって、シングルポイントを変換する場合は、この関数を使用します。layerPointConvertedhttps://developer.apple.com/documentation/avfoundation/avcapturevideopreviewlayer/1623502-layerpointconverted)座標系がVNRectangleObservationのため、yが反転されていることに注意してください。

let convertedTopLeft: CGPoint = cameraLayer.layerPointConverted(fromCaptureDevicePoint: CGPoint(x: rectangle.topLeft.x, y: 1 - rectangle.topLeft.y)) 
let convertedTopRight: CGPoint = cameraLayer.layerPointConverted(fromCaptureDevicePoint: CGPoint(x: rectangle.topRight.x, y: 1 - rectangle.topRight.y)) 
let convertedBottomLeft: CGPoint = cameraLayer.layerPointConverted(fromCaptureDevicePoint: CGPoint(x: rectangle.bottomLeft.x, y: 1 - rectangle.bottomLeft.y)) 
let convertedBottomRight: CGPoint = cameraLayer.layerPointConverted(fromCaptureDevicePoint: CGPoint(x: rectangle.bottomRight.x, y: 1 - rectangle.bottomRight.y)) 

は、それは単にサイズが、私は4ポイントを転置必要があるため、宛先ビューのCGSizeでするCGPoint自体に変換を適用することの問題だった

+0

ありがとうプレビューレイヤーのアスペクトを埋める重力プロパティーを補正する方が良いソリューションかもしれないので、私のコードでチェックします。 – mihaicris

+0

クールで助けてくれたら教えてください – user3699466

+0

こんにちは、layerPointConvertedメソッドを試しましたが、期待通りに動作しません。 キャプチャデバイスの座標(0,0 - 1,0 - 0,1 - 1,1)のコーナーとして入力ポイントを使用すると、変換されたポイントx座標はデスティネーションビューフレームから外れます。メソッドは、プレビュービューのaspectFill videogravityプロパティを考慮しないようなものです(これは画面サイズと同じですが、大きくはありません)。私はこの機能がオフセットをどのように補償するかを知っていたと思った。 – mihaicris

関連する問題