0

これを書き出すことが私の問題に役立つことを願っています。顔を含む画像がありますが、できるだけ多くの顔を維持しながら、アスペクト比を考慮してこれらの画像を再トリミングしたいと思います。

画像を任意の長方形にトリミングしたいのですが、これは、高さ、短さ、正方形、またはアスペクトが4:1までの任意の長方形にすることができます。可能な限り、指定した顔や特徴を(画像の長方形の内側の長方形として)切り抜くことは避けたいと思います。EG画像の長方形(0,0,500、300)と特徴の長方形(20、40、75、75)があり、(アスペクト比を考慮して)それを(0,0、 320,200)、すべて面の長方形を最小限にトリミングします。

私は中央トリミングの実用的な実装を持っています。ここでは、画像の大きい方の側を決定し、同じ比率に基づいて反対側をスケーリングし、xとyをスケーリングされたw/hの中心に設定します-ターゲットw/h。

わかりやすくするために、署名は次のようになります(Obj-Cの場合)。

(CGRect)crop:(CGSize)sourceSize toFitSize:(CGSize)fitSize withoutCroppingRect:(CGRect)featuresRect

sourceSizeは元の画像のサイズ、は画像を切り抜くfitSize形状featuresRect、ははの範囲内の長方形です(0,0,sourceSize.width, sourceSize,height)

おそらく、これは、フィーチャの長方形を中心とした「中央の切り抜き」として実行する必要がありますか?これが何を意味するのか、頭を包み込もうとしています。

4

1 に答える 1

0

これを試してみてください、私はそれがあなたが望むことをするか、少なくともそれはあなたを正しい方向に動かすと思います。出力rectは、ソースイメージrectと同じアスペクト比を維持します。

使用例:

 CGRect sizedRect = [self cropSize:self.inputView.image.size
                         toFitSize:self.outputView.bounds.size
               withoutCroppingRect:self.regionOfInterest.frame];

 CGImageRef cgImage = self.inputView.image.CGImage;

 CGImageRef cgCroppedImage =  CGImageCreateWithImageInRect (
                                         cgImage,
                                         sizedRect
                                         );

 self.outputView.image = [UIImage imageWithCGImage:cgCroppedImage];

特に考慮しなければならない問題がいくつかあります
。-返されるrectは、featuresRectをトリミングしないため、fitSizeよりも大きい場合があります。そのため、これを確認して、後で画像を拡大縮小する必要があります。切り抜きを適用します(または出力imageViewのscaleToFitを適切に設定します)。
-ROIフレームデータはどこから取得していますか?元のソース画像に対して相対的ですか、それともソース画像を含むimageViewに対して相対的ですか。後者の場合は、画像にクロップレクが適用されるため、imageViewではなくソース画像のサイズがimageViewと1:1になるようにする必要があります。
-出力imageViewは入力imageViewよりも小さいです。これが大きい場合はどうなるかわかりませんが、同様のスケーリングの問題が発生する可能性があります。
-ゼロ除算エラーチェックを追加する必要があります。

-     (CGRect)cropSize:(CGSize)sourceSize 
             toFitSize:(CGSize)fitSize
   withoutCroppingRect:(CGRect)featuresRect
{
    CGRect result = CGRectZero;
    BOOL fitSizeIsTaller;
    CGFloat sourceRatio = sourceSize.width / sourceSize.height;
    CGFloat fitRatio    = fitSize.width    / fitSize.height;
     if (sourceRatio > fitRatio)
            fitSizeIsTaller = YES;
     else   fitSizeIsTaller = NO;

        //size sourceRect to fitSize
    if (fitSizeIsTaller){
        result.size.width  = fitSize.width;
        result.size.height = result.size.width / sourceRatio;
    } else {
        result.size.height = fitSize.height;
        result.size.width  = result.size.height * sourceRatio;
    }
        //make sure it is at least as large as fitSize
    if (result.size.height < featuresRect.size.height) {
        result.size.height = featuresRect.size.height;
        result.size.width  = result.size.height * sourceRatio;
    }

    if (result.size.width  < featuresRect.size.width) {
        result.size.width  = featuresRect.size.width;
        result.size.height = result.size.width / sourceRatio;
    }

            //locate resultRect in center
    result.origin.x = (sourceSize.width  - result.size.width )/2;
    result.origin.y = (sourceSize.height - result.size.height)/2;

            //shift origin of result to make sure it includes ROI

    if (featuresRect.origin.x < result.origin.x )    //shift right?
              result.origin.x = featuresRect.origin.x;
    else
        if ((featuresRect.origin.x + featuresRect.size.width)  
               >  (result.origin.x + result.size.width))  //shift left?
            result.origin.x = (featuresRect.origin.x + featuresRect.size.width)
                            - result.size.width;

    if (featuresRect.origin.y < result.origin.y )    //shift up?
              result.origin.y = featuresRect.origin.y;
    else
        if ((featuresRect.origin.y + featuresRect.size.height)  
                > (result.origin.y + result.size.height))  //shift down?
            result.origin.y = (featuresRect.origin.y+featuresRect.size.height)
                            - result.size.height;
    return result;
}
于 2013-01-14T17:11:07.170 に答える