Python 如何在固定大小的图像中找到主要对象的颜色

Python 如何在固定大小的图像中找到主要对象的颜色,python,opencv,machine-learning,Python,Opencv,Machine Learning,我的目标是找到帧/图像中主要对象的颜色。在我的例子中,图像总是同一类型的。例如,森林中的新闻记者(人类)或畜牧场中的新闻记者。新闻记者的位置也是一样的。找出主要对象(新闻记者)的主导颜色的简单解决方案是什么 欢迎任何帮助。谢谢 添加编辑代码 import cv2 from collections import namedtuple from math import sqrt import random import webcolors try: import Image except Im

我的目标是找到帧/图像中主要对象的颜色。在我的例子中,图像总是同一类型的。例如,森林中的新闻记者(人类)或畜牧场中的新闻记者。新闻记者的位置也是一样的。找出主要对象(新闻记者)的主导颜色的简单解决方案是什么

欢迎任何帮助。谢谢

添加编辑代码

import cv2
from collections import namedtuple
from math import sqrt
import random
import webcolors


try:
 import Image
except ImportError:
 from PIL import Image

Point = namedtuple('Point', ('coords', 'n', 'ct'))
Cluster = namedtuple('Cluster', ('points', 'center', 'n'))

def get_points(img):
 points = []
 w, h = img.size
 for count, color in img.getcolors(w * h):
    points.append(Point(color, 3, count))
 return points

 rtoh = lambda rgb: '#%s' % ''.join(('%02x' % p for p in rgb))

def colorz(filename, n=3):
 img = Image.open(filename)
 img.thumbnail((200, 200))
 w, h = img.size

 points = get_points(img)
 clusters = kmeans(points, n, 1)
 rgbs = [map(int, c.center.coords) for c in clusters]
 return map(rtoh, rgbs)

def euclidean(p1, p2):
  return sqrt(sum([
  (p1.coords[i] - p2.coords[i]) ** 2 for i in range(p1.n)
 ]))

 def calculate_center(points, n):
  vals = [0.0 for i in range(n)]
  plen = 0
  for p in points:
    plen += p.ct
    for i in range(n):
        vals[i] += (p.coords[i] * p.ct)
   return Point([(v / plen) for v in vals], n, 1)

def kmeans(points, k, min_diff):
 clusters = [Cluster([p], p, p.n) for p in random.sample(points, k)]

 while 1:
   plists = [[] for i in range(k)]

   for p in points:
        smallest_distance = float('Inf')
        for i in range(k):
            distance = euclidean(p, clusters[i].center)
            if distance < smallest_distance:
                smallest_distance = distance
                idx = i
        plists[idx].append(p)

    diff = 0
    for i in range(k):
        old = clusters[i]
        center = calculate_center(plists[i], old.n)
        new = Cluster(plists[i], center, old.n)
        clusters[i] = new
        diff = max(diff, euclidean(old.center, new.center))

    if diff < min_diff:
        break

 return clusters

def main():

 img = cv2.imread('d:/Emmanu/project-data/b1.jpg')
 res=cv2.resize(img,(400,300))
 crop_img = res[100:200, 150:250]
 cv2.imwrite("d:/Emmanu/project-data/color-test.jpg", crop_img)
 g= colorz('d:/Emmanu/project-data/color-test.jpg',1)
 k=g[0]
 print k
 f=webcolors.hex_to_rgb(k)
 print webcolors.rgb_to_name(f, spec='css3')

if __name__ == '__main__':main()
导入cv2
从集合导入namedtuple
从数学导入sqrt
随机输入
导入网络颜色
尝试:
导入图像
除恐怖外:
从PIL导入图像
Point=namedtuple('Point',('coords','n','ct'))
Cluster=namedtuple('Cluster',('points','center','n'))
def获取积分(img):
点数=[]
w、 h=img.size
对于计数,img.getcolors中的颜色(w*h):
点。追加(点(颜色,3,计数))
返回点
rtoh=lambda rgb:“#%s”%”。联接(“%02x”%p表示rgb中的p))
def colorz(文件名,n=3):
img=Image.open(文件名)
图像缩略图((200200))
w、 h=img.size
积分=获取积分(img)
集群=kmeans(点,n,1)
rgbs=[集群中c的映射(int,c.center.coords)]
返回映射(rtoh、rgbs)
def欧几里德(p1,p2):
返回sqrt(总和([
(p1.coords[i]-p2.coords[i])**2表示范围内的i(p1.n)
]))
def计算中心(点,n):
VAL=[0.0,适用于范围(n)内的i]
plen=0
对于p in点:
plen+=p.ct
对于范围(n)中的i:
VAL[i]+=(p.coords[i]*p.ct)
返回点([(v/plen)表示VAL中的v],n,1)
def kmeans(点、k、最小差值):
集群=[集群([p],p,p.n)表示随机样本中的p。样本(点,k)]
而1:
plists=[]对于范围(k)内的i
对于p in点:
最小距离=浮动('Inf')
对于范围(k)内的i:
距离=欧几里德(p,簇[i]。中心)
如果距离<最小距离:
最小距离=距离
idx=i
plists[idx].append(p)
差异=0
对于范围(k)内的i:
old=簇[i]
中心=计算中心(plists[i],old.n)
新=簇(plists[i],中心,旧的.n)
簇[i]=新
diff=max(diff,欧几里德(旧.中心,新.中心))
如果差异<最小差异:
打破
返回簇
def main():
img=cv2.imread('d:/Emmanu/project data/b1.jpg'))
res=cv2.调整大小(img,(400300))
作物图像=分辨率[100:200,150:250]
imwrite(“d:/Emmanu/project data/color test.jpg”,crop\u img)
g=colorz('d:/Emmanu/project data/color test.jpg',1)
k=g[0]
打印k
f=网络颜色。十六进制到rgb(k)
将webcolors.rgb_打印到_名称(f,spec='css3')
如果uuuu name_uuuuuu=='uuuuuu main:main()

问题是,如果您选择整个图像的颜色,则返回整个图像中的主颜色,而不是主对象

,在大多数情况下,你会得到错误的答案,因为背景更多。如果你的图像大小是固定的,并且你确定对象的位置,最简单的解决方案是在你期望对象的位置裁剪图像。在大多数情况下,它会起作用

为了收成

import cv2
img = cv2.imread("'d:/Emmanu/project-data/b1.jpg'")
crop_img = img[200:400, 100:300] # Crop from x, y, w, h -> 100, 200, 300, 400
# NOTE: its img[y: y + h, x: x + w] and *not* img[x: x + w, y: y + h]
cv2.imshow("cropped", crop_img)
cv2.waitKey(0)

现在将这个裁剪图像作为代码的输入。在大多数情况下,它会给出正确的解决方案。没有比这更简单的了。我认为这会有所帮助。

@tfv我已经编辑过。但是这个代码给我的是整个图像的主要颜色,而不是对象的颜色。如果新闻记者穿着红色衣服,他在森林中,它会给出绿色(十六进制).尽可能正式地定义你的问题。术语“主要对象”和“主要颜色”的定义比较松散。假设您的“主要对象”是前台,您可以使用opencv,然后在前台应用与您类似的代码。