当前位置: 首页 > article >正文

Python中使用opencv-python库进行颜色检测

Python中使用opencv-python库进行颜色检测

之前写过一篇VC++中使用OpenCV进行颜色检测的博文,当然使用opencv-python库也可以实现。
在Python中使用opencv-python库进行颜色检测非常简单,首选读取一张彩色图像,并调用函数imgHSV = cv2.cvtColor(img,cv2.COLOR_BGR2HSV);函数将原图img转换成HSV图像imgHSV,再设置好HSV三个分量的上限和下限值,调用inRange函数imask = cv2.inRange(imgHSV,lower,upper)将HSV色彩图像转换成掩码图,掩码图中只有黑白二值图像,从而达到颜色检测的目的。颜色检测通常可以用于物体检测和跟踪中,尤其在不同的图像和物体中根据特定的颜色去筛选出某个物体。

通过学习油管博主murtazahassan的视频LEARN OPENCV in 3 HOURS with Python | Including 3xProjects | Computer Vision,里面第7个OpenCV示例将到如何从一副兰博基尼的轿车图像中进行颜色检测,相关代码地址为:Learn-OpenCV-in-3-hours
/chapter7.py
如下所示:

import cv2
import numpy as np

def empty(a):
    pass

def stackImages(scale,imgArray):
    rows = len(imgArray)
    cols = len(imgArray[0])
    rowsAvailable = isinstance(imgArray[0], list)
    width = imgArray[0][0].shape[1]
    height = imgArray[0][0].shape[0]
    if rowsAvailable:
        for x in range ( 0, rows):
            for y in range(0, cols):
                if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
                else:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
                if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
        imageBlank = np.zeros((height, width, 3), np.uint8)
        hor = [imageBlank]*rows
        hor_con = [imageBlank]*rows
        for x in range(0, rows):
            hor[x] = np.hstack(imgArray[x])
        ver = np.vstack(hor)
    else:
        for x in range(0, rows):
            if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
                imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
            else:
                imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
            if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
        hor= np.hstack(imgArray)
        ver = hor
    return ver



path = 'Resources/lambo.png'
cv2.namedWindow("TrackBars")
cv2.resizeWindow("TrackBars",640,240)
cv2.createTrackbar("Hue Min","TrackBars",0,179,empty)
cv2.createTrackbar("Hue Max","TrackBars",19,179,empty)
cv2.createTrackbar("Sat Min","TrackBars",110,255,empty)
cv2.createTrackbar("Sat Max","TrackBars",240,255,empty)
cv2.createTrackbar("Val Min","TrackBars",153,255,empty)
cv2.createTrackbar("Val Max","TrackBars",255,255,empty)

while True:
    img = cv2.imread(path)
    imgHSV = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
    h_min = cv2.getTrackbarPos("Hue Min","TrackBars")
    h_max = cv2.getTrackbarPos("Hue Max", "TrackBars")
    s_min = cv2.getTrackbarPos("Sat Min", "TrackBars")
    s_max = cv2.getTrackbarPos("Sat Max", "TrackBars")
    v_min = cv2.getTrackbarPos("Val Min", "TrackBars")
    v_max = cv2.getTrackbarPos("Val Max", "TrackBars")
    print(h_min,h_max,s_min,s_max,v_min,v_max)
    lower = np.array([h_min,s_min,v_min])
    upper = np.array([h_max,s_max,v_max])
    mask = cv2.inRange(imgHSV,lower,upper)
    imgResult = cv2.bitwise_and(img,img,mask=mask)


    # cv2.imshow("Original",img)
    # cv2.imshow("HSV",imgHSV)
    # cv2.imshow("Mask", mask)
    # cv2.imshow("Result", imgResult)

    imgStack = stackImages(0.6,([img,imgHSV],[mask,imgResult]))
    cv2.imshow("Stacked Images", imgStack)

    cv2.waitKey(1)

代码示例和运行结果

import cv2
import numpy as np

"""
@param scale: 图像缩放比例系数
@param imgArray: 二维图像数组
"""
def stackImages(scale,imgArray):
    rows = len(imgArray)
    cols = len(imgArray[0])
    rowsAvailable = isinstance(imgArray[0], list)
    width = imgArray[0][0].shape[1]
    height = imgArray[0][0].shape[0]
    if rowsAvailable:
        for x in range ( 0, rows):
            for y in range(0, cols):
                if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
                else:
                    imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
                if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
        imageBlank = np.zeros((height, width, 3), np.uint8)
        hor = [imageBlank]*rows
        hor_con = [imageBlank]*rows
        for x in range(0, rows):
            hor[x] = np.hstack(imgArray[x])
        ver = np.vstack(hor)
    else:
        for x in range(0, rows):
            if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
                imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
            else:
                imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
            if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
        hor= np.hstack(imgArray)
        ver = hor
    return ver

# 进度条回调函数
"""
@param val: 用户选择的当前进度条的数值
"""
def onValueChanged(val):
    # print("val: ", val)
    pass

# 颜色检测
path = "Resources/lambo.png"
cv2.namedWindow("TrackBars")
cv2.resizeWindow("TrackBars", 640, 240) # 创建一个宽为640,高为200的,窗口名称为Trackbars的窗口
# 在窗口名称为Trackbars的窗口中创建一个名为Hue Min的滑动条,最小值默认为0,最大值为179,滑动条所在值即为hmin,用来控制H分量的最小值
cv2.createTrackbar("Hue Min", "TrackBars", 0, 179, onValueChanged)
# 在窗口名称为Trackbars的窗口中创建一个名为Hue Max的滑动条,最小值默认为0,最大值为179,滑动条所在值即为hmax,用来控制H分量的最大值
cv2.createTrackbar("Hue Max", "TrackBars", 19, 179, onValueChanged)
# 在窗口名称为Trackbars的窗口中创建一个名为Sat Min的滑动条,最小值默认为0,最大值为255,滑动条所在值即为smin,用来控制S分量的最小值
cv2.createTrackbar("Sat Min", "TrackBars", 110, 255, onValueChanged)
# 在窗口名称为Trackbars的窗口中创建一个名为Sat Max的滑动条,最小值默认为0,最大值为255,滑动条所在值即为smax,用来控制S分量的最大值
cv2.createTrackbar("Sat Max", "TrackBars", 240, 255, onValueChanged)
# 在窗口名称为Trackbars的窗口中创建一个名为Val Min的滑动条,最小值默认为0,最大值为255,滑动条所在值即为vmin,用来控制V分量的最小值
cv2.createTrackbar("Val Min", "TrackBars", 153, 255, onValueChanged)
# 在窗口名称为Trackbars的窗口中创建一个名为Val Max的滑动条,最小值默认为0,最大值为255,滑动条所在值即为vmax,用来控制V分量的最大值
cv2.createTrackbar("Val Max", "TrackBars", 255, 255, onValueChanged)

# 循环检测用户操作,用户可以通过Trackbars窗口中的滑动条分别控制H、S、V三个分量的最小和最大值,从而控制mask以及Result图像的最终呈现
while True:
    img = cv2.imread(path)
    imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    h_min = cv2.getTrackbarPos("Hue Min", "TrackBars")
    h_max = cv2.getTrackbarPos("Hue Max", "TrackBars")
    s_min = cv2.getTrackbarPos("Sat Min", "TrackBars")
    s_max = cv2.getTrackbarPos("Sat Max", "TrackBars")
    v_min = cv2.getTrackbarPos("Val Min", "TrackBars")
    v_max = cv2.getTrackbarPos("Val Max", "TrackBars")
    print(h_min, h_max, s_min, s_max, v_min, v_max)
    lower = np.array([h_min, s_min, v_min])
    upper = np.array([h_max, s_max, v_max])
    mask = cv2.inRange(imgHSV, lower, upper)    # 根据lower和upper以及imgHSV图像生成mask图像
    imgResult = cv2.bitwise_and(img, img, mask=mask)

    # cv2.imshow("Original", img)
    # cv2.imshow("HSV", imgHSV)
    # cv2.imshow("Mask", mask)
    # cv2.imshow("Result", imgResult)

    imgStack = stackImages(0.6, ([img, imgHSV], [mask, imgResult]))
    cv2.imshow("Stacked Images", imgStack)

    cv2.waitKey(1)
cv2.destroyAllWindows()

运行结果如下图所示:
颜色检测运行结果

使用matplotlib库将多幅图像在一张图上显示

当然我们可以替换掉上面的stackImages(scale,imgArray),借助matplotlib`库将多幅图像在一张图上显示,相应的代码如下:

import cv2
import numpy as np
from matplotlib import pyplot as plt

# 进度条回调函数
"""
@param val: 用户选择的当前进度条的数值
"""
def onValueChanged(val):
    # print("val: ", val)
    pass

# 颜色检测
path = "Resources/lambo.png"
cv2.namedWindow("TrackBars")
cv2.resizeWindow("TrackBars", 640, 240) # 创建一个宽为640,高为200的,窗口名称为Trackbars的窗口
# 在窗口名称为Trackbars的窗口中创建一个名为Hue Min的滑动条,最小值默认为0,最大值为179,滑动条所在值即为hmin,用来控制H分量的最小值
cv2.createTrackbar("Hue Min", "TrackBars", 0, 179, onValueChanged)
# 在窗口名称为Trackbars的窗口中创建一个名为Hue Max的滑动条,最小值默认为0,最大值为179,滑动条所在值即为hmax,用来控制H分量的最大值
cv2.createTrackbar("Hue Max", "TrackBars", 19, 179, onValueChanged)
# 在窗口名称为Trackbars的窗口中创建一个名为Sat Min的滑动条,最小值默认为0,最大值为255,滑动条所在值即为smin,用来控制S分量的最小值
cv2.createTrackbar("Sat Min", "TrackBars", 110, 255, onValueChanged)
# 在窗口名称为Trackbars的窗口中创建一个名为Sat Max的滑动条,最小值默认为0,最大值为255,滑动条所在值即为smax,用来控制S分量的最大值
cv2.createTrackbar("Sat Max", "TrackBars", 240, 255, onValueChanged)
# 在窗口名称为Trackbars的窗口中创建一个名为Val Min的滑动条,最小值默认为0,最大值为255,滑动条所在值即为vmin,用来控制V分量的最小值
cv2.createTrackbar("Val Min", "TrackBars", 153, 255, onValueChanged)
# 在窗口名称为Trackbars的窗口中创建一个名为Val Max的滑动条,最小值默认为0,最大值为255,滑动条所在值即为vmax,用来控制V分量的最大值
cv2.createTrackbar("Val Max", "TrackBars", 255, 255, onValueChanged)

# 循环检测用户操作,用户可以通过Trackbars窗口中的滑动条分别控制H、S、V三个分量的最小和最大值,从而控制mask以及Result图像的最终呈现
while True:
    img = cv2.imread(path)
    imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    h_min = cv2.getTrackbarPos("Hue Min", "TrackBars")
    h_max = cv2.getTrackbarPos("Hue Max", "TrackBars")
    s_min = cv2.getTrackbarPos("Sat Min", "TrackBars")
    s_max = cv2.getTrackbarPos("Sat Max", "TrackBars")
    v_min = cv2.getTrackbarPos("Val Min", "TrackBars")
    v_max = cv2.getTrackbarPos("Val Max", "TrackBars")
    print(h_min, h_max, s_min, s_max, v_min, v_max)
    lower = np.array([h_min, s_min, v_min])
    upper = np.array([h_max, s_max, v_max])
    imgMask = cv2.inRange(imgHSV, lower, upper)    # 根据lower和upper以及imgHSV图像生成mask图像
    imgResult = cv2.bitwise_and(img, img, mask=imgMask)

    # cv2.imshow("Original", img)
    # cv2.imshow("HSV", imgHSV)
    # cv2.imshow("Mask", mask)
    # cv2.imshow("Result", imgResult)

    plt.figure(figsize=(8, 6))
    plt.subplot(221), plt.axis('off'), plt.title("1.Original Image")
    plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    plt.subplot(222), plt.axis("off"), plt.title("2.HSV Image")
    plt.imshow(cv2.cvtColor(imgHSV, cv2.COLOR_BGR2RGB))
    plt.subplot(223), plt.axis("off"), plt.title("3.Mask Image")
    plt.imshow(cv2.cvtColor(imgMask, cv2.COLOR_BGR2RGB))
    plt.subplot(224), plt.axis("off"), plt.title("4.Result Image")
    # plt.imshow(imgResult)
    plt.imshow(cv2.cvtColor(imgResult, cv2.COLOR_BGR2RGB))
    plt.tight_layout()
    plt.show()

    cv2.waitKey(1)
cv2.destroyAllWindows()

VScode中运行结果如下图所示:
VSCode运行结果2
注意由于python-opencv中彩色图像默认是BGRmatplotlib库中默认是RGB,所以使用matplotlib库显示图像时,需要对原图像(BGR)使用cv2.cvtColor(img, cv2.COLOR_BGR2RGB)函数进行转换,不然图像显示不正确。如下图所示:
颜色不对

参考资料

  • HSL和HSV色彩空间
  • OpenCV—HSV色彩空间基础知识
  • 三分钟带你快速学习RGB、HSV和HSL颜色空间
  • Learn-OpenCV-in-3-hours Python Video
  • Learn-OpenCV-in-3-hours
  • Learn-OpenCV-cpp-in-4-Hours C++ Video
  • https://github.com/murtazahassan/Learn-OpenCV-cpp-in-4-Hours
  • https://github.com/murtazahassan

http://www.kler.cn/a/233048.html

相关文章:

  • odoo 17 后端路由接口认证自定义
  • 服务器显卡和桌面pc显卡有什么不同
  • INQUIRE:一个包含五百万张自然世界图像,涵盖10,000个不同物种的专为专家级文本到图像检索任务设计的新型基准数据集。
  • 基于混合配准策略的多模态医学图像配准方法研究
  • Typescript类型运算符、关键字以及内置高级类型
  • ODOO学习笔记(1):ODOO的SWOT分析和技术优势是什么?
  • 【芯片设计- RTL 数字逻辑设计入门 7 -- 同步复位与异步复位详细介绍】
  • 使用Collections.singletonList()遇到的问题
  • Unity学习笔记之【IK反向动力学操作】
  • 20240209-最大可整分子集
  • c#: 表达式树的简化
  • 科研绘图-半小提琴图-
  • List 差集
  • 【开源】JAVA+Vue+SpringBoot实现房屋出售出租系统
  • vue父子组件通讯的几种方式总结学习
  • 基于SpringBoot的记账系统项目
  • Vagrant 虚拟机工具基本操作指南
  • echarts 一条折线图上显示不同颜色
  • 【Android】GridLayout实现等比布局
  • DC-9靶机渗透详细流程
  • 每日五道java面试题之java基础篇(一)
  • 飞桨自然语言处理框架 paddlenlp的 trainer
  • openssl3.2 - exp - buffer to BIO
  • HarmonyOS SDK 助力新浪新闻打造精致易用的新闻应用
  • 【ETOJ P1046】斐波那契数列 题解(数学+动态规划)
  • Electron+Vue实现仿网易云音乐实战