Get Average Color of Uiimage in Swift

Get average color of UIImage in Swift

CoreImage in iOS 9: use the CIAreaAverage filter and pass the extent of your entire image to be averaged.

Plus, it's much faster since it'll either be running on the GPU or as a highly-optimized CPU CIKernel.

How to calculate the average color of a UIImage?

You'll need to use the Accelerate Library, Apple has a manual with some sample code, it'll work in Swift or ObjC

Here is a sample to get you going, I use this to calculate a person's heart rate and heart rate variability using the change in colors of a finger over the camera lens.

Full code here:
https://github.com/timestocome/SwiftHeartRate/blob/master/Swift%20Pulse%20Reader/ViewController.swift

It's in an older version of Swift but I think you'll get the idea. I was doing this at 240 fps, but with a cropped smaller section of the image.

Relevant code here:

// compute the brightness for reg, green, blue and total
// pull out color values from pixels --- image is BGRA
var greenVector:[Float] = Array(count: numberOfPixels, repeatedValue: 0.0)
var blueVector:[Float] = Array(count: numberOfPixels, repeatedValue: 0.0)
var redVector:[Float] = Array(count: numberOfPixels, repeatedValue: 0.0)

vDSP_vfltu8(dataBuffer, 4, &blueVector, 1, vDSP_Length(numberOfPixels))
vDSP_vfltu8(dataBuffer+1, 4, &greenVector, 1, vDSP_Length(numberOfPixels))
vDSP_vfltu8(dataBuffer+2, 4, &redVector, 1, vDSP_Length(numberOfPixels))

// compute average per color
var redAverage:Float = 0.0
var blueAverage:Float = 0.0
var greenAverage:Float = 0.0

vDSP_meamgv(&redVector, 1, &redAverage, vDSP_Length(numberOfPixels))
vDSP_meamgv(&greenVector, 1, &greenAverage, vDSP_Length(numberOfPixels))
vDSP_meamgv(&blueVector, 1, &blueAverage, vDSP_Length(numberOfPixels))

// convert to HSV ( hue, saturation, value )
// this gives faster, more accurate answer
var hue: CGFloat = 0.0
var saturation: CGFloat = 0.0
var brightness: CGFloat = 0.0
var alpha: CGFloat = 1.0

var color: UIColor = UIColor(red: CGFloat(redAverage/255.0), green: CGFloat(greenAverage/255.0), blue: CGFloat(blueAverage/255.0), alpha: alpha)
color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha)

// 5 count rolling average
let currentHueAverage = hue/movingAverageCount
movingAverageArray.removeAtIndex(0)
movingAverageArray.append(currentHueAverage)

let movingAverage = movingAverageArray[0] + movingAverageArray[1] + movingAverageArray[2] + movingAverageArray[3] + movingAverageArray[4]

UIImage and Finding the Average UIColor of Center Pixels

You are only iterating the pixels from startPoint to one less of endPoint. Maybe using

for(int row = yStartPoint; row <= yEndPoint; row++)
// ...
for(int column = xStartPoint; column <= xEndPoint; column++)

will fix it?

Also you will have to adjust your rowPtr to start at your xStartPoint:

const UInt8 *rowPtr = rawPixelData + bytesPerRow * row + stride * xStartPoint;

Else you will be starting at x = 0 every row.

And your average should be calculated like so:

int numberOfPixels = (yEndPoint - yStartPoint) * (xEndPoint - xStartPoint);

red /= numberOfPixels;
green /= numberOfPixels;
blue /= numberOfPixels;

return [UIColor colorWithRed:red / 255.0 green:green / 255.0 blue:blue / 255.0 alpha:1.0f];

Objective-c - Getting least used and most used color in a image

Not sure about finding most color or least color, but here is a method to find out the average color.

- (UIColor *)averageColor {

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
unsigned char rgba[4];
CGContextRef context = CGBitmapContextCreate(rgba, 1, 1, 8, 4, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

CGContextDrawImage(context, CGRectMake(0, 0, 1, 1), self.CGImage);
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);

if(rgba[3] > 0) {
CGFloat alpha = ((CGFloat)rgba[3])/255.0;
CGFloat multiplier = alpha/255.0;
return [UIColor colorWithRed:((CGFloat)rgba[0])*multiplier
green:((CGFloat)rgba[1])*multiplier
blue:((CGFloat)rgba[2])*multiplier
alpha:alpha];
}
else {
return [UIColor colorWithRed:((CGFloat)rgba[0])/255.0
green:((CGFloat)rgba[1])/255.0
blue:((CGFloat)rgba[2])/255.0
alpha:((CGFloat)rgba[3])/255.0];
}
}

You can probably follow a similar approach to find out the most used color.

Also check this answer about counting red color pixels in an image.



Related Topics



Leave a reply



Submit