LoginSignup
2
2

More than 5 years have passed since last update.

色んな座標系をあっちからこっちに変換する

Last updated at Posted at 2017-02-14

映像信号が反転していたり
端末が横向きだったり
ライブラリによって左下座標系だったり右上座標系だったり
範囲が0〜1に正規化されていたり

ウザいんであっちの座標系からこっちの座標系の変換クラスを用意しました

いまだにObjCしか知らなくてスイマセン

Coordinateクラス

Coordinate.h

typedef NS_ENUM(NSInteger, CoordinateSystem)
{
  CoordinateSystemLeftDown,
  CoordinateSystemLeftUp,
  CoordinateSystemRightDown,
  CoordinateSystemRightUp,
};


@interface Coordinate : NSObject

+(CGRect)changeCoordinateRect:(CGRect)rect
                         from:(CoordinateSystem)fromCoordinate orientation:(UIInterfaceOrientation)fromOrientation size:(CGSize)fromSize isNormalize:(BOOL)fromNormalize
                           to:(CoordinateSystem)toCoordinate orientation:(UIInterfaceOrientation)toOrientation size:(CGSize)toSize isNormalize:(BOOL)toNormalize;

+(CGPoint)changeCoordinatePoint:(CGPoint)point
                           from:(CoordinateSystem)fromCoordinate orientation:(UIInterfaceOrientation)fromOrientation size:(CGSize)fromSize isNormalize:(BOOL)fromNomalize
                             to:(CoordinateSystem)toCoordinate orientation:(UIInterfaceOrientation)toOrientation size:(CGSize)toSize isNormalize:(BOOL)toNormalize;

@end
Coordinate.m

@implementation Coordinate

+(CGPoint)changeCoordinatePoint:(CGPoint)point
                           from:(CoordinateSystem)fromCoordinate orientation:(UIInterfaceOrientation)fromOrientation size:(CGSize)fromSize isNormalize:(BOOL)fromNomalize
                             to:(CoordinateSystem)toCoordinate orientation:(UIInterfaceOrientation)toOrientation size:(CGSize)toSize isNormalize:(BOOL)toNormalize{

  float x = point.x;
  float y = point.y;

  if(!fromNomalize){
    x = x / fromSize.width;
    y = y / fromSize.height;
  }

  CGAffineTransform t = [Coordinate transformFrom:fromCoordinate orientation:fromOrientation to:toCoordinate orientation:toOrientation];

  CGPoint last = CGPointApplyAffineTransform((CGPoint){x, y}, t);

  if(!toNormalize){
    last.x = last.x * toSize.width;
    last.y = last.y * toSize.height;
  }

  return last;
}

+(CGRect)changeCoordinateRect:(CGRect)rect
                         from:(CoordinateSystem)fromCoordinate orientation:(UIInterfaceOrientation)fromOrientation size:(CGSize)fromSize isNormalize:(BOOL)fromNormalize
                           to:(CoordinateSystem)toCoordinate orientation:(UIInterfaceOrientation)toOrientation size:(CGSize)toSize isNormalize:(BOOL)toNormalize{


  float x = rect.origin.x;
  float y = rect.origin.y;
  float w = rect.size.width;
  float h = rect.size.height;

  if(!fromNormalize){
    x = x / fromSize.width;
    y = y / fromSize.height;
    w = w / fromSize.width;
    h = h / fromSize.height;
  }

  CGAffineTransform t = [Coordinate transformFrom:fromCoordinate orientation:fromOrientation to:toCoordinate orientation:toOrientation];

  CGRect last = CGRectApplyAffineTransform((CGRect){x, y, w, h}, t);

  if(!toNormalize){
    last = (CGRect){
      last.origin.x * toSize.width,
      last.origin.y * toSize.height,
      last.size.width * toSize.width,
      last.size.height * toSize.height,
    };
  }

  return last;
}


+(CGAffineTransform)transformFrom:(CoordinateSystem)fromCoordinate orientation:(UIInterfaceOrientation)fromOrientation
                               to:(CoordinateSystem)toCoordinate orientation:(UIInterfaceOrientation)toOrientation{

  CGAffineTransform t = CGAffineTransformIdentity;

  //上下反転
  if(
     (
      //端末の傾きについての条件
      fromOrientation == toOrientation
      &&
      //座標系の条件
      ((fromCoordinate == CoordinateSystemLeftUp && toCoordinate == CoordinateSystemLeftDown)
       ||
       (fromCoordinate == CoordinateSystemLeftDown && toCoordinate == CoordinateSystemLeftUp)
       ||
       (fromCoordinate == CoordinateSystemRightUp && toCoordinate == CoordinateSystemRightDown)
       ||
       (fromCoordinate == CoordinateSystemRightDown && toCoordinate == CoordinateSystemRightUp)
       )
      )
     ||
     (
      //端末の傾きについての条件
      (
       (fromOrientation == UIInterfaceOrientationPortrait && toOrientation == UIInterfaceOrientationPortraitUpsideDown)
       ||
       (fromOrientation == UIInterfaceOrientationPortraitUpsideDown && toOrientation == UIInterfaceOrientationPortrait)
       ||
       (fromOrientation == UIInterfaceOrientationLandscapeLeft && toOrientation == UIInterfaceOrientationLandscapeRight)
       ||
       (fromOrientation == UIInterfaceOrientationLandscapeRight && toOrientation == UIInterfaceOrientationLandscapeLeft)
       )
      &&
      //座標系の条件
      (
       (fromCoordinate == CoordinateSystemLeftUp && toCoordinate == CoordinateSystemRightUp)
       ||
       (fromCoordinate == CoordinateSystemLeftDown && toCoordinate == CoordinateSystemRightDown)
       ||
       (fromCoordinate == CoordinateSystemRightUp && toCoordinate == CoordinateSystemLeftUp)
       ||
       (fromCoordinate == CoordinateSystemRightDown && toCoordinate == CoordinateSystemLeftDown)
       )
      )
     ){
    //上下反転
    t = [Utils concats:@[
                         [NSValue valueWithCGAffineTransform:CGAffineTransformMakeScale(1, -1)],
                         [NSValue valueWithCGAffineTransform:CGAffineTransformMakeTranslation(0, 1)],
                         ]];
  }
  //左右反転
  else if(
          (
           //端末の傾きについての条件
           fromOrientation == toOrientation
           &&
           //座標系の条件
           (
            (fromCoordinate == CoordinateSystemLeftUp && toCoordinate == CoordinateSystemRightUp)
            ||
            (fromCoordinate == CoordinateSystemLeftDown && toCoordinate == CoordinateSystemRightDown)
            ||
            (fromCoordinate == CoordinateSystemRightUp && toCoordinate == CoordinateSystemLeftUp)
            ||
            (fromCoordinate == CoordinateSystemRightDown && toCoordinate == CoordinateSystemRightUp)
            )
           )
          ||
          (
           (
            //端末の傾きについての条件
            (fromOrientation == UIInterfaceOrientationPortrait && toOrientation == UIInterfaceOrientationPortraitUpsideDown)
            ||
            (fromOrientation == UIInterfaceOrientationPortraitUpsideDown && toOrientation == UIInterfaceOrientationPortrait)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeLeft && toOrientation == UIInterfaceOrientationLandscapeRight)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeRight && toOrientation == UIInterfaceOrientationLandscapeLeft)
            )
           &&
           (
            //座標系の条件
            (fromCoordinate == CoordinateSystemLeftUp && toCoordinate == CoordinateSystemLeftDown)
            ||
            (fromCoordinate == CoordinateSystemLeftDown && toCoordinate == CoordinateSystemLeftUp)
            ||
            (fromCoordinate == CoordinateSystemRightUp && toCoordinate == CoordinateSystemRightDown)
            ||
            (fromCoordinate == CoordinateSystemRightDown && toCoordinate == CoordinateSystemRightUp)
            )
           )
          ){
    //左右反転
    t = [Utils concats:@[
                         [NSValue valueWithCGAffineTransform:CGAffineTransformMakeScale(-1, 1)],
                         [NSValue valueWithCGAffineTransform:CGAffineTransformMakeTranslation(1, 0)],
                         ]];
  }
  //縦横入れ替え
  else if(
          (
           //端末の傾きについての条件
           (
            (fromOrientation == UIInterfaceOrientationPortrait && toOrientation == UIInterfaceOrientationLandscapeLeft)
            ||
            (fromOrientation == UIInterfaceOrientationPortraitUpsideDown && toOrientation == UIInterfaceOrientationLandscapeRight)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeLeft && toOrientation == UIInterfaceOrientationPortraitUpsideDown)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeRight && toOrientation == UIInterfaceOrientationPortrait)
            )
           &&
           (
            //座標系の条件
            (fromCoordinate == CoordinateSystemLeftUp && toCoordinate == CoordinateSystemRightUp)
            ||
            (fromCoordinate == CoordinateSystemLeftDown && toCoordinate == CoordinateSystemLeftUp)
            ||
            (fromCoordinate == CoordinateSystemRightUp && toCoordinate == CoordinateSystemRightDown)
            ||
            (fromCoordinate == CoordinateSystemRightDown && toCoordinate == CoordinateSystemLeftDown)
            )
           )
          ||
          (
           //端末の傾きについての条件
           (
            (fromOrientation == UIInterfaceOrientationPortrait && toOrientation == UIInterfaceOrientationLandscapeRight)
            ||
            (fromOrientation == UIInterfaceOrientationPortraitUpsideDown && toOrientation == UIInterfaceOrientationLandscapeLeft)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeLeft && toOrientation == UIInterfaceOrientationPortrait)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeRight && toOrientation == UIInterfaceOrientationPortraitUpsideDown)
            )
           &&
           (
            //座標系の条件
            (fromCoordinate == CoordinateSystemLeftUp && toCoordinate == CoordinateSystemLeftDown)
            ||
            (fromCoordinate == CoordinateSystemLeftDown && toCoordinate == CoordinateSystemRightDown)
            ||
            (fromCoordinate == CoordinateSystemRightUp && toCoordinate == CoordinateSystemLeftUp)
            ||
            (fromCoordinate == CoordinateSystemRightDown && toCoordinate == CoordinateSystemRightUp)
            )
           )
          ){
    //縦横入れ替え
    //xとyをwidthとheight入れ替える
    t = CGAffineTransformMake(0, 1, 1, 0, 0, 0);
  }
  //上下反転・左右反転
  else if(
          (
           //端末の傾きについての条件
           (fromOrientation == toOrientation)
           &&
           //座標系の条件
           (
            (fromCoordinate == CoordinateSystemLeftUp && toCoordinate == CoordinateSystemRightDown)
            ||
            (fromCoordinate == CoordinateSystemLeftDown && toCoordinate == CoordinateSystemRightUp)
            ||
            (fromCoordinate == CoordinateSystemRightUp && toCoordinate == CoordinateSystemLeftDown)
            ||
            (fromCoordinate == CoordinateSystemRightDown && toCoordinate == CoordinateSystemLeftUp)
            )
           )
          ||
          (
           //端末の傾きについての条件
           (
            (fromOrientation == UIInterfaceOrientationPortrait && toOrientation == UIInterfaceOrientationPortraitUpsideDown)
            ||
            (fromOrientation == UIInterfaceOrientationPortraitUpsideDown && toOrientation == UIInterfaceOrientationPortrait)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeLeft && toOrientation == UIInterfaceOrientationLandscapeRight)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeRight && toOrientation == UIInterfaceOrientationLandscapeLeft)
            )
           &&
           //座標系の条件
           (fromCoordinate == toCoordinate)
           )
          ){
    //上下反転・左右反転
    t = [Utils concats:@[
                         [NSValue valueWithCGAffineTransform:CGAffineTransformMakeScale(-1, -1)],
                         [NSValue valueWithCGAffineTransform:CGAffineTransformMakeTranslation(1, 1)],
                         ]];
  }
  //上下反転・縦横入れ替え
  else if(
          (
           //端末の傾きについての条件
           (
            (fromOrientation == UIInterfaceOrientationPortrait && toOrientation == UIInterfaceOrientationLandscapeLeft)
            ||
            (fromOrientation == UIInterfaceOrientationPortraitUpsideDown && toOrientation == UIInterfaceOrientationLandscapeRight)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeLeft && toOrientation == UIInterfaceOrientationPortraitUpsideDown)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeRight && toOrientation == UIInterfaceOrientationPortrait)
            )
           &&
           //座標系の条件
           ((fromCoordinate == CoordinateSystemLeftUp && toCoordinate == CoordinateSystemRightDown)
            ||
            (fromCoordinate == CoordinateSystemLeftDown && toCoordinate == CoordinateSystemLeftDown)
            ||
            (fromCoordinate == CoordinateSystemRightUp && toCoordinate == CoordinateSystemRightUp)
            ||
            (fromCoordinate == CoordinateSystemRightDown && toCoordinate == CoordinateSystemLeftUp)
            )
           )
          ||
          (
           //端末の傾きについての条件
           (
            (fromOrientation == UIInterfaceOrientationPortrait && toOrientation == UIInterfaceOrientationLandscapeRight)
            ||
            (fromOrientation == UIInterfaceOrientationPortraitUpsideDown && toOrientation == UIInterfaceOrientationLandscapeLeft)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeLeft && toOrientation == UIInterfaceOrientationPortrait)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeRight && toOrientation == UIInterfaceOrientationPortraitUpsideDown)
            )
           &&
           //座標系の条件
           (
            (fromCoordinate == CoordinateSystemLeftUp && toCoordinate == CoordinateSystemLeftUp)
            ||
            (fromCoordinate == CoordinateSystemLeftDown && toCoordinate == CoordinateSystemRightUp)
            ||
            (fromCoordinate == CoordinateSystemRightUp && toCoordinate == CoordinateSystemLeftDown)
            ||
            (fromCoordinate == CoordinateSystemRightDown && toCoordinate == CoordinateSystemRightDown)
            )
           )
          ){
    //上下反転・縦横入れ替え
    t = [Utils concats:@[
                         //xとyをwidthとheight入れ替える
                         [NSValue valueWithCGAffineTransform:CGAffineTransformMake(0, 1, 1, 0, 0, 0)],
                         //上下反転
                         [NSValue valueWithCGAffineTransform:CGAffineTransformMakeScale(1, -1)],
                         [NSValue valueWithCGAffineTransform:CGAffineTransformMakeTranslation(0, 1.0)],
                         ]];

  }
  //左右反転・縦横入れ替え
  else if(
          (
           //端末の傾きについての条件
           (
            (fromOrientation == UIInterfaceOrientationPortrait && toOrientation == UIInterfaceOrientationLandscapeLeft)
            ||
            (fromOrientation == UIInterfaceOrientationPortraitUpsideDown && toOrientation == UIInterfaceOrientationLandscapeRight)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeLeft && toOrientation == UIInterfaceOrientationPortraitUpsideDown)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeRight && toOrientation == UIInterfaceOrientationPortrait))
           &&
           //座標系の条件
           ((fromCoordinate == CoordinateSystemLeftUp && toCoordinate == CoordinateSystemLeftUp)
            ||
            (fromCoordinate == CoordinateSystemLeftDown && toCoordinate == CoordinateSystemRightUp)
            ||
            (fromCoordinate == CoordinateSystemRightUp && toCoordinate == CoordinateSystemLeftDown)
            ||
            (fromCoordinate == CoordinateSystemRightDown && toCoordinate == CoordinateSystemRightDown)
            )
           )
          ||
          (
           //端末の傾きについての条件
           ((fromOrientation == UIInterfaceOrientationPortraitUpsideDown && toOrientation == UIInterfaceOrientationLandscapeLeft)
            ||
            (fromOrientation == UIInterfaceOrientationPortrait && toOrientation == UIInterfaceOrientationLandscapeRight)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeLeft && toOrientation == UIInterfaceOrientationPortrait)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeRight && toOrientation == UIInterfaceOrientationPortraitUpsideDown)
            )
           &&
           //座標系の条件
           ((fromCoordinate == CoordinateSystemLeftUp && toCoordinate == CoordinateSystemRightDown)
            ||
            (fromCoordinate == CoordinateSystemLeftDown && toCoordinate == CoordinateSystemLeftDown)
            ||
            (fromCoordinate == CoordinateSystemRightUp && toCoordinate == CoordinateSystemRightUp)
            ||
            (fromCoordinate == CoordinateSystemRightDown && toCoordinate == CoordinateSystemLeftUp)
            )
           )
          ){
    //左右反転・縦横入れ替え
    //    t = CGAffineTransformMake(0, -1, 1, 0, 0, 1);
    t = [Utils concats:@[
                         //xとyをwidthとheight入れ替える
                         [NSValue valueWithCGAffineTransform:CGAffineTransformMake(0, 1, 1, 0, 0, 0)],
                         //左右反転
                         [NSValue valueWithCGAffineTransform:CGAffineTransformMakeScale(-1, 1)],
                         [NSValue valueWithCGAffineTransform:CGAffineTransformMakeTranslation(1, 0)],
                         ]];
  }
  //上下反転・左右反転・縦横入れ替え
  else if(
          (
           //端末の傾きについての条件
           (
            (fromOrientation == UIInterfaceOrientationPortrait && toOrientation == UIInterfaceOrientationLandscapeLeft)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeLeft && toOrientation == UIInterfaceOrientationPortraitUpsideDown)
            ||
            (fromOrientation == UIInterfaceOrientationPortraitUpsideDown && toOrientation == UIInterfaceOrientationLandscapeRight)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeRight && toOrientation == UIInterfaceOrientationPortrait)
            )
           &&
           //座標系の条件
           (
            (fromCoordinate == CoordinateSystemLeftUp && toCoordinate == CoordinateSystemLeftDown)
            ||
            (fromCoordinate == CoordinateSystemLeftDown && toCoordinate == CoordinateSystemRightDown)
            ||
            (fromCoordinate == CoordinateSystemRightUp && toCoordinate == CoordinateSystemLeftUp)
            ||
            (fromCoordinate == CoordinateSystemRightDown && toCoordinate == CoordinateSystemRightUp)
            )
           )
          ||
          (
           //端末の傾きについての条件
           (
            (fromOrientation == UIInterfaceOrientationPortrait && toOrientation == UIInterfaceOrientationLandscapeRight)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeLeft && toOrientation == UIInterfaceOrientationPortrait)
            ||
            (fromOrientation == UIInterfaceOrientationPortraitUpsideDown && toOrientation == UIInterfaceOrientationLandscapeLeft)
            ||
            (fromOrientation == UIInterfaceOrientationLandscapeRight && toOrientation == UIInterfaceOrientationPortraitUpsideDown)
            )
           &&
           //座標系の条件
           (
            (fromCoordinate == CoordinateSystemLeftUp && toCoordinate == CoordinateSystemRightUp)
            ||
            (fromCoordinate == CoordinateSystemLeftDown && toCoordinate == CoordinateSystemLeftUp)
            ||
            (fromCoordinate == CoordinateSystemRightUp && toCoordinate == CoordinateSystemRightDown)
            ||
            (fromCoordinate == CoordinateSystemRightDown && toCoordinate == CoordinateSystemLeftDown)
            )
           )
          ){
    //上下反転・左右反転・縦横入れ替え
    t = [Utils concats:@[
                         //xとyをwidthとheight入れ替える
                         [NSValue valueWithCGAffineTransform:CGAffineTransformMake(0, 1, 1, 0, 0, 0)],
                         //上下左右反転
                         [NSValue valueWithCGAffineTransform:CGAffineTransformMakeScale(-1, -1)],
                         [NSValue valueWithCGAffineTransform:CGAffineTransformMakeTranslation(1, 1)],
                         ]];

  }

  return t;
}

+(CGAffineTransform)concats:(NSArray*)affineTransforms{

  CGAffineTransform t = CGAffineTransformIdentity;

  for (id obj in affineTransforms) {
    CGAffineTransform a = [obj CGAffineTransformValue];
    t = CGAffineTransformConcat(t, a);
  }

  return t;
}

@end

使い方

/*
ライブラリSomeLib1で顔を検出して、別のライブラリSomeLibe2にその情報を渡したいけど座標系とかが違う場合

imageの方向 : 縦向き (UIDeviceOrientationPortrait)

SomeLib1の座標系 : 左下座標系 (CoordinateSystemLeftDown)
SomeLib1の向き : 縦向き (UIDeviceOrientationPortrait)
SomeLib1の範囲 : 0〜1に正規化

SomeLib2の座標系 : 右上座標系 (CoordinateSystemRightUp)
SomeLib2の向き : 横向き (UIDeviceOrientationLandscapeLeft)
SomeLib2の範囲 : 画像サイズ
*/

CGRect r = [SomeLib1 getFaceWithUIImage:image];

//座標系をSomeLib1のものからSomeLib2のものへ変換
CGRect r2 = [Coordinate changeCoordinateRect:r //変換前のCGRect
                                        //変換前の情報
                                        from:CoordinateSystemLeftDown
                                 orientation:UIDeviceOrientationPortrait 
                                        size:image.size 
                                 isNormalize:YES
                                          //変換後の情報
                                          to:CoordinateSystemRightUp 
                                 orientation:UIDeviceOrientationLandscapeLeft 
                                        size:(CGSize){image.size.height, image.size.width}
                                 isNormalize:NO];

//SomeLib2に渡す
[SomeLib2 setFaceRect:r2];
2
2
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
2
2