📐

Vision標準で用意されている座標変換関数ライブラリ

2024/04/23に公開

Visionでは、左下原点を持つ0.0から1.0の正規化座標空間を使用する。

たとえばこれをCore Graphicsで扱うためにピクセル単位の座標に変換したい、といった座標変換が必要になるケースは多い。

で、そういう変換処理をいつも自前で書いてしまうのだが、そういえばVision標準で既に用意されてるのだった [1] と思い出したので備忘録としてここに貼り付けておく。

VNImageRectForNormalizedRect

正規化された CGRect をピクセル単位での CGRect に変換する。

@discussion Returns a rectangle in (possibly non-integral) image coordinates that is projected from a rectangle in a normalized coordinate space.

(正規化座標空間内の矩形を投影した(非積分の) 画像座標内の矩形を返します。)

/**
    @param    normalizedRect    The rectangle in the normalized coordinate space of [0..1].
    @param    imageWidth        The pixel width of the image.
    @param    imageHeight       The pixel height of the image.
    @return the rectangle in pixel coordinates.
*/
@available(iOS 11.0, *)
public func VNImageRectForNormalizedRect(_ normalizedRect: CGRect, _ imageWidth: Int, _ imageHeight: Int) -> CGRect

たとえばこれは物体検出・トラッキング系でこんな感じで使う:

let imageRect = VNImageRectForNormalizedRect(bestResult.boundingBox, 
                     imageSize.width, 
                     imageSize.height)

ただし、この関数は原点の変換はやってくれない。Visionの座標系に則った左下原点のまま。つまりこの imageRectorigin は矩形の左下の座標を表している。

これを補正するには、たとえば次のようにY座標を反転するextensionを書いておき、

extension CGRect {
    var flipped: CGRect {
        return CGRect(x: origin.x,
                      y: 1 - origin.y - height,
                      width: width, height: height)
    }
}

反転させたものを VNImageRectForNormalizedRect で変換する。

let imageRect = VNImageRectForNormalizedRect(bestResult.boundingBox.flipped, 
                     imageSize.width, 
                     imageSize.height)

本関数は拙作OSSである MLModelCamera でも使用している:

https://github.com/shu223/MLModelCamera

VNNormalizedRectForImageRect

上の逆バージョン。

@discussion Returns an image rectangle in normalized coordinates.

(画像の矩形を正規化座標で返します。)

/**
    @param    imageRect        The rectangle in image coordinate space.   
    @param    imageWidth       The pixel width of the image.
    @param    imageHeight      The pixel height of the image.
    @return the normalized rectangle.
*/
@available(iOS 11.0, *)
public func VNNormalizedRectForImageRect(_ imageRect: CGRect, _ imageWidth: Int, _ imageHeight: Int) -> CGRect

VNImagePointForNormalizedPoint

正規化された座標をピクセル単位での座標に変換する。

@discussion Returns a point in (possibly non-integral) image coordinates that is projected from a point in a normalized coordinate space.

(正規化座標空間内の点から投影された(非積分の可能性のある)画像座標内の点を返 します。)

/**
    @param    normalizedPoint   The point in the normalized coordinate space of [0..1].
    @param    imageWidth        The pixel width of the image.
    @param    imageHeight       The pixel height of the image.
    @return the point in normalized coordinates.
*/
@available(iOS 11.0, *)
public func VNImagePointForNormalizedPoint(_ normalizedPoint: CGPoint, _ imageWidth: Int, _ imageHeight: Int) -> CGPoint

VNNormalizedFaceBoundingBoxPointForLandmarkPoint

@discussion Returns the cooridnate of a given face landmark point relative to a face bounding box.
(指定された顔のランドマーク点の、顔のバウンディングボックスに対する相対座標を返します。)

/**
    @param    faceLandmarkPoint  A face landmark point obtained from a VNFaceLandmarkRegion2D instance.
    @param    faceBoundingBox    The normalized bounding box of a face obtaining from a VNFaceObservation.
    @param    imageWidth         The pixel width of the image from which the VNFaceObservation was generated.
    @param    imageHeight        The pixel height of the image from which the VNFaceObservation was generated.
    @return    the face landmark point in face bounding box coordinates.
*/
@available(iOS 11.0, *)
public func VNNormalizedFaceBoundingBoxPointForLandmarkPoint(_ faceLandmarkPoint: vector_float2, _ faceBoundingBox: CGRect, _ imageWidth: Int, _ imageHeight: Int) -> CGPoint

VNImagePointForFaceLandmarkPoint

@discussion Returns the (possibly non-integral) image cooridnate of a given face landmark point.

(与えられた顔ランドマーク点の(おそらく非整数)画像座標を返します。)

/**
    @param    faceLandmarkPoint  A face landmark point obtained from a VNFaceLandmarkRegion2D instance.
    @param    faceBoundingBox    The normalized bounding box of a face obtaining from a VNFaceObservation.
    @param    imageWidth         The pixel width of the image from which the VNFaceObservation was generated.
    @param    imageHeight        The pixel height of the image from which the VNFaceObservation was generated.
    @return    the face landmark point in image coordinates.
*/
@available(iOS 11.0, *)
public func VNImagePointForFaceLandmarkPoint(_ faceLandmarkPoint: vector_float2, _ faceBoundingBox: CGRect, _ imageWidth: Int, _ imageHeight: Int) -> CGPoint

VNNormalizedIdentityRect

{ {0, 0}, {1, 1} }CGRect を返す。

/**
    @brief    The normalized identity rect of { {0, 0}, {1, 1} }.
*/
@available(iOS 11.0, *)
public let VNNormalizedIdentityRect: CGRect

VNNormalizedRectIsIdentityRect

{ {0, 0}, {1, 1} }CGRect かどうかを判定する。

@discussion Determines whether or not the normalized rect describes the identity rect of { {0, 0}, {1, 1} }.

(正規化された矩形が、 {0, 0}, {1, 1} } の同一矩形を記述 し ているかどうかを決定し ます。)

/**
    @param    normalizedRect        The rectangle in the normalized coordinate space of [0..1].
    @return YES if the rect is the identity rect; otherwise, NO.
*/
@available(iOS 11.0, *)
public func VNNormalizedRectIsIdentityRect(_ normalizedRect: CGRect) -> Bool

VNElementTypeSize

Feature Print 要素のサイズを返す。

/**
    @brief Obtain the size, in bytes, of a given element type.

    @param    elementType        The element type.
    @return a byte count, or 0 if the element type is unknown.
*/
@available(iOS 13.0, *)
public func VNElementTypeSize(_ elementType: VNElementType) -> Int
脚注
  1. 本記事にまとめた関数は、ObjCでは VNUtils.h というヘッダに集約されている。というわけで集合体のイメージをもってタイトルで「ライブラリ」と表現したが、実際にこれらが独立したLibraryとして用意されているわけではなく、あくまでVisionフレームワークに用意されている関数群でしかない。 ↩︎

Discussion