Python获取RGB和HSV值并框出对应颜色

获取RGB值

使用PIL工具

1
2
3
4
5
6
7
8
9
from PIL import Image

# 打开图像文件
image = Image.open('../image/031301.png')

# 获取指定位置的像素颜色
rgb = image.getpixel((100, 100))

print("RGB值为:", rgb)

使用OpenCV

1
2
3
4
5
6
7
8
9
import cv2

# 读取图像
image = cv2.imread('../image/031301.png')

# 获取指定位置的像素颜色
(b, g, r) = image[100, 100]

print("RGB值为: ({}, {}, {})".format(r, g, b))

转换为hsv值并计算上下限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 导入所需的库
import numpy as np
import cv2
# 为颜色定义一个numpy.ndarray
green = np.uint8([[[0, 255, 0]]]) # 在此插入要转换为HSV的BGR值
# 将颜色转换为HSV
hsvGreen = cv2.cvtColor(green, cv2.COLOR_BGR2HSV)
# 显示颜色的值
print("BGR of Green:", green)
print("HSV of Green:", hsvGreen)
# 计算下限和上限
lowerLimit = hsvGreen[0][0][0] -10, 100, 100
upperLimit = hsvGreen[0][0][0] + 10, 255, 255
# 显示下限和上限
print("Lower Limit:", lowerLimit)
print("Upper Limit", upperLimit)

获取图片某一点hsv值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import cv2

def mouse_callback(event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONDOWN: # 鼠标左击按下
# 获取鼠标按下位置的hsv值
h, s, v = hsv[y, x]
print(f'H:{h}, S:{s}, V:{v}')

img = cv2.imread(r'xxx.png') # 加载图片
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 将图片转为hsv

img_name = 'image'
cv2.namedWindow(img_name)
cv2.setMouseCallback(img_name, mouse_callback) # 设置鼠标回调

cv2.imshow(img_name, img) # 展示图片
cv2.waitKey(0)

click

识别并框出同种颜色的图形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import cv2
import numpy as np


def color(lower, upper, name):
Img = cv2.imread('image/origin/all.png') # 读入一幅图像

kernel_3 = np.ones((3, 3), np.uint8) # 3x3的卷积核

if Img is not None: # 判断图片是否读入
HSV = cv2.cvtColor(Img, cv2.COLOR_BGR2HSV) # 把BGR图像转换为HSV格式

# mask是把HSV图片中在颜色范围内的区域变成白色,其他区域变成黑色
if name == 'red':
mask = cv2.inRange(HSV, lower[:3], upper[:3])
mask = mask + cv2.inRange(HSV, lower[3:], upper[3:])
else:
mask = cv2.inRange(HSV, lower, upper)

# 下面四行是用卷积进行滤波
# erode()函数可以对输入图像用特定结构元素进行腐蚀操作,该结构元素确定腐蚀操作过程中的邻域的形状,
# 各点像素值将被替换为对应邻域上的最小值:
erosion = cv2.erode(mask, kernel_3, iterations=1)
erosion = cv2.erode(erosion, kernel_3, iterations=1)
# dilate()函数可以对输入图像用特定结构元素进行膨胀操作,该结构元素确定膨胀操作过程中的邻域的形状,
# 各点像素值将被替换为对应邻域上的最大值:
dilation = cv2.dilate(erosion, kernel_3, iterations=1)
dilation = cv2.dilate(dilation, kernel_3, iterations=1)

# target是把原图中的非目标颜色区域去掉剩下的图像
cv2.bitwise_and(Img, Img, mask=dilation)

# 将滤波后的图像变成二值图像放在binary中
ret, binary = cv2.threshold(dilation, 127, 255, cv2.THRESH_BINARY)

# 在binary中发现轮廓,轮廓按照面积从小到大排列
contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for index, contour in enumerate(contours): # 遍历所有的轮廓
x, y, w, h = cv2.boundingRect(contour) # 将轮廓分解为识别对象的左上角坐标和宽、高
# 在图像上画上矩形(图片、左上角坐标、右下角坐标、颜色、线条宽度)
cv2.rectangle(Img, (x, y), (x + w, y + h), (0, 255,), 3)
# 给识别对象写上标号
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(Img, name + str(index+1), (x - 10, y + 10), font, 1, (0, 0, 255), 2) # 加减10是调整字符位置

print(name, '方块的数量是', len(contours), '个') # 终端输出目标数量

# cv2.imshow('target', target)
# cv2.imshow('Mask', mask)
# cv2.imshow("prod", dilation)
cv2.namedWindow('Img', 0)
cv2.imshow('Img', Img)
cv2.imwrite('./image/' + name + '.png', Img) # 将画上矩形的图形保存到当前目录

while True:
key = cv2.waitKey(10) & 0xFF
if key == 27 or cv2.getWindowProperty('Img', cv2.WND_PROP_VISIBLE) < 1.0:
break


if __name__ == '__main__':
# 下面两个值是要识别的颜色范围
# 要识别哪个颜色就取消以下哪部分的注释:color()
lower_yellow = np.array([20, 20, 20]) # 黄色的下限
upper_yellow = np.array([30, 255, 255]) # 黄色上限
# color(lower_yellow, upper_yellow, 'yellow')

# 红色需要特殊处理
lower_red = np.array([0, 43, 46, 156, 43, 46]) # 红色阈值下界
higher_red = np.array([10, 255, 255, 180, 255, 255]) # 红色阈值上界
# color(lower_red, higher_red, 'red')

lower_green = np.array([35, 110, 106]) # 绿色阈值下界
higher_green = np.array([77, 255, 255]) # 绿色阈值上界
# color(lower_green, higher_green, 'green')

lower_blue = np.array([78, 43, 46]) # 蓝色阈值下界
upper_blue = np.array([110, 255, 255]) # 蓝色阈值下界
color(lower_blue, upper_blue, 'blue')

same.png

识别并框出多种颜色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import cv2
import numpy as np


def bitwise_or_fun(masks):
if len(masks) <= 1:
return
mask = cv2.bitwise_or(masks[0], masks[1])

for i in range(2, len(masks)):
mask = cv2.bitwise_or(mask, masks[i])


def color(img):
colors, lower_highers = get_params()
frame = cv2.imread(img) # 读入一幅图像
font = cv2.FONT_HERSHEY_SIMPLEX
img_hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

masks = []
for index, lower_higher in enumerate(lower_highers):
lower_color = lower_higher[0]
higher_color = lower_higher[1]

if colors[index] == 'red':
mask = cv2.inRange(img_hsv, lower_color[:3], higher_color[:3]) # 可以认为是过滤出红色部分,获得红色的掩膜
mask = mask + cv2.inRange(img_hsv, lower_color[3:], higher_color[3:]) # 可以认为是过滤出红色部分,获得红色的掩膜
else:
mask = cv2.inRange(img_hsv, lower_color, higher_color)
mask = cv2.medianBlur(mask, 7) # 中值滤波
masks.append(mask)

bitwise_or_fun(masks)
cntss = []
for mask in masks:
cnts, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # 轮廓检测
cntss.append(cnts)

for (colorname, cnts) in zip(colors, cntss):
for index, cnt in enumerate(cnts):
(x, y, w, h) = cv2.boundingRect(cnt) # 该函数返回矩阵四个点
# cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 0), 2) # 将检测到的颜色框起来
cv2.putText(frame, colorname + str(index + 1), (x, y - 5), font, 0.7, (0, 0, 0), 2)
cv2.drawContours(frame, cnts, -1, (0, 0, 0), 3)
# cv2.namedWindow('frame', 0)
cv2.imshow('frame', frame)
cv2.imwrite('image/frame.png', frame) # 将画上矩形的图形保存到当前目录

while True:
key = cv2.waitKey(10) & 0xFF
if key == 27 or cv2.getWindowProperty('frame', cv2.WND_PROP_VISIBLE) < 1.0:
break


def get_params():
# 下面两个值是要识别的颜色范围
lower_yellow = np.array([20, 20, 20]) # 黄色的下限
upper_yellow = np.array([30, 255, 255]) # 黄色上限

# 红色需要特殊处理
lower_red = np.array([0, 43, 46, 156, 43, 46]) # 红色阈值下界
higher_red = np.array([10, 255, 255, 180, 255, 255]) # 红色阈值上界

lower_green = np.array([35, 110, 106]) # 绿色阈值下界
higher_green = np.array([77, 255, 255]) # 绿色阈值上界

lower_blue = np.array([78, 43, 46]) # 蓝色阈值下界
upper_blue = np.array([110, 255, 255]) # 蓝色阈值下界

# 下面两个值是要识别的颜色范围
lower_purple = np.array([125, 43, 46]) # 紫色的下限
upper_purple = np.array([155, 255, 255]) # 紫色上限

params = []
colors = []
params.append([lower_red, higher_red]);colors.append('red') # 不框出哪种颜色就注释掉哪一条
params.append([lower_yellow, upper_yellow]);colors.append('yellow')
params.append([lower_green, higher_green]);colors.append('green')
params.append([lower_blue, upper_blue]);colors.append('blue')
params.append([lower_purple, upper_purple]);colors.append('purple')

return colors, params


if __name__ == '__main__':
color('./image/origin/all.png')

difference

参考教程