用python提取图片主要颜色_在Python中从图像中提取特定颜色范围的简单方法?

I'm trying to extract a specific color from an image within a defined RGB range using the cv2 module. In the example below I am trying to isolate the fire from the exhaust of the space shuttle between yellow and white RGB values and then print out the percentage of RGB values within that range compared to the rest of the image.

Here is my minimal working example:

import cv2

import numpy as np

from matplotlib import pyplot as plt

import imageio

img = imageio.imread(r"shuttle.jpg")

plt.imshow(img)

This is the output image. Its from wikipedia.

img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

color1 = (255,255,0) #yellow

color2 = (255,255,255) #white

boundaries = [([color1[0], color1[1], color1[2]], [color2[0], color2[1], color2[2]])]

for (lower, upper) in boundaries:

lower = np.array(lower, dtype=np.uint8)

upper = np.array(upper, dtype=np.uint8)

mask = cv2.inRange(img, lower, upper)

output = cv2.bitwise_and(img, img, mask=mask)

ratio = cv2.countNonZero(mask)/(img.size/3)

print('pixel percentage:', np.round(ratio*100, 2))

plt.imshow(mask)

However this does not seem to work because I get 0% of pixels between the yellow and white values. I'm not really sure where I'm going wrong:

[([255, 255, 0], [255, 255, 255])]

pixel percentage: 0.0

And the output graph appears to be blank with a blue/purple image:

Note I haven't used cv2's builtin image viewers such as cv2.imshow(), cv2.waitKey() and cv2.destroyAllWindows() because calling them kept crashing my IDE (Spyder 3.3.1) on Windows 8.1. Not sure if this is why the image is appearing blue/purple?

Also when I just try to output the original image, it appears in a strange inverted color format:

plt.imshow(img)

Anyway, I have tried following a similar method to detect a specific color range previously described here however that particular method gave me problems during compilation and has frozen and crashed my computer several times, when I try to implement something like this:

imask = mask>0

exhaust_color = np.zeros_like(img, np.uint8)

green[imask] = img[exhaust_color]

I guess what I'm tried to achieve here is something like the image below where only the colors between yellow and white are displayed, and then print out the percentage of pixels consisting of these colors. For the image below I just filtered out all colors below RGB (255, 255, 0) using a basic image processing software.

Is there a way to achieve this using the code I have already written or similar?

EDIT 1: Followed the advice below to convert to HSV color space first. However it still doesn't work and the yellow to white pixel percentage is still 0%. Output graphs are still the same and showing all black or purple. Also I managed to get cv2.imshow() working by passing 1 to cs2.waitKey(1). (Doesn't work with 0 for some reason.)

#CONVERT TO HSV COLORS

hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

color1 = np.uint8([[[0, 255, 255 ]]]) #yellow

color2 = np.uint8([[[255, 255, 255]]]) #white

hsv_color1 = cv2.cvtColor(color1,cv2.COLOR_BGR2HSV)

hsv_color2 = cv2.cvtColor(color2,cv2.COLOR_BGR2HSV)

print(hsv_color1)

print(hsv_color2)

#Define threshold color range to filter

mask = cv2.inRange(hsv_img, hsv_color1, hsv_color2)

# Bitwise-AND mask and original image

res = cv2.bitwise_and(hsv_img, hsv_img, mask=mask)

ratio = cv2.countNonZero(mask)/(hsv_img.size/3)

print('pixel percentage:', np.round(ratio*100, 2))

#plt.imshow(mask)

cv2.imshow('mask',res)

cv2.waitKey(1)

Output

[[[ 30 255 255]]]

[[[ 0 0 255]]]

pixel percentage: 0.0

解决方案

It was a pretty simple issue; you gave a larger color before a smaller one to cv2.inRange, so there was no valid intersection! Here's some working code that shows the output. This should be easy to adapt into your own script.

import cv2

import numpy as np

import matplotlib.pyplot as plt

img = cv2.imread('shuttle.jpg') # you can read in images with opencv

img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

hsv_color1 = np.asarray([0, 0, 255]) # white!

hsv_color2 = np.asarray([30, 255, 255]) # yellow! note the order

mask = cv2.inRange(img_hsv, hsv_color1, hsv_color2)

plt.imshow(mask, cmap='gray') # this colormap will display in black / white

plt.show()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值