前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >OS实现智能背景

OS实现智能背景

原创
作者头像
花落花相惜
发布2021-12-04 10:26:51
发布2021-12-04 10:26:51
4180
举报

前言

实现:根据一张输入的图片,获取图片上的所有像素分析,并计算出一个颜色数组。具体步骤有:undefined 输入图片→图片转换→颜色获取→颜色筛选→我们要的颜色数组

github地址

输入图片

输入图片后,由于图片太大,所有我们先将图片进行缩放操作,减少计算量。

代码语言:txt
复制
// 1.此处缩放图片,缩小图片大小,提升计算速度
代码语言:txt
复制
    CGFloat scale = [UIScreen mainScreen].scale;
代码语言:txt
复制
    CGSize thumbSize = CGSizeMake(kImgW, image.size.height/image.size.width*kImgW);
代码语言:txt
复制
    UIGraphicsBeginImageContextWithOptions(thumbSize, NO, scale);
代码语言:txt
复制
    [image drawInRect:CGRectMake(0, 0, thumbSize.width, thumbSize.height)];
代码语言:txt
复制
    image = UIGraphicsGetImageFromCurrentImageContext();
代码语言:txt
复制
    UIGraphicsEndImageContext();

图片转换

我们要计算图片,需要将图片像素通过颜色空间转换为二进制数据,再将二进制数据转换为颜色,从而获取到这张图片的所有颜色数据。

代码语言:txt
复制
      // 2.将图片通过颜色空间转换为二进制数据。
代码语言:txt
复制
    int bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast;
代码语言:txt
复制
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
代码语言:txt
复制
    CGContextRef context = CGBitmapContextCreate(NULL,
代码语言:txt
复制
                                                 thumbSize.width,
代码语言:txt
复制
                                                 thumbSize.height,
代码语言:txt
复制
                                                 8,//bits per component
代码语言:txt
复制
                                                 thumbSize.width*4,
代码语言:txt
复制
                                                 colorSpace,
代码语言:txt
复制
                                                 bitmapInfo);
代码语言:txt
复制
    CGRect drawRect = CGRectMake(0, 0, thumbSize.width, thumbSize.height);
代码语言:txt
复制
    CGContextDrawImage(context, drawRect, image.CGImage);
代码语言:txt
复制
    CGColorSpaceRelease(colorSpace);
代码语言:txt
复制
    unsigned char* data = CGBitmapContextGetData (context);
代码语言:txt
复制
    if (data == NULL) return nil;

颜色获取

从获取到的二进制data数据中分别生成对应颜色,并通过LimitCount(现在颜色重复限制),去除颜色过少的颜色,并获得大于等于LimitCount数量的颜色。下一步,我们将除去重复颜色以及相近颜色。

代码语言:txt
复制
for (int x = 0; x < thumbSize.width; x ++) {
代码语言:txt
复制
        for (int y = 0; y < thumbSize.height; y ++) {
代码语言:txt
复制
            int offset = 4 * (x * y);
代码语言:txt
复制
            int red = data[offset];
代码语言:txt
复制
            int green = data[offset+1];
代码语言:txt
复制
            int blue = data[offset+2];
代码语言:txt
复制
            int alpha =  data[offset+3];
代码语言:txt
复制
            // 过滤掉白色
代码语言:txt
复制
            if (red!=255 & green!=255 & blue!=255) {
代码语言:txt
复制
                NSArray *clr = @[@(red),@(green),@(blue),@(alpha)];
代码语言:txt
复制
                // 当前颜色数量超过限制后,不再加入cls集合,如果需要计算最多颜色数量,则需要加入每一个大于LimitCount的颜色
代码语言:txt
复制
                if ([cls containsObject:clr] >= LimitCount)continue;
代码语言:txt
复制
                [cls addObject:clr];
代码语言:txt
复制
            }
代码语言:txt
复制
        }
代码语言:txt
复制
    }

除去颜色

去除颜色我们分两步,上一步获取到的颜色,在数组中,每一种颜色数量都是LimitCount。我们先去除重复的颜色。

1.颜色去重
代码语言:txt
复制
    NSArray *curColor = nil;
代码语言:txt
复制
    NSUInteger tempcount = 0;
代码语言:txt
复制
    NSEnumerator *enumerator = [cls objectEnumerator];
代码语言:txt
复制
    // 4.1除去重复颜色,获取单一颜色数组
代码语言:txt
复制
    while ((curColor = [enumerator nextObject]) != nil ){
代码语言:txt
复制
        if ([moreCls containsObject:curColor] > 0) continue;
代码语言:txt
复制
        tempcount = [cls countForObject:curColor];
代码语言:txt
复制
        if (tempcount < LimitCount) continue;
代码语言:txt
复制
        [moreCls addObject:curColor];
代码语言:txt
复制
    }
2.颜色去重

到这一步,我们就可以根据自己的项目需求再次剔除颜色,获取我们想要的颜色结果了。undefined 这一步,我们首先需要了解HSV颜色空间模型,这样我们才能更好的筛选出我们想要的颜色。

HSV颜色空间模型

观察模型,我们发现Value值较小的全是黑色的。Saturation值较小的全是白色灰色,所有我们首先去除的就是这类颜色。undefined 然后,某一个颜色的立体颜色,周围都是相近的颜色,我们也需要剔除,具体代码如下。

代码语言:txt
复制
// 4.2除去相近颜色算法。
代码语言:txt
复制
    NSArray *currentH = nil;
代码语言:txt
复制
    enumerator = [moreCls objectEnumerator];
代码语言:txt
复制
    while ((curColor = [enumerator nextObject]) != nil ){
代码语言:txt
复制
        int red = [curColor[0] intValue];
代码语言:txt
复制
        int green = [curColor[1] intValue];
代码语言:txt
复制
        int blue = [curColor[2] intValue];
代码语言:txt
复制
    //        int alpha =  [curColor[3] intValue];
代码语言:txt
复制
        // RGB转HSV算法
代码语言:txt
复制
        CGFloat max = MAX(MAX(red, blue), green);
代码语言:txt
复制
        CGFloat min = MIN(MIN(red, blue), green);
代码语言:txt
复制
        CGFloat hue = 0,s,value;
代码语言:txt
复制
        value = max;
代码语言:txt
复制
        s     = (max-min)/max;
代码语言:txt
复制
        if (red == max) hue = (green-blue)/(max-min)* 60;
代码语言:txt
复制
        if (green == max) hue = 120+(blue-red)/(max-min)* 60;
代码语言:txt
复制
        if (blue == max) hue = 240 +(red-green)/(max-min)* 60;
代码语言:txt
复制
        if (hue < 0) hue = hue + 360;
代码语言:txt
复制
        NSEnumerator *moreenur = [huarr objectEnumerator];
代码语言:txt
复制
        BOOL isAdd = YES;
代码语言:txt
复制
        // HSV模型可参考https://baike.baidu.com/item/HSV/547122?fr=aladdin
代码语言:txt
复制
        while ((currentH = [moreenur nextObject]) != nil ){
代码语言:txt
复制
            // 抛弃灰白色,和暗黑色颜色,可参考HSV模型
代码语言:txt
复制
            if (s > 0.2 && value > 0.3*255) {
代码语言:txt
复制
                if (value < 0.5*255) { // 根据value大小抛弃范围不同
代码语言:txt
复制
                    // 抛弃某一个颜色周围的相近颜色
代码语言:txt
复制
                    if (fabs(hue-[currentH[0] floatValue]) < 180 && fabs(s-[currentH[1] floatValue])*255 < 125 && fabs(value-[currentH[2] floatValue]) < 0.5*255) {
代码语言:txt
复制
                        isAdd = NO;
代码语言:txt
复制
                        break;
代码语言:txt
复制
                    }
代码语言:txt
复制
                }else{
代码语言:txt
复制
                    // 抛弃某一个颜色周围的相近颜色
代码语言:txt
复制
                    if (fabs(hue-[currentH[0] floatValue]) < 20 && fabs(s-[currentH[1] floatValue])*255 < 25 && fabs(value-[currentH[2] floatValue]) < 25) {
代码语言:txt
复制
                        isAdd = NO;
代码语言:txt
复制
                        break;
代码语言:txt
复制
                    }
代码语言:txt
复制
                }
代码语言:txt
复制
            }else{
代码语言:txt
复制
                isAdd = NO;
代码语言:txt
复制
            }
代码语言:txt
复制
        }
代码语言:txt
复制
        if (isAdd) {
代码语言:txt
复制
            // 确认的颜色HSV转RGB算法。注意,直接用RGB颜色部分颜色会出问题,建议还是再转换一次。
代码语言:txt
复制
            [huarr addObject:@[@(hue),@(s),@(value)]];
代码语言:txt
复制
            if (s == 0)
代码语言:txt
复制
            red = green = blue = value;
代码语言:txt
复制
            else{
代码语言:txt
复制
            hue /= 60;
代码语言:txt
复制
            int i = hue;
代码语言:txt
复制
            CGFloat f = hue - i;
代码语言:txt
复制
            CGFloat a = value * ( 1 - s );
代码语言:txt
复制
            CGFloat b = value * ( 1 - s * f );
代码语言:txt
复制
            CGFloat c = value * ( 1 - s * (1 - f ) );
代码语言:txt
复制
                switch (i) {
代码语言:txt
复制
                    case 0: red = value; green = c; blue = a;
代码语言:txt
复制
                        break;
代码语言:txt
复制
                    case 1: red = b; green = value; blue = a;
代码语言:txt
复制
                        break;
代码语言:txt
复制
                    case 2: red = a; green = value; blue = c;
代码语言:txt
复制
                        break;
代码语言:txt
复制
                    case 3: red = a; green = b; blue = value;
代码语言:txt
复制
                        break;
代码语言:txt
复制
                    case 4: red = c; green = a; blue = value;
代码语言:txt
复制
                        break;
代码语言:txt
复制
                        case 5: red = value; green = a; blue = b;
代码语言:txt
复制
                    default:
代码语言:txt
复制
                        break;
代码语言:txt
复制
                }
代码语言:txt
复制
            }
代码语言:txt
复制
            UIColor *c = [UIColor colorWithRed:(red/255.0f) green:(green/255.0f) blue:(blue/255.0f) alpha:([curColor[3] intValue]/255.0f)];
代码语言:txt
复制
            [colorArr addObject:c];
代码语言:txt
复制
        }
代码语言:txt
复制
    }

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
    • 输入图片
    • 图片转换
    • 颜色获取
    • 除去颜色
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档