获取图片中黑色/白色像素点比例

637 阅读2分钟

图片黑白像素点比例检测方法,可通过比例来判断图片是否为几乎纯黑或者纯白,来判断是否为异常情况。具体逻辑见下面代码,需要注意图片的alphaInfo,这个值会影响到取像素值的准确与否

- (BOOL)isImagePredominantlyBlackOrWhite:(UIImage *)image threshold:(CGFloat)threshold {

    // 获取图片的CGImage
    CGImageRef imageRef = [image CGImage];

    // 图片宽度和高度
    size_t width = CGImageGetWidth(imageRef);
    size_t height = CGImageGetHeight(imageRef);

    // 配置图片上下文
    CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef);
    CGContextRef context = CGBitmapContextCreate(nil, width, height, 8, 0, CGImageGetColorSpace(imageRef), alphaInfo);

    // 在上下文中绘制图片
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);

    // 获取图片数据
    unsigned char *data = CGBitmapContextGetData(context);
    if (data == nil) {
        CGContextRelease(context);
        return NO; // 无法获取图片数据
    }
    
    // 统计纯黑和纯白的像素数量
    int blackPixelCount = 0;
    int whitePixelCount = 0;
    
    // 设置一个宽松值
    CGFloat blackLoose = 30;
    CGFloat whiteLoose = 225;
    
    /// RGB在前
    BOOL firstRGB = kCGImageAlphaNone == alphaInfo || kCGImageAlphaPremultipliedLast == alphaInfo || kCGImageAlphaLast == alphaInfo || kCGImageAlphaNoneSkipLast == alphaInfo;
    
    // RGB在后
    BOOL lastRGB = kCGImageAlphaPremultipliedFirst == alphaInfo || kCGImageAlphaFirst == alphaInfo || kCGImageAlphaNoneSkipFirst == alphaInfo;
    
    for (int i = 0; i < width * height * 4; i += 4) {
        if (firstRGB) {
            if (data[i] <= blackLoose && data[i + 1] <= blackLoose && data[i + 2] <= blackLoose) {
                blackPixelCount++;
            } else if (data[i] >= whiteLoose && data[i + 1] >= whiteLoose && data[i + 2] >= whiteLoose) {
                whitePixelCount++;
            }
        } else if (lastRGB) {
            if (data[i + 1] <= blackLoose && data[i + 2] <= blackLoose && data[i + 3] <= blackLoose) {
                blackPixelCount++;
            } else if (data[i + 1] >= whiteLoose && data[i + 2] >= whiteLoose && data[i + 3] >= whiteLoose) {
                whitePixelCount++;
            }
        } else {
            // kCGImageAlphaOnly
        }
    }
    
    CGContextRelease(context);
    
    // 计算比例
    CGFloat totalPixels = width * height;
    CGFloat blackRatio = (CGFloat)blackPixelCount / totalPixels;
    CGFloat whiteRatio = (CGFloat)whitePixelCount / totalPixels;

    NSLog(@"黑色比例为%f",blackRatio);
    NSLog(@"白色比例为%f",whiteRatio);

    // 判断是否90%以上为纯黑或纯白
    return (blackRatio >= threshold || whiteRatio >= threshold);
}

使用

// 视图转图片
- (UIImage *)imageFromView:(UIView *)view {
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0.0);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}


- (void)viewDidLoad {
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor blackColor];
    UIImage *image = [self imageFromView:self.view];

    // 设置阈值
    CGFloat threshold = 0.9; // 90%
    
    // 检测图片是否90%以上为纯黑或纯白
    if ([self isImagePredominantlyBlackOrWhite:image threshold:0.9]) {
        NSLog(@"图片为90以上纯黑或者纯白");
    } else {
        NSLog(@"精选频道图片正常");
    }
    
    // Do any additional setup after loading the view.
}