如何在iOS中从源图像更改脸部的肤色?

我的代码:如何pipe理不同色调的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); } 

尝试使用Brad Larson的GPUImage框架:

https://github.com/BradLarson/GPUImage

这是处理图像的非常强大的框架。

阅读这个问题:

GPUImage创build一个自定义filter来更改所选的颜色

希望能帮助到你!

快速的答案是改变你的ORs:

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

与ANDs:

  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相同的图像,它不会像现在这样反映在您的代码中。

这种方法只有在您确定的颜色范围完全且仅存在于图像的肉质区域时才有效。

一个长的答案可以看看更复杂的色彩select范围,select图像区域的替代方法,使用CIFilter或openCV框架…

尝试蒙版图像…这将有助于更改掩码中定义的特定颜色范围

码:

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

CFDataGetBytePtr根据文档,它返回一个指向CFData对象字节的只读指针,你确定没有查找将CFData对象的字节内容复制到外部缓冲区的CFDataGetBytes。 在这种情况下,你将不得不分配你的缓冲区来包含width * height * bpp。 一旦你有这个副本,你可以操纵它,无论如何你想创build新的图片。

像素select根据你的问题,我似乎明白,你想改变肤色从白色到黑色。 您当前的代码迭代每个像素以更改其颜色。 您应该评估像素颜色与您要查找的内容之间的“距离”,以及是否低于某个阈值处理它。 在HSV中执行操作可能比处理RGB颜色更容易

1)获取你想要应用你的algorithm的CGPath。 2)获取CGimage的宽度。

 int width = CGImageGetWidth(image); 

3)获取当前处理像素的像素CGPoint。 在应用您的algorithm之前检查条件。 然后应用你的条件。 而已。 这是代码的示例部分。

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

以面部和头发为对象。 对象有颜色,并有一个全局的方法来改变他们的颜色。 然后在你的主要,使两个对象(头发,脸),并指定你想要准确的颜色。 这是正确的做法。 希望能帮助到你!