2022年02月26日

アップルのMLサンプルの updateLayerGeometry() 修正する

前回に引き続き、さらにアップルのサンプルを修正します。それは updateLayerGeometry() です。
これはiPhoneの画面の大きさに合わせてキャプチャのプレビューを配置する部分ですが、提供されているサンプルはデバイスの縦持ち(portrait)にしか対応していませんでしたので、横持ち(landscape)にも対応するようにこれを修正します。
func updateLayerGeometry() {
let bounds = rootLayer.bounds // iOS用
//横持ち用
var scale: CGFloat
let xScale: CGFloat = bounds.size.width / bufferSize.width //.height
let yScale: CGFloat = bounds.size.height / bufferSize.height //.width
scale = fmax(xScale, yScale)
if scale.isInfinite {
scale = 1.0
}
//縦持ち用
var scalePortrait: CGFloat
let xScalePortrait: CGFloat = bounds.size.width / bufferSize.height
let yScalePortrait: CGFloat = bounds.size.height / bufferSize.width
scalePortrait = fmax(xScalePortrait, yScalePortrait)
if scalePortrait.isInfinite {
scalePortrait = 1.0
}
//
CATransaction.begin()
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
switch UIApplication.shared.statusBarOrientation {
case .portrait:
print("updateLayerGeometry: statusBarOrientation.portrait")
detectionOverlay.bounds = CGRect(x: 0.0, y: 0.0, width: bufferSize.height, height: bufferSize.width)
detectionOverlay.setAffineTransform(CGAffineTransform(rotationAngle: 0.0).scaledBy(x: scalePortrait, y: -scalePortrait))
case .landscapeLeft:
print("updateLayerGeometry: statusBarOrientation.landscapeLeft")
detectionOverlay.bounds = CGRect(x: 0.0, y: 0.0, width: bufferSize.width, height: bufferSize.height)
detectionOverlay.setAffineTransform(CGAffineTransform(rotationAngle: 0.0).scaledBy(x: scale, y: -scale))
case .landscapeRight:
print("updateLayerGeometry: statusBarOrientation.landscapeRight")
detectionOverlay.bounds = CGRect(x: 0.0, y: 0.0, width: bufferSize.width, height: bufferSize.height)
detectionOverlay.setAffineTransform(CGAffineTransform(rotationAngle: 0.0).scaledBy(x: scale, y: -scale))
case .portraitUpsideDown:
print("updateLayerGeometry: statusBarOrientation.portraitUpsideDown")
detectionOverlay.bounds = CGRect(x: 0.0, y: 0.0, width: bufferSize.height, height: bufferSize.width)
detectionOverlay.setAffineTransform(CGAffineTransform(rotationAngle: 0.0).scaledBy(x: scalePortrait, y: -scalePortrait))
default: //break
detectionOverlay.setAffineTransform(CGAffineTransform(rotationAngle: CGFloat(.pi / 2.0)).scaledBy(x: scale, y: -scale))
}
// center the layer
detectionOverlay.position = CGPoint(x: bounds.midX, y: bounds.midY)
CATransaction.commit()
}

タグ:vision
posted by MacLab. at 22:36| Comment(0) | TrackBack(0) | 技術情報

2022年02月17日

アップルのMLアプリのサンプルの exifOrientationFromDeviceOrientation() は間違えているという話

機械学習のためのVisionフレームワークを使ったmacOS/iOSアプリの開発をやっています。
その中で、アップルが公開して世間で広く使われているサンプルのSwiftコードに誤りがあるのではないかということに気がつきました。
それはビデオキャプチャ、特にiPhoneのカメラを使ったアプリの場合に使われる exifOrientationFromDeviceOrientation() のコードです。
これはiPhoneの向きに合わせて推論の向きを変更するコードで、今では世界中の多くのブログや教科書に転載されていますが、これでアプリを作成すると、portrait(iPhoneを縦に持つ)に Visionの推論の精度が低くなることに気がつきました。
また、横持ちの場合でも出力される結果が反転する現象がありました。
アップルが提供するコードに誤りがあるとはついぞ思い至らなかったため、自作の部分をこねくりまわして悩むことになってしまいました。続きを読む
タグ:vision
posted by MacLab. at 22:41| Comment(0) | TrackBack(0) | 技術情報