14

MY コード:顔のさまざまな色合いの RGB 値を管理する方法と適用方法は? このコードは髪と一緒に顔の色を変更しますが、1.髪を除いて顔だけを色付けしたいです。

    -(void)changeSkinColorValue:(float)value WithImage:(UIImage*)needToModified
    {

        CGContextRef ctx;

        CGImageRef imageRef = needToModified.CGImage;
        NSUInteger width = CGImageGetWidth(imageRef);
        NSUInteger height = CGImageGetHeight(imageRef);
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        //unsigned char *rawData = malloc(firstImageV.image.size.height * firstImageV.image.size.width * 10);

        CFMutableDataRef m_DataRef = CFDataCreateMutableCopy(0, 0,CGDataProviderCopyData(CGImageGetDataProvider(firstImageV.image.CGImage)));
        UInt8 *rawData = (UInt8 *) CFDataGetMutableBytePtr(m_DataRef);
        int length = CFDataGetLength(m_DataRef);
        NSUInteger bytesPerPixel = 4;
        NSUInteger bytesPerRow = bytesPerPixel * firstImageV.image.size.width;
        NSUInteger bitsPerComponent = 8;

                CGContextRef context1 = CGBitmapContextCreate(rawData, firstImageV.image.size.width, firstImageV.image.size.height, bitsPerComponent, bytesPerRow, colorSpace,                     kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
        CGColorSpaceRelease(colorSpace);

        CGContextDrawImage(context1, CGRectMake(0, 0, firstImageV.image.size.width, firstImageV.image.size.height), imageRef);

        NSLog(@"%d::%d",width,height);


       // for(int ii = 0 ; ii < 250   ; ii+=4)
        //{

            for(int ii = 0 ; ii < length ; ii+=4)
            {
            //NSLog(@"Raw data %s",rawData);

            int  R = rawData[ii];
            int G = rawData[ii+1];
            int B = rawData[ii+2];

            //        NSLog(@"%d   %d   %d", R, G, B);
            //if( ( (R>60)&&(R<237) ) || ((G>10)&&(G<120))||((B>4) && (B<120)))
                 //       if( ( (R>100)&&(R<186) ) || ((G>56)&&(G<130))||((B>30) && (B<120)))
                //        if( ( (R>188)&&(R<228) ) || ((G>123)&&(G<163))||((B>85) && (B<125)))
                       // if( ( (R>95)&&(R<260) ) || ((G>40)&&(G<210))||((B>20) && (B<170)))

                        //new code......

                if( ( (R>0)&&(R<260) ) || ((G>0)&&(G<210))||((B>0) && (B<170)))

                    {
                        rawData[ii+1]=R;//13;
                        rawData[ii+2]=G;//43;
                        rawData[ii+3]=value;//63
                    }
                }


        ctx = CGBitmapContextCreate(rawData,
                            CGImageGetWidth( imageRef ),
                            CGImageGetHeight( imageRef ),
                            8,
                            CGImageGetBytesPerRow( imageRef ),
                            CGImageGetColorSpace( imageRef ),
                            kCGImageAlphaPremultipliedLast );

        imageRef = CGBitmapContextCreateImage(ctx);
        UIImage* rawImage = [UIImage imageWithCGImage:imageRef];
        //UIImageView *ty=[[UIImageView alloc]initWithFrame:CGRectMake(100, 200, 400, 400)];
        //ty.image=rawImage;
        //[self.view addSubview:ty];
        [secondImageV setImage:rawImage];
        CGContextRelease(context1);
        CGContextRelease(ctx);  
        free(rawData);
    }
4

6 に答える 6

1

Brad Larson による GPUImage Framework を使用してみてください。

https://github.com/BradLarson/GPUImage

これは、画像を操作するための非常に強力なフレームワークです。

この質問を読んでください:

GPUImage は、選択した色を変更するカスタム フィルターを作成します

それが役に立てば幸い!

于 2013-05-17T21:09:16.633 に答える
0

顔と髪をオブジェクトにします。オブジェクトには色があり、色を変更するグローバル メソッドがあります。次に、メインで両方のオブジェクト(髪、顔)を作成し、正確に色を付けたいものを指定します。これが正しいアプローチです。それが役に立てば幸い!

于 2015-02-25T16:23:17.037 に答える
0

1) アルゴリズムを適用する顔の CGPath を取得します。2) CGimage の幅を取得します。

int width = CGImageGetWidth(image);

3) 現在処理中のピクセルのピクセル CGPoint を取得します。アルゴリズムを適用する前に条件を確認してください。そして、条件を適用します。それでおしまい。コードのサンプル部分を次に示します。

CGFloat pointY = (int)(i/4)/(int)width;
CGFloat pointX = (int)(i/4)%(int)width;
CGPoint point = CGPointMake(pointX, pointY);

if (CGPathContainsPoint(yourFacePath, NULL, point, NO))
{
    if( ( (R>0)&&(R<260) ) || ((G>0)&&(G<210))||((B>0) && (B<170)))
    {
        rawData[ii+1]=R;//13;
        rawData[ii+2]=G;//43;
        rawData[ii+3]=value;//63
    }
}
于 2013-09-13T07:16:24.707 に答える
0

簡単な答えは、OR を変更することです。

            if( ( (R>0)&&(R<260) ) || ((G>0)&&(G<210)) || ((B>0) && (B<170)))

AND へ:

            if( ( (R>0)&&(R<260) ) && ((G>0)&&(G<210)) && ((B>0) && (B<170)))

次に、RGB 範囲を調整して、画像内の肌の色調の範囲を近似させます (UI でいくつかのスライダーを試してください)。

ところで、次のことを知っていると思います。

        rawData[ii+1]=R;//13;
        rawData[ii+2]=G;//43;
        rawData[ii+3]=value;//63

赤のチャンネルを緑のチャンネルに、緑のチャンネルを青のチャンネルにvalue、ALPHA チャンネルに割り当てています。それがあなたの望むものだとは思いません。

また、needToModified画像はおそらく と同じ画像になるように意図firstImageV.imageされていますが、現在のコードには反映されていません。

このアプローチは、識別された色の範囲が完全に画像の肌の領域にのみ存在する場合にのみ機能します。

長い答えは、色範囲のより洗練された選択、画像領域を選択する別の方法、CIFilterまたはopenCVフレームワークの使用を検討することができます...

于 2013-04-26T17:43:10.973 に答える