问题
MY code: How to manage RGB value for differet shades of face,and how to apply? this code will change the color of face along with hair,but i want 1.only face to be colored excluding hair.
-(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);
}
回答1:
Try to use GPUImage Framework by Brad Larson:
https://github.com/BradLarson/GPUImage
This is very powerful framework for working with images.
Read this question:
GPUImage create a custom Filter that change selected colors
Hope it helps!
回答2:
The quick answer is to change your ORs:
if( ( (R>0)&&(R<260) ) || ((G>0)&&(G<210)) || ((B>0) && (B<170)))
to ANDs:
if( ( (R>0)&&(R<260) ) && ((G>0)&&(G<210)) && ((B>0) && (B<170)))
Then adjust your RGB ranges to approximate the range of skin tones in the image (try with some sliders in your UI).
By the way, I presume you know that this:
rawData[ii+1]=R;//13;
rawData[ii+2]=G;//43;
rawData[ii+3]=value;//63
is assigning the red channel to the green channel, the green channel to the blue channel, and value
to the ALPHA channel. I don't expect that is what you want.
Also your needToModified
image is probably intended to be the same image as firstImageV.image
, which is not reflected in your code as it is now.
This approach will only work if your identified colour ranges are wholly and only present in flesh regions of the image.
A long answer could look at more sophisticated selection of colour ranges, alternative ways of selecting image regions, the use of CIFilter
or the openCV framework...
回答3:
Try Masking the image ... it will help to change the specific range of colors defined in mask
Code:
- (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 According to the docs, it Returns a read-only pointer to the bytes of a CFData object., are you sure you're not looking for CFDataGetBytes which Copies the byte contents of a CFData object to an external buffer. In which case you'll have to allocate your buffer to contain width * height * bpp. Once you have this copy, you can manipulate it anyway you want to create the new picture.
Pixel Selection According to your question, I seem to understand that you want to change skin color from White to Black. Your current code iterates over every pixel to change its color. You should evaluate the "distance" between the pixel color and what you're looking for, and if it's below a certain threshold process it. It might be easier to perform the operation in HSV than by dealing with RGB colors
回答5:
1) Get a CGPath of face where you want to apply your algorithm. 2) Get width of CGimage.
int width = CGImageGetWidth(image);
3) Get pixel CGPoint of currently processing pixel. Check for the condition before applying your algorithm. And then apply your condition. That's it. Here is the sample portion of code.
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:
make the face and the hair as objects. object have color and have a global method to change their colors. then in your main,make both objects (hair, face) and specify what you want to color exactly. This is the right approach. hope it helps!
来源:https://stackoverflow.com/questions/16236934/how-to-change-the-skin-color-of-face-from-the-source-image-in-ios