LoginSignup
7
6

More than 5 years have passed since last update.

iOS+OpenCV: CvVideoCameraのアスペクト比を正しくする

Posted at

問題点

  • CvVideoCameraのアスペクト比がおかしい
    • UIViewContentModeScaleToFillの状態。

事前調査

  • カメラ画像を表示しているUIImageViewのcontentModeを変更しても反映されない。
  • CALayerがなんたらかんたら。
  • カメラの動作を開始しないとカメラの解像度が確定しない。
    • 動作開始後に調整しないといけない。
  • カテゴリを使って既存クラスを拡張できる。(メソッドの追加)
    • CvVideoCameraにstartWithContentMode:を追加する。

完成品

CvVideoCamera+ContentMode.h
#import <UIKit/UIKit.h>
#import <opencv2/highgui/cap_ios.h>

@interface CvVideoCamera (WithContentMode)

- (void)startWithContentMode:(UIViewContentMode)contentMode;

@end
CvVideoCamera+ContentMode.m
#import <AVFoundation/AVFoundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import <CoreMedia/CoreMedia.h>
#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>
#import "CvVideoCamera+ContentMode.h"

@implementation CvVideoCamera (WithContentMode)

- (void)startWithContentMode:(UIViewContentMode)contentMode
{
  [self start];

  //カメラの解像度を調べる
  AVCaptureInput *input = [self.captureSession.inputs objectAtIndex:0];
  AVCaptureInputPort *port = [input.ports objectAtIndex:0];
  CMFormatDescriptionRef formatDescription = port.formatDescription;
  CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions(formatDescription);
  NSLog( @"dimensions=%dx%d", dimensions.width, dimensions.height );

  if( parentView.layer.sublayers != nil )
  {
    CALayer *layer = [parentView.layer.sublayers objectAtIndex:0];
    NSLog( @"[before] frame%@ position%@", NSStringFromCGRect(layer.frame), NSStringFromCGPoint(layer.position) );

    //現在のアスペクト比
    CGFloat ratiox = dimensions.width / layer.frame.size.width;
    CGFloat ratioy = dimensions.height / layer.frame.size.height;
    //contentModeによる表示サイズ/位置の決定
    switch( contentMode )
    {
      case UIViewContentModeScaleAspectFit:
        ratiox = (ratiox > ratioy)? ratiox : ratioy;
        ratioy = ratiox;
        break;
      case UIViewContentModeScaleAspectFill:
        ratiox = (ratiox < ratioy)? ratiox : ratioy;
        ratioy = ratiox;
        break;
      default:
        NSLog( @"does not support" );
        break;
    }
    NSLog( @"ratio(%.3f,%.3f)", ratiox, ratioy );
    //新しい表示サイズ/位置をセット
    CGFloat x, y, w, h;
    w = dimensions.width / ratiox;
    h = dimensions.height / ratioy;
    x = (layer.frame.size.width - w)/2;
    y = (layer.frame.size.height - h)/2;
    layer.frame = CGRectMake( x, y, w, h );
    NSLog( @"[after] frame%@ position%@", NSStringFromCGRect(layer.frame), NSStringFromCGPoint(layer.position) );
  }
}

@end

使い方など

  • startの代わりにstartWithContentMode:を呼ぶ。
  • ScaleAspectFitScaleAspectFillのみ対応。
  • 対症療法的に作ったので色々と不安。
7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6