2010-07-13 17 views
38

मैं अजगर का उपयोग कर छवि में सबसे प्रभावशाली रंग/स्वर खोजने का एक तरीका ढूंढ रहा हूं। या तो आरडीबी की औसत छाया या सबसे आम बात होगी। मैंने पाइथन इमेजिंग लाइब्रेरी को देखा है, और जो कुछ मैं अपने मैनुअल में ढूंढ रहा था उससे संबंधित कुछ भी नहीं मिला, और संक्षेप में वीटीके में भी।पायथन - एक छवि में प्रभावशाली/सबसे आम रंग खोजें

हालांकि मुझे एक PHP स्क्रिप्ट मिलती है जो मुझे चाहिए, here (डाउनलोड करने के लिए लॉगिन आवश्यक)। प्रमुख रंगों को बाहर लाने के लिए, स्क्रिप्ट छवि को 150 * 150 तक आकार देने लगती है। हालांकि, उसके बाद, मैं काफी हद तक खो गया हूँ। मैंने कुछ ऐसा लिखने पर विचार किया जो छवि को छोटे आकार में आकार देगा, फिर उसकी छवि के लिए हर दूसरे पिक्सेल की जांच करें, हालांकि मुझे लगता है कि यह बहुत अक्षम होगा (हालांकि इस विचार को लागू करना सी पाइथन मॉड्यूल एक विचार हो सकता है)।

हालांकि, इसके बाद भी, मैं अभी भी स्टंप हूं। तो मैं तुम्हारे पास आ गया, तो। एक छवि में प्रभावशाली रंग खोजने के लिए एक आसान, कुशल तरीका है।

+0

मैं मैं अनुमान लगाता हूं कि यह रेजलिंग एल्गोरिदम आपके लिए कुछ औसत औसत करने के लिए चित्र का आकार बदलता है। – Skurmedel

उत्तर

39

यहां कोड PIL और Scipy's cluster package का उपयोग कर रहा है।

सादगी के लिए मैंने फ़ाइल नाम को "image.jpg" के रूप में हार्डकोड किया है। छवि का आकार बदलना गति के लिए है: यदि आपको प्रतीक्षा नहीं है, तो आकार बदलें कॉल पर टिप्पणी करें। जब यह sample image of blue peppers पर चलता है तो आमतौर पर यह कहता है कि प्रमुख रंग # d8c865 है, जो लगभग दो मिर्च के निचले बाएं हिस्से में उज्ज्वल पीले रंग के क्षेत्र से मेल खाता है। मैं "आमतौर पर" कहता हूं क्योंकि clustering algorithm में इसका उपयोग यादृच्छिकता है। आप इसे बदलने के कई तरीके हैं, लेकिन आपके उद्देश्यों के लिए यह अच्छी तरह से अनुकूल हो सकता है। (यदि आप नियतात्मक परिणाम की जरूरत kmeans2() संस्करण के विकल्प देखें।)

import struct 
import Image 
import numpy as np 
import scipy 
import scipy.misc 
import scipy.cluster 

NUM_CLUSTERS = 5 

print 'reading image' 
im = Image.open('image.jpg') 
im = im.resize((150, 150))  # optional, to reduce time 
ar = np.asarray(im) 
shape = ar.shape 
ar = ar.reshape(scipy.product(shape[:2]), shape[2]).astype(float) 

print 'finding clusters' 
codes, dist = scipy.cluster.vq.kmeans(ar, NUM_CLUSTERS) 
print 'cluster centres:\n', codes 

vecs, dist = scipy.cluster.vq.vq(ar, codes)   # assign codes 
counts, bins = scipy.histogram(vecs, len(codes)) # count occurrences 

index_max = scipy.argmax(counts)     # find most frequent 
peak = codes[index_max] 
colour = ''.join(chr(int(c)) for c in peak).encode('hex') 
print 'most frequent is %s (#%s)' % (peak, colour) 

नोट: जब मैं समूहों की संख्या को बढ़ाने के लिए 5 से 10 या 15 को खोजने के लिए है, यह अक्सर दिया परिणाम है कि हरे थे या नीला इनपुट छवि को देखते हुए, वे भी उचित परिणाम हैं ... मैं यह नहीं बता सकता कि उस छवि में कौन सा रंग वास्तव में प्रभावशाली है, इसलिए मैं एल्गोरिदम को गलती नहीं करता!

इसके अलावा एक छोटे से बोनस: केवल एन सबसे लगातार रंग के साथ कम-आकार की छवि को बचाने:

# bonus: save image using only the N most common colours 
c = ar.copy() 
for i, code in enumerate(codes): 
    c[scipy.r_[scipy.where(vecs==i)],:] = code 
scipy.misc.imsave('clusters.png', c.reshape(*shape)) 
print 'saved clustered image' 
+1

वाह। एक दम बढ़िया। लगभग वही जो मैं खोज रहा था। मैंने झुकाव देखा, और महसूस किया कि जवाब कहीं कहीं था: पी आपके उत्तर के लिए धन्यवाद। –

+0

ग्रेट उत्तर। मेरे लिए काम किया हालांकि, मेरे पास एक छोटा सा सवाल था। इस मामले में मैं दूसरे सबसे लगातार रंग का उपयोग कैसे करूं कि काला सबसे अधिक बार होता है और मैं इसे अनदेखा करना चाहता हूं? – frakman1

+0

@ frakman1, argmax() केवल एक सुविधा समारोह है जो पहले देता है। आपको क्या करना होगा, गणना संख्या (मूल सूचकांक का ट्रैक रखने) को क्रमबद्ध करें, फिर पहले (या प्रभावी रूप से क्या तर्कसंगत है) की बजाय दूसरी (या दूसरी अंतिम) प्रविष्टि चुनें। –

10

पायथन इमेजिंग पुस्तकालय छवि वस्तुओं पर विधि getcolors है:

im.getcolors() => a list of (count, color) tuples or None

मुझे लगता है कि आप अभी भी है कि इससे पहले कि छवि का आकार बदलने के लिए प्रयास करें और देखें कि क्या वह किसी भी बेहतर प्रदर्शन करती है सकते हैं।

5

आप पीआईएल का उपयोग प्रत्येक आयाम में 2 के कारक द्वारा बार-बार छवि का आकार बदलने के लिए कर सकते हैं जब तक यह 1x1 तक नहीं पहुंच जाता। मुझे नहीं पता कि एल्गोरिदम पीआईएल बड़े कारकों से डाउनस्कलिंग के लिए क्या उपयोग करता है, इसलिए एक ही आकार में सीधे 1x1 पर जाकर जानकारी खो सकती है। यह सबसे कुशल नहीं हो सकता है, लेकिन यह आपको छवि का "औसत" रंग देगा।

3

, पीटर जवाब देने के लिए जोड़ने के लिए, यदि जनहित याचिका आप मोड "पी" के साथ एक छवि दे रहा है या बहुत अधिक मोड जो "आरजीबीए" नहीं है, तो आपको इसे आरजीबीए में बदलने के लिए अल्फा मास्क लागू करने की आवश्यकता है।आप के साथ बहुत आसानी से ऐसा कर सकते हैं:

if im.mode == 'P': 
    im.putalpha(0) 
1

Below is a c++ Qt based example to guess the predominant image color. You can use PyQt and translate the same to Python equivalent.

#include <Qt/QtGui> 
#include <Qt/QtCore> 
#include <QtGui/QApplication> 

int main(int argc, char** argv) 
{ 
    QApplication app(argc, argv); 
    QPixmap pixmap("logo.png"); 
    QImage image = pixmap.toImage(); 
    QRgb col; 
    QMap<QRgb,int> rgbcount; 
    QRgb greatest = 0; 

    int width = pixmap.width(); 
    int height = pixmap.height(); 

    int count = 0; 
    for (int i = 0; i < width; ++i) 
    { 
     for (int j = 0; j < height; ++j) 
     { 
      col = image.pixel(i, j); 
      if (rgbcount.contains(col)) { 
       rgbcount[col] = rgbcount[col] + 1; 
      } 
      else { 
       rgbcount[col] = 1; 
      } 

      if (rgbcount[col] > count) { 
       greatest = col; 
       count = rgbcount[col]; 
      } 

     } 
    } 
    qDebug() << count << greatest; 
    return app.exec(); 
} 
2

आप अभी भी एक जवाब के लिए देख रहे हैं, यहाँ क्या मेरे लिए काम किया, बहुत कुशल नहीं यद्यपि है:

from PIL import Image 

def compute_average_image_color(img): 
    width, height = img.size 

    r_total = 0 
    g_total = 0 
    b_total = 0 

    count = 0 
    for x in range(0, width): 
     for y in range(0, height): 
      r, g, b = img.getpixel((x,y)) 
      r_total += r 
      g_total += g 
      b_total += b 
      count += 1 

    return (r_total/count, g_total/count, b_total/count) 

img = Image.open('image.png') 
#img = img.resize((50,50)) # Small optimization 
average_color = compute_average_image_color(img) 
print(average_color) 
+0

पीएनजी के लिए, आपको इस तथ्य को संभालने के लिए थोड़ा सा बदलाव करना होगा कि img.getpixel आर, जी, बी, ए (तीन की बजाय चार मान) देता है। या यह मेरे लिए वैसे भी किया। – rossdavidh

+0

यह पिक्सल असमान रूप से वजन करता है। अंतिम पिक्सेल स्पर्श कुल मूल्य का आधा योगदान देता है। इससे पहले पिक्सेल उसमें से आधे योगदान देता है। वास्तव में केवल अंतिम 8 पिक्सल औसत को प्रभावित करेंगे, वास्तव में। –

+0

आप सही हैं - मूर्खतापूर्ण गलती। बस जवाब संपादित किया - अगर यह काम करता है तो मुझे बताएं। –

संबंधित मुद्दे