Как изменить цвет кожи лица с исходного изображения в ios? - программирование
Подтвердить что ты не робот

Как изменить цвет кожи лица с исходного изображения в ios?

МОЙ код: Как управлять значением 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);
    }
4b9b3361

Ответ 2

Быстрый ответ: изменить ORS:

            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, чтобы приблизиться к диапазону оттенков кожи на изображении (попробуйте с некоторыми слайдерами в пользовательском интерфейсе).

Кстати, я полагаю, вы знаете, что это:

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

назначает красный канал зеленому каналу, зеленый канал - синему каналу, а value - каналу ALPHA. Я не ожидаю, что это то, что вы хотите.

Также ваше изображение needToModified, вероятно, должно быть тем же изображением, что и firstImageV.image, которое не отражается в вашем коде, как сейчас.

Этот подход будет работать, только если ваши идентифицированные цветовые диапазоны полностью и только присутствуют в областях плоти изображения.

В длинном ответе можно рассмотреть более сложный выбор цветовых диапазонов, альтернативные способы выбора областей изображения, использование CIFilter или рамки openCV...

Ответ 3

Попробуйте маскировать изображение... это поможет изменить определенный диапазон цветов, определенных в маске

код:

- (UIImage *)doctorTheImage:(UIImage *)originalImage
{

   const float brownsMask[6] = {85, 255, 85, 255, 85, 255};


    UIImageView *imageView = [[UIImageView alloc] initWithImage:originalImage];

    UIGraphicsBeginImageContext(originalImage.size);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetRGBFillColor (context, 1.0,1.0, 1.0, 1);


    CGContextFillRect(context, CGRectMake(0, 0, imageView.image.size.width, imageView.image.size.height));

    CGImageRef brownRef = CGImageCreateWithMaskingColors(imageView.image.CGImage, brownsMask);

    CGRect imageRect = CGRectMake(0, 0, imageView.image.size.width, imageView.image.size.height);

    CGContextTranslateCTM(context, 0, imageView.image.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    //CGImageRef whiteRef = CGImageCreateWithMaskingColors(brownRef, whiteMask);
    CGContextDrawImage (context, imageRect, brownRef);

    //[originalImage drawInRect:CGRectMake(0, 0, imageView.image.size.width, imageView.image.size.height)];

    CGImageRelease(brownRef);
   // CGImageRelease(whiteRef);

    UIImage *doctoredImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return doctoredImage;
}

Ответ 4

CFDataGetBytePtr В соответствии с документами он возвращает указатель на чтение только для байтов объекта CFData. Вы уверены, что не ищете CFDataGetBytes, который копирует содержимое байта объекта CFData во внешний буфер. В этом случае вам придется выделять свой буфер, чтобы он имел ширину * height * bpp. Если у вас есть эта копия, вы можете манипулировать ею в любом случае, вы хотите создать новое изображение.

Выбор пикселей. Согласно вашему вопросу, я, кажется, понимаю, что вы хотите изменить цвет кожи от белого до черного. Ваш текущий код выполняет итерацию по каждому пикселю, чтобы изменить его цвет. Вы должны оценить "расстояние" между цветом пикселя и тем, что вы ищете, и если оно ниже определенного порогового процесса. Возможно, было бы легче выполнить операцию в HSV, чем с использованием цветов RGB

Ответ 5

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
    }
}

Ответ 6

сделайте лицо и волосы как предметы. объект имеет цвет и имеет глобальный метод изменения цвета. затем, в основном, сделайте оба объекта (волосы, лицо) и укажите, что вы хотите точно рассказать. Это правильный подход. надеюсь, что это поможет!