用python写识别图片主要颜色的程序

Python015

用python写识别图片主要颜色的程序,第1张

# -*- coding: utf-8 -*-

import colorsys

 

def get_dominant_color(image):

    

    #颜色模式转换,以便输出rgb颜色值

    image = image.convert('RGBA')

    

    #生成缩略图,减少计算量,减小cpu压力

    image.thumbnail((200, 200))

    

    max_score = None

    dominant_color = None

    

    for count, (r, g, b, a) in image.getcolors(image.size[0] * image.size[1]):

        # 跳过纯黑色

        if a == 0:

            continue

        

        saturation = colorsys.rgb_to_hsv(r / 255.0, g / 255.0, b / 255.0)[1]

       

        y = min(abs(r * 2104 + g * 4130 + b * 802 + 4096 + 131072) >> 13, 235)

       

        y = (y - 16.0) / (235 - 16)

        

        # 忽略高亮色

        if y > 0.9:

            continue

        

        # Calculate the score, preferring highly saturated colors.

        # Add 0.1 to the saturation so we don't completely ignore grayscale

        # colors by multiplying the count by zero, but still give them a low

        # weight.

        score = (saturation + 0.1) * count

        

        if score > max_score:

            max_score = score

            dominant_color = (r, g, b)

    

    return dominant_color

    

if __name__=="__main__":

    from PIL import Image

    import os

    

    path = r'.\\pics\\'

    fp = open('file_color.txt','w')

    for filename in os.listdir(path):

        print path+filename

        try:

            color =  get_dominant_color(Image.open(path+filename))

            fp.write('The color of '+filename+' is '+str(color)+'\n')

        except:

            print "This file format is not support"

    fp.close()

pics文件夹和python程序在一个目录下,产生的文件名file_color.txt也在这个目录下。

看看能否帮到你

难得被人求助一次, 这个必须回答一下. 不过你的需求确实没有写得太清楚. 根据k值算法出来的是主要颜色有三个, 所以我把三个颜色都打在记事本里了. 如果和你的需求有误, 请自行解决吧.

另外这里需要用到numpy的库, 希望你装了, 如果没装, 这个直接安装也比较麻烦, 可以看一下portablepython的绿色版。

代码如下:

# -*- coding: utf-8 -*-

import Image

import random

import numpy

class Cluster(object):

    def __init__(self):

        self.pixels = []

        self.centroid = None

    def addPoint(self, pixel):

        self.pixels.append(pixel)

    def setNewCentroid(self):

        R = [colour[0] for colour in self.pixels]

        G = [colour[1] for colour in self.pixels]

        B = [colour[2] for colour in self.pixels]

        R = sum(R) / len(R)

        G = sum(G) / len(G)

        B = sum(B) / len(B)

        self.centroid = (R, G, B)

        self.pixels = []

        return self.centroid

class Kmeans(object):

    def __init__(self, k=3, max_iterations=5, min_distance=5.0, size=200):

        self.k = k

        self.max_iterations = max_iterations

        self.min_distance = min_distance

        self.size = (size, size)

    def run(self, image):

        self.image = image

        self.image.thumbnail(self.size)

        self.pixels = numpy.array(image.getdata(), dtype=numpy.uint8)

        self.clusters = [None for i in range(self.k)]

        self.oldClusters = None

        randomPixels = random.sample(self.pixels, self.k)

        for idx in range(self.k):

            self.clusters[idx] = Cluster()

            self.clusters[idx].centroid = randomPixels[idx]

        iterations = 0

        while self.shouldExit(iterations) is False:

            self.oldClusters = [cluster.centroid for cluster in self.clusters]

            print iterations

            for pixel in self.pixels:

                self.assignClusters(pixel)

            for cluster in self.clusters:

                cluster.setNewCentroid()

            iterations += 1

        return [cluster.centroid for cluster in self.clusters]

    def assignClusters(self, pixel):

        shortest = float('Inf')

        for cluster in self.clusters:

            distance = self.calcDistance(cluster.centroid, pixel)

            if distance < shortest:

                shortest = distance

                nearest = cluster

        nearest.addPoint(pixel)

    def calcDistance(self, a, b):

        result = numpy.sqrt(sum((a - b) ** 2))

        return result

    def shouldExit(self, iterations):

        if self.oldClusters is None:

            return False

        for idx in range(self.k):

            dist = self.calcDistance(

                numpy.array(self.clusters[idx].centroid),

                numpy.array(self.oldClusters[idx])

            )

            if dist < self.min_distance:

                return True

        if iterations <= self.max_iterations:

            return False

        return True

    # ############################################

    # The remaining methods are used for debugging

    def showImage(self):

        self.image.show()

    def showCentroidColours(self):

        for cluster in self.clusters:

            image = Image.new("RGB", (200, 200), cluster.centroid)

            image.show()

    def showClustering(self):

        localPixels = [None] * len(self.image.getdata())

        for idx, pixel in enumerate(self.pixels):

                shortest = float('Inf')

                for cluster in self.clusters:

                    distance = self.calcDistance(

                        cluster.centroid,

                        pixel

                    )

                    if distance < shortest:

                        shortest = distance

                        nearest = cluster

                localPixels[idx] = nearest.centroid

        w, h = self.image.size

        localPixels = numpy.asarray(localPixels)\

            .astype('uint8')\

            .reshape((h, w, 3))

        colourMap = Image.fromarray(localPixels)

        colourMap.show()

    

if __name__=="__main__":

    from PIL import Image

    import os

    

    k_image=Kmeans()

    path = r'.\\pics\\'

    fp = open('file_color.txt','w')

    for filename in os.listdir(path):

        print path+filename

        try:

            color = k_image.run(Image.open(path+filename))

            fp.write('The color of '+filename+' is '+str(color)+'\n')

        except:

            print "This file format is not support"

    fp.close()