12

これは私が達成する必要があるものです:

  • カメラまたはギャラリーから画像を取得
  • 画像から背景を削除して保存する
  • 背景は黒または白である必要があります
  • また、背景とともに影を削除する必要があります

結果の例:

元の画像

ここに画像の説明を入力

結果画像

ここに画像の説明を入力

これは私が試したことです:

CGFloat colorMasking[6]={222,255,222,255,222,255};
CGImageRef imageRef = CGImageCreateWithMaskingColors([IMG CGImage], colorMasking);
UIImage  *resultThumbImage = [UIImage imageWithCGImage:imageRef scale:ThumbImage.scale orientation:IMG.imageOrientation];

白い背景でのみ機能します。より効果的ではありません。上記の画像に配置した正確な結果を達成する必要があります。

私はいくつかの参考文献も参照しました:

iOSで画像の背景色をマスクする方法

iPhoneアプリで画像の背景を削除する方法は?

キャプチャした画像の背景色をカメラから白に変更する

誰かがこれを達成するのを手伝ってくれますか?

任意の参照または非常に高く評価されます。

前もって感謝します。

4

2 に答える 2

8

一般に、経験則として、背景色が他のすべての色と異なるほど、画像を前景と背景に分割しやすくなります。このような場合、@Chris が既に提案したように、単純なクロマ キーの実装を使用することができます。以下は、 Wikipediaで説明されているキーイングの簡単な実装です(C++ で記述されていますが、Objective-C に変換するのは簡単なはずです)。

/**
 * @brief Separate foreground from background using simple chroma keying.
 *
 * @param imageBGR   Image with monochrome background
 * @param chromaBGR  Color of the background (using channel order BGR and range [0, 255])
 * @param tInner     Inner threshold, color distances below this value will be counted as foreground
 * @param tOuter     Outer threshold, color distances above this value will be counted as background
 *
 * @return  Mask (0 - background, 255 - foreground, [1, 255] - partially fore- and background)
 *
 * Details can be found on [Wikipedia][1].
 *
 * [1]: https://en.wikipedia.org/wiki/Chroma_key#Programming
 */
cv::Mat1b chromaKey( const cv::Mat3b & imageBGR, cv::Scalar chromaBGR, double tInner, double tOuter )
{
    // Basic outline:
    //
    // 1. Convert the image to YCrCb.
    // 2. Measure Euclidean distances of color in YCrBr to chroma value.
    // 3. Categorize pixels:
    //   * color distances below inner threshold count as foreground; mask value = 0
    //   * color distances above outer threshold count as background; mask value = 255
    //   * color distances between inner and outer threshold a linearly interpolated; mask value = [0, 255]

    assert( tInner <= tOuter );

    // Convert to YCrCb.
    assert( ! imageBGR.empty() );
    cv::Size imageSize = imageBGR.size();
    cv::Mat3b imageYCrCb;
    cv::cvtColor( imageBGR, imageYCrCb, cv::COLOR_BGR2YCrCb );
    cv::Scalar chromaYCrCb = bgr2ycrcb( chromaBGR ); // Convert a single BGR value to YCrCb.

    // Build the mask.
    cv::Mat1b mask = cv::Mat1b::zeros( imageSize );
    const cv::Vec3d key( chromaYCrCb[ 0 ], chromaYCrCb[ 1 ], chromaYCrCb[ 2 ] );

    for ( int y = 0; y < imageSize.height; ++y )
    {
        for ( int x = 0; x < imageSize.width; ++x )
        {
            const cv::Vec3d color( imageYCrCb( y, x )[ 0 ], imageYCrCb( y, x )[ 1 ], imageYCrCb( y, x )[ 2 ] );
            double distance = cv::norm( key - color );

            if ( distance < tInner )
            {
                // Current pixel is fully part of the background.
                mask( y, x ) = 0;
            }
            else if ( distance > tOuter )
            {
                // Current pixel is fully part of the foreground.
                mask( y, x ) = 255;
            }
            else
            {
                // Current pixel is partially part both, fore- and background; interpolate linearly.
                // Compute the interpolation factor and clip its value to the range [0, 255].
                double d1 = distance - tInner;
                double d2 = tOuter   - tInner;
                uint8_t alpha = static_cast< uint8_t >( 255. * ( d1 / d2 ) );

                mask( y, x ) = alpha;
            }
        }
    }

    return mask;
}

完全に機能するコード例は、このGithub Gistにあります。

残念ながら、あなたの例はその経験則に固執していません。前景と背景は強度のみが異なるため、良好な分離のための単一のグローバル パラメータ セットを見つけることは困難 (または不可能) です。

  1. オブジェクトの周りに黒い線があるが、オブジェクトの内側に穴がない ( tInner=50tOuter=90) マスク1 背景置換 1

  2. オブジェクトの周りに黒い線はありませんが、オブジェクトの内側に穴があります ( tInner=100tOuter=170) マスク 2 背景置換 2

そのため、画像の背景を変更できない場合は、より複雑なアプローチが必要になります。ただし、迅速で単純な実装例は範囲外ですが、画像のセグメンテーションアルファ マッティングの関連領域を調べたい場合があります。

于 2015-07-19T13:37:33.120 に答える
4

クロマキーを使用する必要があると思います-黒を選んでいますが、うまくいくはずです。

1つの簡単なグーグルがこれを思いつきまし

于 2015-07-14T08:00:27.320 に答える