Tôi đã tự hỏi liệu có ai đó có thể giúp tôi tìm ra cách tôi có thể xác định màu chính và phụ trong UIImage không. Tôi đã không thể tìm thấy bất kỳ điều gì hữu ích khủng khiếp trong Google.Xác định màu chính và phụ của UIImage
Trả lời
Các kỹ sư tại Panic đã viết một thuật toán để phân tích màu tương tự như được tìm thấy trong iTunes 11 (để xác định màu chính, phụ và chi tiết tốt). Họ đã đăng một lời giải thích về cách nó hoạt động và mã số on their blog.
Tuyệt vời! Chính xác những gì tôi đang tìm kiếm. Cảm ơn –
Tôi đã làm một bản dịch thô này vào iOS Swift và sau đó làm việc với nó cho đến khi nó đủ nhanh cho một thiết bị iOS để xử lý không chậm trễ ngay [Here: AverageColor] (https://github.com/Sethmr/AverageColor) – Sethmr
Dựa trên blog Panic trên, đây là một phương pháp nhanh (< 10ms tùy thuộc vào biến).
Đưa một đầu vào UIImage và đầu ra:
- màu nền
- màu chính
- màu thứ
Khi đi qua các UIImage đến phương pháp, vượt qua một 'cạnh' cũng . Điều này nói đến đó là một phần của hình ảnh được tiếp xúc với phần còn lại của xem (xem hình ảnh dưới đây để biết rõ):
- cạnh = 0 = top
- cạnh = 1 = trái
- cạnh = 2 = đáy
- cạnh = 3 = đúng
**
Bước 1.
** đặt thứ nguyên. Điều này đề cập đến bao nhiêu điểm ảnh trên và xuống hình ảnh nên được.
Bước 2. thay đổi kích thước hình ảnh dựa trên đầu vào thứ nguyên (ví dụ: 20 x 20 = 400px).
Bước 3. tạo mảng màu, kéo giá trị RGB từ dữ liệu thô được tạo ở bước 2. Ngoài ra, thu thập các pixel chạy dọc theo cạnh đã chọn.
Bước 4. tính cạnh hoặc màu nền. Điều này được sử dụng sau này để tương phản các màu nhấn, theo blog Panic.
Bước 5. đi qua các màu đã thu thập (giá trị RGB) và xác định xem chúng có tương phản đầy đủ với màu cạnh/nền hay không. Nếu không, độ tương phản yêu cầu tối thiểu sẽ giảm. Ngoài ra, đối với mỗi đối tượng màu, thiết lập 'khoảng cách' của nó với các màu khác. Đây là một ước tính sơ bộ về màu sắc tương tự như các màu khác trong hình ảnh.
Bước 6. sắp xếp dấu theo khoảng cách (khoảng cách ngắn nhất có nghĩa là tương tự nhất), với màu tương tự nhất xuất hiện ở trên cùng. Đặt màu thường xuyên nhất làm màu chính.
Bước 7. đi qua các màu còn lại và xác định màu nào tương phản nhất với màu chính. Sau đó, đặt màu phụ của bạn.
Caveat: Tôi chắc chắn phương pháp có thể được cải thiện, nhưng đó là điểm khởi đầu nhanh chóng. Ví dụ, bạn có thể xác định màu của các điểm ảnh ở phía trên bên phải hoặc trên cùng bên trái của hình ảnh (nơi các biểu tượng quay lại thường được đặt) và gợi ý một màu tương phản cho các biểu tượng ở đó.
Dưới đây là các mã:
-(NSDictionary *)coloursForImage:(UIImage *)image forEdge:(int)edge {
NSLog(@"start");
//1. set vars
float dimension = 20;
//2. resize image and grab raw data
//this part pulls the raw data from the image
CGImageRef imageRef = [image CGImage];
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
unsigned char *rawData = (unsigned char*) calloc(dimension * dimension * 4, sizeof(unsigned char));
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * dimension;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, dimension, dimension, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, dimension, dimension), imageRef);
CGContextRelease(context);
//3. create colour array
NSMutableArray * colours = [NSMutableArray new];
float x = 0, y = 0; //used to set coordinates
float eR = 0, eB = 0, eG = 0; //used for mean edge colour
for (int n = 0; n<(dimension*dimension); n++){
Colour * c = [Colour new]; //create colour
int i = (bytesPerRow * y) + x * bytesPerPixel; //pull index
c.r = rawData[i]; //set red
c.g = rawData[i + 1]; //set green
c.b = rawData[i + 2]; //set blue
[colours addObject:c]; //add colour
//add to edge if true
if ((edge == 0 && y == 0) || //top
(edge == 1 && x == 0) || //left
(edge == 2 && y == dimension-1) || //bottom
(edge == 3 && x == dimension-1)){ //right
eR+=c.r; eG+=c.g; eB+=c.b; //add the colours
}
//update pixel coordinate
x = (x == dimension - 1) ? 0 : x+1;
y = (x == 0) ? y+1 : y;
}
free(rawData);
//4. calculate edge colour
Colour * e = [Colour new];
e.r = eR/dimension;
e.g = eG/dimension;
e.b = eB/dimension;
//5. calculate the frequency of colour
NSMutableArray * accents = [NSMutableArray new]; //holds valid accents
float minContrast = 3.1; //play with this value
while (accents.count < 3) { //minimum number of accents
for (Colour * a in colours){
//NSLog(@"contrast value is %f", [self contrastValueFor:a andB:e]);
//5.1 ignore if it does not contrast with edge
if ([self contrastValueFor:a andB:e] < minContrast){ continue;}
//5.2 set distance (frequency)
for (Colour * b in colours){
a.d += [self colourDistance:a andB:b];
}
//5.3 add colour to accents
[accents addObject:a];
}
minContrast-=0.1f;
}
//6. sort colours by the most common
NSArray * sorted = [[NSArray arrayWithArray:accents] sortedArrayUsingDescriptors:@[[[NSSortDescriptor alloc] initWithKey:@"d" ascending:true]]];
//6.1 set primary colour (most common)
Colour * p = sorted[0];
//7. get most contrasting colour
float high = 0.0f; //the high
int index = 0; //the index
for (int n = 1; n < sorted.count; n++){
Colour * c = sorted[n];
float contrast = [self contrastValueFor:c andB:p];
//float sat = [self saturationValueFor:c andB:p];
if (contrast > high){
high = contrast;
index = n;
}
}
//7.1 set secondary colour (most contrasting)
Colour * s = sorted[index];
NSLog(@"er %i eg %i eb %i", e.r, e.g, e.b);
NSLog(@"pr %i pg %i pb %i", p.r, p.g, p.b);
NSLog(@"sr %i sg %i sb %i", s.r, s.g, s.b);
NSMutableDictionary * result = [NSMutableDictionary new];
[result setValue:[UIColor colorWithRed:e.r/255.0f green:e.g/255.0f blue:e.b/255.0f alpha:1.0f] forKey:@"background"];
[result setValue:[UIColor colorWithRed:p.r/255.0f green:p.g/255.0f blue:p.b/255.0f alpha:1.0f] forKey:@"primary"];
[result setValue:[UIColor colorWithRed:s.r/255.0f green:s.g/255.0f blue:s.b/255.0f alpha:1.0f] forKey:@"secondary"];
NSLog(@"end");
return result;
}
-(float)contrastValueFor:(Colour *)a andB:(Colour *)b {
float aL = 0.2126 * a.r + 0.7152 * a.g + 0.0722 * a.b;
float bL = 0.2126 * b.r + 0.7152 * b.g + 0.0722 * b.b;
return (aL>bL) ? (aL + 0.05)/(bL + 0.05) : (bL + 0.05)/(aL + 0.05);
}
-(float)saturationValueFor:(Colour *)a andB:(Colour *)b {
float min = MIN(a.r, MIN(a.g, a.b)); //grab min
float max = MAX(b.r, MAX(b.g, b.b)); //grab max
return (max - min)/max;
}
-(int)colourDistance:(Colour *)a andB:(Colour *)b {
return abs(a.r-b.r)+abs(a.g-b.g)+abs(a.b-b.b);
}
Đối tượng Màu sắc là một lớp tùy chỉnh đơn giản:
@interface Colour : NSObject
@property int r, g, b, d;
@end
Ý anh là gì? Hai màu được sử dụng nhiều nhất? – borrrden