Python 查找Numpy中排名前10(n)的RGB颜色

Python 查找Numpy中排名前10(n)的RGB颜色,python,numpy,image-processing,colors,numpy-slicing,Python,Numpy,Image Processing,Colors,Numpy Slicing,我有一个吃几秒钟的函数。函数应该返回给定图像中的前(n)种颜色。必须对返回进行排序,以便我可以使用第一、第二、第三个最上面颜色的rgb值 在第一方面,我有一个PIL.Image对象,我在x,y坐标上循环,并在defaultdict中计算它。我已经用一个Numpy数组替换了我项目中的PIL对象,这给了我很大的提升,但我不知道在这种情况下如何替换defaultdict 我当前的解决方案: import numpy as np from scipy import misc # for example

我有一个吃几秒钟的函数。函数应该返回给定图像中的前(n)种颜色。必须对返回进行排序,以便我可以使用第一、第二、第三个最上面颜色的rgb值

在第一方面,我有一个PIL.Image对象,我在x,y坐标上循环,并在defaultdict中计算它。我已经用一个Numpy数组替换了我项目中的PIL对象,这给了我很大的提升,但我不知道在这种情况下如何替换defaultdict

我当前的解决方案:

import numpy as np
from scipy import misc  # for example Image
from collections import defaultdict

def count_colors(img, n):
    img = img.reshape(-1, img.shape[-1])
    color = defaultdict(int)

    for pixel in img:
        rgb = (pixel[0], pixel[1], pixel[2])
        color[rgb] += 1

    sorted_color = sorted(color.items(), key=lambda k_v: k_v[1], reverse=True)
    sorted_color = sorted_color[:n]

    return sorted_color

img = misc.face()  # example Numpy Image array
top_colors = count_colors(img, n=5)

display(top_colors)
[((9, 9, 9), 1062),
 ((10, 10, 10), 700),
 ((8, 8, 8), 668),
 ((9, 7, 8), 586),
 ((9, 7, 10), 579)]
电流输出:

import numpy as np
from scipy import misc  # for example Image
from collections import defaultdict

def count_colors(img, n):
    img = img.reshape(-1, img.shape[-1])
    color = defaultdict(int)

    for pixel in img:
        rgb = (pixel[0], pixel[1], pixel[2])
        color[rgb] += 1

    sorted_color = sorted(color.items(), key=lambda k_v: k_v[1], reverse=True)
    sorted_color = sorted_color[:n]

    return sorted_color

img = misc.face()  # example Numpy Image array
top_colors = count_colors(img, n=5)

display(top_colors)
[((9, 9, 9), 1062),
 ((10, 10, 10), 700),
 ((8, 8, 8), 668),
 ((9, 7, 8), 586),
 ((9, 7, 10), 579)]
有没有真正的简单方法来解决这个问题?

方法#1

我们可以使用来获得每种唯一颜色的计数,然后为紧凑的矢量化解决方案获取其中的前N种颜色的计数-

def topN_colors(img, N):
    unqc,C = np.unique(img.reshape(-1,img.shape[-1]), axis=0, return_counts=True)
    topNidx = np.argpartition(C,-N)[-N:]
    return unqc[topNidx], C[topNidx]
# https://stackoverflow.com/a/57236217/ @tstanisl
def scalarize(x):
    # compute x[...,2]*65536+x[...,1]*256+x[...,0] in efficient way
    y = x[...,2].astype('u4')
    y <<= 8
    y +=x[...,1]
    y <<= 8
    y += x[...,0]
    return y

def topN_colors_v2(img, N):
    img2D = scalarize(img)
    unq,idx,C = np.unique(img2D, return_index=True, return_counts=True)
    topNidx = np.argpartition(C,-N)[-N:]
    return img.reshape(-1,img.shape[-1])[idx[topNidx]], C[topNidx]
方法#2

另一个主要基于24位整数2D缩减,以获得更高效的解决方案-

def topN_colors(img, N):
    unqc,C = np.unique(img.reshape(-1,img.shape[-1]), axis=0, return_counts=True)
    topNidx = np.argpartition(C,-N)[-N:]
    return unqc[topNidx], C[topNidx]
# https://stackoverflow.com/a/57236217/ @tstanisl
def scalarize(x):
    # compute x[...,2]*65536+x[...,1]*256+x[...,0] in efficient way
    y = x[...,2].astype('u4')
    y <<= 8
    y +=x[...,1]
    y <<= 8
    y += x[...,0]
    return y

def topN_colors_v2(img, N):
    img2D = scalarize(img)
    unq,idx,C = np.unique(img2D, return_index=True, return_counts=True)
    topNidx = np.argpartition(C,-N)[-N:]
    return img.reshape(-1,img.shape[-1])[idx[topNidx]], C[topNidx]

是的,它是有效的,你的第二种方法非常快。我真的需要按降序排列。您的范围(-N,0)是关键。我修改了返回到:return img.reformate(-1,img.shape[-1])[idx[topNidx][::-1],C[topNidx][::-1]tbh,我没有得到scalarize函数。你永远不会停止学习:)