Python-이미지에서 주된 / 가장 일반적인 색상 찾기
파이썬을 사용하여 이미지에서 가장 지배적 인 색상 / 톤을 찾는 방법을 찾고 있습니다. 평균적인 음영 또는 가장 일반적인 RGB 중 하나가 가능합니다. 저는 Python Imaging 라이브러리를 살펴 보았지만 매뉴얼에서 찾고있는 내용과 VTK에 대한 간략한 정보를 찾을 수 없었습니다.
그러나 여기에서 필요한 작업을 수행하는 PHP 스크립트를 찾았습니다 (다운로드하려면 로그인해야 함). 스크립트는 이미지의 크기를 150 * 150으로 조정하여 주요 색상을 강조하는 것 같습니다. 그러나 그 후 나는 상당히 길을 잃었습니다. 나는 이것이 매우 비효율적이라고 생각하지만 이미지를 작은 크기로 조정 한 다음 다른 모든 픽셀을 확인하는 것을 고려했습니다 (이 아이디어를 C 파이썬 모듈로 구현하는 것이 아이디어 일 수 있음).
그러나 그 모든 후에도 여전히 난처합니다. 그래서 나는 당신에게로 향합니다. 이미지에서 주요 색상을 찾는 쉽고 효율적인 방법이 있습니까?
Pillow 와 Scipy의 클러스터 패키지 를 사용하는 코드는 다음과 같습니다 .
간단하게 파일 이름을 "image.jpg"로 하드 코딩했습니다. 이미지 크기 조정은 속도를위한 것입니다. 기다려도 괜찮다면 크기 조정 호출을 주석 처리하십시오. 이 푸른 고추 샘플 이미지를 실행 하면 일반적으로 주된 색상이 # d8c865라고 표시되며, 이는 대략 두 고추의 왼쪽 아래에있는 밝은 노란색 영역에 해당합니다. 사용 된 클러스터링 알고리즘 이 임의의 정도를 가지고 있기 때문에 "보통"이라고 말합니다 . 이를 변경할 수있는 방법에는 여러 가지가 있지만 목적에 따라 적합 할 수 있습니다. (결정적 결과가 필요한 경우 kmeans2 () 변형의 옵션을 확인하십시오.)
from __future__ import print_function
import binascii
import struct
from PIL 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 = binascii.hexlify(bytearray(int(c) for c in peak)).decode('ascii')
print('most frequent is %s (#%s)' % (peak, colour))
참고 : 클러스터 수를 5 개에서 10 개 또는 15 개로 확장하면 녹색 또는 푸르스름한 결과가 자주 나타납니다. 입력 이미지를 감안할 때 이것도 합리적인 결과입니다 ... 그 이미지에서 어떤 색상이 실제로 우세한지 알 수 없으므로 알고리즘에 결함이 없습니다!
또한 작은 보너스 : N 개의 가장 자주 사용되는 색상 만 사용하여 축소 된 이미지를 저장하십시오.
# bonus: save image using only the N most common colours
import imageio
c = ar.copy()
for i, code in enumerate(codes):
c[scipy.r_[scipy.where(vecs==i)],:] = code
imageio.imwrite('clusters.png', c.reshape(*shape).astype(np.uint8))
print('saved clustered image')
Python Imaging Library에는 Image 개체에 대한 getcolors 메서드가 있습니다.
im.getcolors () => (개수, 색상) 튜플 목록 또는 없음
그 전에 이미지 크기를 조정하고 성능이 더 좋은지 확인할 수 있다고 생각합니다.
여전히 답을 찾고 있다면 매우 효율적이지는 않지만 저에게 도움이 된 것은 다음과 같습니다.
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)
You could use PIL to repeatedly resize the image down by a factor of 2 in each dimension until it reaches 1x1. I don't know what algorithm PIL uses for downscaling by large factors, so going directly to 1x1 in a single resize might lose information. It might not be the most efficient, but it will give you the "average" color of the image.
Try Color-thief. It is based on PIL
and works awesome.
Installation
pip install colorthief
Usage
from colorthief import ColorThief
color_thief = ColorThief('/path/to/imagefile')
# get the dominant color
dominant_color = color_thief.get_color(quality=1)
It can also find color pallete
palette = color_thief.get_palette(color_count=6)
To add to Peter's answer, if PIL is giving you an image with mode "P" or pretty much any mode that isn't "RGBA", then you need to apply an alpha mask to convert it to RGBA. You can do that pretty easily with:
if im.mode == 'P':
im.putalpha(0)
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();
}
It's not necessary to use k-means to find the dominant color as Peter suggests. This overcomplicates a simple problem. You're also restricting yourself by the amount of clusters you select so basically you need an idea of what you're looking at.
As you mentioned and as suggested by zvone, a quick solution to find the most common/dominant color is by using the Pillow library. We just need to sort the pixels by their count number.
from PIL import Image
def dominant_color(filename):
#Resizing parameters
width, height = 150,150
image = Image.open(filename)
image = image.resize((width, height),resample = 0)
#Get colors from image object
pixels = image.getcolors(width * height)
#Sort them by count number(first element of tuple)
sorted_pixels = sorted(pixels, key=lambda t: t[0])
#Get the most frequent color
dominant_color = sorted_pixels[-1][1]
return dominant_color
The only problem is that the method getcolors()
returns None when the amount of colors is more than 256. You can deal with it by resizing the original image.
In all, it might not be the most precise solution but it gets the job done.
ReferenceURL : https://stackoverflow.com/questions/3241929/python-find-dominant-most-common-color-in-an-image
'programing' 카테고리의 다른 글
동일한 로거에 대해 서로 다른 로그 수준을 서로 다른 파일에 기록하도록 log4j를 구성하는 방법 (0) | 2021.01.14 |
---|---|
실제 테이블 대. (0) | 2021.01.14 |
연결 문자열에 앰퍼샌드를 포함하는 방법은 무엇입니까? (0) | 2021.01.14 |
명부 (0) | 2021.01.14 |
vim에서 X 개의 문자를 어떻게 잡아 당기나요? (0) | 2021.01.14 |