最近写一个应用,需要对图像中某一个像素点的颜色进行取样,并检测是否与特定颜色一致或相近,解决的办法如下:
一、像素点颜色取样
+ (UIColor*) getPixelColorAtLocation:(CGPoint)point inImage:(UIImage *)image {
UIColor* color = nil;
CGImageRef inImage = image.CGImage;
CGContextRef cgctx = [DetectColour createARGBBitmapContextFromImage:
inImage];
if(cgctx == NULL) {returnnil;/* error */}
size_tw = CGImageGetWidth(inImage);
size_th = CGImageGetHeight(inImage);
CGRect rect = {{0,0},{w,h}};
CGContextDrawImage(cgctx, rect, inImage);
unsignedchar* data = CGBitmapContextGetData (cgctx);
if(data != NULL) {
intoffset = 4*((w*round(point.y))+round(point.x));
intalpha = data[offset];
intred = data[offset+1];
intgreen = data[offset+2];
intblue = data[offset+3];
NSLog(@"offset: %i colors: RGB A %i %i %i %i",offset,red,green,
blue,alpha);
NSLog(@"x:%f y:%f", point.x, point.y);
color = [UIColor colorWithRed:(red/255.0f) green:(green/255.0f) blue:
(blue/255.0f) alpha:(alpha/255.0f)];
}
CGContextRelease(cgctx);
if(data) { free(data); }
returncolor;
}
+ (CGContextRef) createARGBBitmapContextFromImage:(CGImageRef) inImage {
CGContextRef context = NULL;
CGColorSpaceRef colorSpace;
void* bitmapData;
intbitmapByteCount;
intbitmapBytesPerRow;
size_tpixelsWide = CGImageGetWidth(inImage);
size_tpixelsHigh = CGImageGetHeight(inImage);
bitmapBytesPerRow = (pixelsWide * 4);
bitmapByteCount = (bitmapBytesPerRow * pixelsHigh);
colorSpace = CGColorSpaceCreateDeviceRGB();
if(colorSpace == NULL)
{
fprintf(stderr,"Error allocating color space\n");
returnNULL;
}
bitmapData = malloc( bitmapByteCount );
if(bitmapData == NULL)
{
fprintf (stderr,"Memory not allocated!");
CGColorSpaceRelease( colorSpace );
returnNULL;
}
context = CGBitmapContextCreate (bitmapData,
pixelsWide,
pixelsHigh,
8,
bitmapBytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedFirst);
if(context == NULL)
{
free (bitmapData);
fprintf (stderr,"Context not created!");
}
CGColorSpaceRelease( colorSpace );
returncontext;
}
二、颜色匹配计算
一是精确的匹配,通过生成两个CGColor,利用CGColorEqualToColor函数进行对比即可,如下:
[cpp]view plaincopy
//生成采样对照颜色(黑色)
UIColor* sampleColor = [UIColor colorWithRed:(0/255.0f) green:(0/255.0f)
blue:(0/255.0f) alpha:(255/255.0f)];
//比较
if(CGColorEqualToColor(detectedColor.CGColor, sampleColor.CGColor)) {
//处理
}
二是模糊的匹配,在RGB色彩空间下, 每个像素点的颜色有四个通道(R, G, B, Alpha),比较
两个颜色是否一致的方法,可以通过比较其向量的方式来进行,如下:
[cpp]view plaincopy
//获取颜色分量
constCGFloat* components = CGColorGetComponents(detectedColor.CGColor);
CGFloat Red, Green, Blue, Alpha;
Alpha = components[0];
Red = components[0+1];
....
//向量比较
floatdifference = pow( pow((red1 - red2), 2) + pow((green1 - green2), 2) +
pow((blue1 - blue2), 2), 0.5 );
至于阀值的设定,就需要大家根据实际情况来调整了,一般可设置为85,如果严格一点,则小一点;宽松一点,则可以设大一点。
网友评论