OpenCV物体颜色检测(Python)


前言

最近工作又来新活了,船舶颜色检测。开始接到这个活还是有点懵,后面慢慢的感觉来了!!!


一、前期调查

因为本项目涉及到颜色判断与分类,笔者一开始就想到的就是每种颜色的范围划分是什么,刚开始想的是否能够依据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

  • 8
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI小笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值