Vision Framework で水平角検出(傾き) Horizon Detection
iOS 11 関連記事
iOS 11 UIKit の変更点 - ObjecTips
iOS 11 Foundation の変更点 - ObjecTips
iOS 11 Messages Framework の変更点 - ObjecTips
iOS 11 PDFKit - ObjecTips
iOS 11 Core Image の変更点 - ObjecTips
koze.hatenablog.jp
Horizon Detection
Vision Framework を使って傾き検出と得られた結果から表示の補正を行う。
カメラロールの中に程良く傾いた景色の画像があったのでそれを使う。まず何も処理を入れず普通に UIImage を作成して UIImageView に配置する。

実装
Horizon Detection with Vision Framework
まず VNImageRequestHandler を作成。
今回は UIImage 経由で CGImageRef から作成している。
次に VNDetectHorizonRequest 作成しハンドラを設定してリクエストを実行する。
うまく傾きを検出できると request.results に VNHorizonObservationが入ってくる。
VNHorizonObservation の持つプロパティは以下2つ
@property (readonly, nonatomic, assign) CGAffineTransform transform; @property (readonly, nonatomic, assign) CGFloat angle;
ドキュメントにもヘッダにも何も書かれていないけど、angle は検出された傾きだろうという事が分かる。ちなみにこの値は radian になっている。
この angle から以下の様に UIImageView を補正表示するための CGAffineTransform を作成する。
CGAffineTransform t = CGAffineTransformMakeRotation(-horizonObservation.angle);
これまで同様に座標系が逆になっているので結果の angle にマイナス値をかけて値を補正している。
この CGAffineTransform を UIImageView に設定してやる。
実行結果
以下の様になる。

正しく傾きの補正が出来ている模様。
UIImageView の中心をずらさずに回転のみで補正した形になる。
コメントアウト部分にある様に
CGAffineTransformInvert(CGAffineTransformMakeRotation(horizonObservation.angle));
この様に値を補正してやっても同じ結果になる。
実行結果2
検出結果の VNHorizonObservation にもう1つプロパティがある。
@property (readonly, nonatomic, assign) CGAffineTransform transform;
これを使って UIImageView を変形してみる。
検出結果の座標系は逆になっているので先の例と同じ様に Invert で補正してやる。
CGAffineTransformInvert(horizonObservation.transform);
結果は以下

傾きの補正はOKっぽい。
ただ位置の変形がこれでいいのかどうか、、?
transform プロパティが何を表しているのか、どういった値が入ってくるのか現時点ではドキュメントも無いしWWDCのセッションもまだなので何かしら解説が出るのを待ってみたい。