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
Custom View Which Looks Like Uialertview
iPhone Opengl Es 2.0 - Pixel Perfect Textures
Create Ssl Connection Using Certificate
A Server with the Specified Hostname Could Not Be Found
Push View Programmatically in Callback, Swiftui
"Unable to Validate Your Application Error" While Uploading a New Version of iOS App
Can't Import Embedded Framework with Xcode 6 Gm
Xcode 6.3.2 Can't Run on Osx 10.11 El Capitan Developer Preview 3
How Big Can the Payload Be When Sending Data via Watchconnectivity
Detect and Use Optional External C Library at Runtime in Objective-C
Google Objective-C API 'Gtl' with Swift
Schedule Number of Local Notifications
Ios/Swift - Hide/Show Uitabbarcontroller When Scrolling Down/Up
Swift How to Modify Exif Info in Images Taken from Mobile Camera
Endless Scrolling Background in Spritekit
How to Move to the Next Page in Facebook JSON Response Using iOS Sdk