2013-04-12 33 views
5

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

+0

Ý anh là gì? Hai màu được sử dụng nhiều nhất? – borrrden

Trả lời

3

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.

+0

Tuyệt vời! Chính xác những gì tôi đang tìm kiếm. Cảm ơn –

+0

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

7

enter image description here

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 
Các vấn đề liên quan