最近工作又来新活了,船舶颜色检测。开始接到这个活还是有点懵,后面慢慢的感觉来了!!!
因为本项目涉及到颜色判断与分类,笔者一开始就想到的就是每种颜色的范围划分是什么,刚开始想的是否能够依据RGB值来划分颜色,很遗憾没找到各类颜色的RGB分割阈值,后来找到了关于HSV颜色模型的颜色分量范围资料。
OpenCV中HSV颜色模型及颜色分量范围
这给项目的颜色划分提供了依据。
思路:由于项目已训练好的模型可以对船头进行定位截图,本文就默认对所给图片进行颜色判断。
步骤:
1.设定颜色的HSV的上下界;
2. 找出图片中属于设定颜色的区域;
3. 计算各个颜色区域的量化面积;
4. 通过颜色最大面积来判别所属颜色;
# -*- coding:utf-8 -*-
# @Time : 2021/2/4 17:54
# @Author : JulyLi
# @File : 颜色总面积判断颜色.py
# @Software: PyCharm
import numpy as np
import cv2
import os
font = cv2.FONT_HERSHEY_SIMPLEX
lower_red = np.array([156, 43, 46]) # 红色阈值下界
higher_red = np.array([180, 255, 255]) # 红色阈值上界
lower_green = np.array([31, 43, 46]) # 绿色阈值下界
higher_green = np.array([77, 255, 255]) # 绿色阈值上界
lower_yellow = np.array([11, 43, 46]) # 黄色阈值下界
higher_yellow = np.array([30, 255, 255]) # 黄色阈值上界
lower_blue = np.array([78, 43, 46])
higher_blue = np.array([124, 255, 255]) # 蓝色
lower_gray = np.array([0, 0, 46])
higher_gray = np.array([180, 43, 220]) # 灰色
lower_black = np.array([0, 0, 0])
higher_black = np.array([180, 255, 46]) # 黑色
lower_white = np.array([0, 0, 221])
higher_white = np.array([180, 30, 225]) # 白色
lower_purple = np.array([125, 43, 46])
higher_purple = np.array([155, 255, 225]) # 紫色
# frame = cv2.imread("shiphead/3.jpg")
def color_detection(img):
red_temp = [0]
green_temp = [0]
yellow_temp = [0]
blue_temp = [0]
black_temp = [0]
white_temp = [0]
gray_temp = [0]
purple_temp = [0]
maxsize_temp = {}
frame = cv2.imread(img)
img_hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
mask_red = cv2.inRange(img_hsv, lower_red, higher_red) # 可以认为是过滤出红色部分,获得红色的掩膜
mask_red = cv2.medianBlur(mask_red, 7) # 中值滤波
mask_yellow = cv2.inRange(img_hsv, lower_yellow, higher_yellow) # 获得黄色部分掩膜
mask_yellow = cv2.medianBlur(mask_yellow, 7) # 中值滤波
mask_blue = cv2.inRange(img_hsv, lower_blue, higher_blue) # 获得蓝色部分掩膜
mask_blue = cv2.medianBlur(mask_blue, 7) # 中值滤波
mask_green = cv2.inRange(img_hsv, lower_green, higher_green) # 获得蓝色部分掩膜
mask_green = cv2.medianBlur(mask_green, 7) # 中值滤波
mask_black = cv2.inRange(img_hsv, lower_black, higher_black) # 获得黑色部分掩膜
mask_black = cv2.medianBlur(mask_black, 7) # 中值滤波
mask_while = cv2.inRange(img_hsv, lower_white, higher_white) # 获得白色部分掩膜
mask_while = cv2.medianBlur(mask_while, 7) # 中值滤波
mask_gray = cv2.inRange(img_hsv, lower_gray, higher_gray) # 获得灰色部分掩膜
mask_gray = cv2.medianBlur(mask_gray, 7) # 中值滤波
mask_purple = cv2.inRange(img_hsv, lower_purple, higher_purple) # 获得灰色部分掩膜
mask_purple = cv2.medianBlur(mask_purple, 7) # 中值滤波
# mask = cv2.bitwise_or(mask_green, mask_red) # 三部分掩膜进行按位或运算
# print(mask_red)
cnts1, hierarchy1 = cv2.findContours(mask_red, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # 轮廓检测 #红色
cnts2, hierarchy2 = cv2.findContours(mask_blue, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # 轮廓检测 #蓝色
cnts3, hierarchy3 = cv2.findContours(mask_yellow, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts4, hierarchy4 = cv2.findContours(mask_black, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts5, hierarchy5 = cv2.findContours(mask_while, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts6, hierarchy6 = cv2.findContours(mask_gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts7, hierarchy7 = cv2.findContours(mask_green, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts8, hierarchy8 = cv2.findContours(mask_purple, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
for cnt in cnts1:
# (x, y, w, h) = cv2.boundingRect(cnt) # 该函数返回矩阵四个点
# cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2) # 将检测到的颜色框起来
# cv2.putText(frame, 'red', (x, y - 5), font, 0.7, (0, 0, 255), 2)
# cv2.drawContours(frame, cnt, -1, (0, 0, 255), -1)
size = cv2.contourArea(cnt)
red_temp.append(size)
for cnt in cnts2:
# (x, y, w, h) = cv2.boundingRect(cnt) # 该函数返回矩阵四个点
# cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2) # 将检测到的颜色框起来
# cv2.putText(frame, 'blue', (x, y - 5), font, 0.7, (255, 0, 0), 2)
# cv2.drawContours(frame, cnt, -1, (255, 0, 0), -1)
size = cv2.contourArea(cnt)
blue_temp.append(size)
for cnt in cnts3:
# (x, y, w, h) = cv2.boundingRect(cnt) # 该函数返回矩阵四个点
# cv2.rectangle(frame, (x, y), (x + w, y + h), (50, 50, 50), 2) # 将检测到的颜色框起来
# cv2.putText(frame, 'yellow', (x, y - 5), font, 0.7, (50, 50, 50), 2)
# cv2.drawContours(frame, cnt, -1, (50, 50, 50), -1)
size = cv2.contourArea(cnt)
yellow_temp.append(size)
for cnt in cnts4:
# (x, y, w, h) = cv2.boundingRect(cnt) # 该函数返回矩阵四个点
# cv2.rectangle(frame, (x, y), (x + w, y + h), (88, 87, 86), 2) # 将检测到的颜色框起来
# cv2.putText(frame, 'black', (x, y - 5), font, 0.7, (88, 87, 86), 2)
# cv2.drawContours(frame, cnt, -1, (88, 87, 86), -1)
size = cv2.contourArea(cnt)
black_temp.append(size)
for cnt in cnts5:
# (x, y, w, h) = cv2.boundingRect(cnt) # 该函数返回矩阵四个点
# cv2.rectangle(frame, (x, y), (x + w, y + h), (88, 87, 86), 2) # 将检测到的颜色框起来
# cv2.putText(frame, 'white', (x, y - 5), font, 0.7, (88, 87, 86), 2)
# cv2.drawContours(frame, cnt, -1, (88, 87, 86), -1)
size = cv2.contourArea(cnt)
white_temp.append(size)
for cnt in cnts6:
# (x, y, w, h) = cv2.boundingRect(cnt) # 该函数返回矩阵四个点
# cv2.rectangle(frame, (x, y), (x + w, y + h), (220, 183, 183), 2) # 将检测到的颜色框起来
# cv2.putText(frame, 'gray', (x, y - 5), font, 0.7, (220, 183, 183), 2)
# cv2.drawContours(frame, cnt, -1, (220, 183, 183), -1)
size = cv2.contourArea(cnt)
gray_temp.append(size)
for cnt in cnts7:
# (x, y, w, h) = cv2.boundingRect(cnt) # 该函数返回矩阵四个点
# cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) # 将检测到的颜色框起来
# cv2.putText(frame, 'green', (x, y - 5), font, 0.7, (0, 255, 0), 2)
# cv2.drawContours(frame, cnt, -1, (0, 255, 0), -1)
size = cv2.contourArea(cnt)
green_temp.append(size)
for cnt in cnts8:
# (x, y, w, h) = cv2.boundingRect(cnt) # 该函数返回矩阵四个点
# cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) # 将检测到的颜色框起来
# cv2.putText(frame, 'green', (x, y - 5), font, 0.7, (0, 255, 0), 2)
# cv2.drawContours(frame, cnt, -1, (240, 32, 160), -1)
size = cv2.contourArea(cnt)
purple_temp.append(size)
# print(max(red_temp))
# print(max(gray_temp))
# print(max(green_temp))
# print(max(black_temp))
# print(max(blue_temp))
#黑色与灰色多为干扰颜色,故为其他颜色添加补偿系数
maxsize_temp["red"] = sum(red_temp)*10
maxsize_temp["blue"] = sum(blue_temp)*10
maxsize_temp["green"] = sum(green_temp)*10
maxsize_temp["yellow"] = sum(yellow_temp)*10
maxsize_temp["black"] = max(black_temp)
maxsize_temp["white"] = sum(white_temp)*10
maxsize_temp["gray"] = max(gray_temp)
maxsize_temp["purple"] = sum(purple_temp)*10
# maxsize_temp["red"] = max(red_temp) * 10
# maxsize_temp["blue"] = max(blue_temp) * 10
# maxsize_temp["green"] = max(green_temp) * 10
# maxsize_temp["yellow"] = max(yellow_temp) * 10
# maxsize_temp["black"] = max(black_temp)
# maxsize_temp["white"] = max(white_temp)*10
# maxsize_temp["gray"] = max(gray_temp)
# maxsize_temp["purple"] = max(purple_temp) * 10
# print(maxsize_temp)
d = list(zip(maxsize_temp.values(), maxsize_temp.keys()))
d = sorted(d)
# print(d)
return d[-1][-1], frame
if __name__ == '__main__':
#单张测试
# img = r"shiphead/1036.jpg"
# color_final, img = color_detection(img)
# print(color_final)
# size = img.shape
# w = size[1] # 宽度
# h = size[0] # 高度
# cv2.putText(img, color_final, (int(w/2), int(h/2)), font, 0.7, (0, 255, 0), 2)
# cv2.imshow('frame', img)
# # cv2.imwrite('res/res7.png', img)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
#批量测试
img_dir = r'E:\opencv\colordetect\shiphead' # 原始文件目录
# img_dir = r'E:\opencv\colordetect\test' # 原始文件目录
save_dir = r'E:\opencv\colordetect\result3/' # 保存目录
if not os.path.exists(save_dir):
os.makedirs(save_dir)
names = os.listdir(img_dir)
for name in names:
img_path = os.path.join(img_dir, name)
# image = cv2.imread(img_path)
color_final, img = color_detection(img_path)
# print(color_final)
size = img.shape
w = size[1] # 宽度
h = size[0] # 高度
cv2.putText(img, color_final, (int(w / 2), int(h / 2)), font, 0.7, (255, 255, 255), 2)
cv2.imwrite(save_dir + name, img)
print("finished")
本方法是一种比较简单且通用的颜色检测方法,能满足简单真实场景下的颜色检测要求。
本方法不足之处为:
①准确度依赖剪裁图像的质量;
②颜色上下界阈值设定不一定符合人眼感受。
如果阅读本文对你有用,欢迎点赞关注评论收藏呀!!!
2021年2月5日17:57:46