You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于OpenCV的Python图像颜色识别:红/紫色条纹识别失败问题

解决OpenCV中红/紫色HSV颜色范围识别问题

从你的代码来看,红色识别失效的核心问题是HSV范围设置完全错误,OpenCV里的HSV通道取值范围是固定的:

  • H(色调):0~180
  • S(饱和度):0~255
  • V(亮度):0~255

你的red_upper里H值设为239(超过了180的上限),而且S和V的数值逻辑颠倒了(比如S的上限设为12,这几乎是灰色区域,根本抓不到红色)。另外红色在HSV里是跨0度的,需要分两段范围来覆盖,紫色则是单独一段范围。

修正后的代码

下面是调整好红/紫色HSV范围的完整代码,同时优化了部分逻辑:

import numpy as np
import cv2

img = cv2.imread(r'/home/pavithra/Downloads/pic.jpeg')
hsvFrame = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# 红色的HSV范围(分两段,因为红色在色轮两端)
red_lower1 = np.array([0, 80, 80], np.uint8)
red_upper1 = np.array([10, 255, 255], np.uint8)
red_lower2 = np.array([160, 80, 80], np.uint8)
red_upper2 = np.array([180, 255, 255], np.uint8)
# 合并两个红色掩码
red_mask1 = cv2.inRange(hsvFrame, red_lower1, red_upper1)
red_mask2 = cv2.inRange(hsvFrame, red_lower2, red_upper2)
red_mask = cv2.bitwise_or(red_mask1, red_mask2)

# 紫色的HSV范围
purple_lower = np.array([120, 80, 80], np.uint8)
purple_upper = np.array([160, 255, 255], np.uint8)
purple_mask = cv2.inRange(hsvFrame, purple_lower, purple_upper)

# 保留你原来的绿、蓝范围
green_lower = np.array([25, 52, 72], np.uint8)
green_upper = np.array([102, 255, 255], np.uint8)
green_mask = cv2.inRange(hsvFrame, green_lower, green_upper)

blue_lower = np.array([94, 80, 2], np.uint8)
blue_upper = np.array([120, 255, 255], np.uint8)
blue_mask = cv2.inRange(hsvFrame, blue_lower, blue_upper)

kernal = np.ones((5, 5), "uint8")
# 膨胀操作
red_mask = cv2.dilate(red_mask, kernal)
purple_mask = cv2.dilate(purple_mask, kernal)
green_mask = cv2.dilate(green_mask, kernal)
blue_mask = cv2.dilate(blue_mask, kernal)

# 生成颜色掩码后的图像
res_red = cv2.bitwise_and(img, img, mask=red_mask)
res_purple = cv2.bitwise_and(img, img, mask=purple_mask)
res_green = cv2.bitwise_and(img, img, mask=green_mask)
res_blue = cv2.bitwise_and(img, img, mask=blue_mask)

# 红色轮廓检测与绘制
contours, hierarchy = cv2.findContours(red_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for pic, contour in enumerate(contours):
    area = cv2.contourArea(contour)
    if area > 300:
        x, y, w, h = cv2.boundingRect(contour)
        img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)
        cv2.putText(img, "Red", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), 2)

# 紫色轮廓检测与绘制
contours, hierarchy = cv2.findContours(purple_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for pic, contour in enumerate(contours):
    area = cv2.contourArea(contour)
    if area > 300:
        x, y, w, h = cv2.boundingRect(contour)
        img = cv2.rectangle(img, (x, y), (x + w, y + h), (128, 0, 128), 2)
        cv2.putText(img, "Purple", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (128, 0, 128), 2)

# 绿色轮廓检测与绘制(保留原逻辑)
contours, hierarchy = cv2.findContours(green_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for pic, contour in enumerate(contours):
    area = cv2.contourArea(contour)
    if area > 300:
        x, y, w, h = cv2.boundingRect(contour)
        img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
        cv2.putText(img, "Green", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 0), 2)

# 蓝色轮廓检测与绘制(保留原逻辑)
contours, hierarchy = cv2.findContours(blue_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for pic, contour in enumerate(contours):
    area = cv2.contourArea(contour)
    if area > 300:
        x, y, w, h = cv2.boundingRect(contour)
        img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
        cv2.putText(img, "Blue", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 2)

resize = cv2.resize(img, (800, 480))
cv2.imshow("Color Detection", resize)
cv2.waitKey(0)
cv2.destroyAllWindows()

关键调整点说明

  1. 红色HSV范围修正:

    • 红色在HSV色轮中是从0度附近到10度,以及160度到180度的两段区域,所以需要用两个范围合并掩码,才能完整覆盖所有红色色调。
    • 把S和V的下限设为80,确保只抓取饱和度和亮度足够高的红色,避免误识别灰色或浅色区域。
  2. 紫色HSV范围设置:

    • 紫色的H通道范围大概在120~160之间,同样设置合适的S和V下限,保证只识别纯正的紫色区域。
  3. 其他细节优化:

    • 给红色和紫色的绘制框用了对应颜色的BGR值(OpenCV默认BGR格式),让识别结果更直观。
    • 最后添加了cv2.destroyAllWindows()避免程序退出后窗口残留。

调试HSV范围的实用技巧

如果还是需要微调颜色范围,可以写一个带滑动条的小工具,实时调整HSV上下限并预览掩码效果:

import cv2
import numpy as np

def nothing(x):
    pass

# 创建窗口
cv2.namedWindow("HSV Tuner")
# 创建滑动条
cv2.createTrackbar("H Lower", "HSV Tuner", 0, 180, nothing)
cv2.createTrackbar("H Upper", "HSV Tuner", 180, 180, nothing)
cv2.createTrackbar("S Lower", "HSV Tuner", 0, 255, nothing)
cv2.createTrackbar("S Upper", "HSV Tuner", 255, 255, nothing)
cv2.createTrackbar("V Lower", "HSV Tuner", 0, 255, nothing)
cv2.createTrackbar("V Upper", "HSV Tuner", 255, 255, nothing)

img = cv2.imread(r'/home/pavithra/Downloads/pic.jpeg')
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

while True:
    # 获取滑动条值
    h_low = cv2.getTrackbarPos("H Lower", "HSV Tuner")
    h_high = cv2.getTrackbarPos("H Upper", "HSV Tuner")
    s_low = cv2.getTrackbarPos("S Lower", "HSV Tuner")
    s_high = cv2.getTrackbarPos("S Upper", "HSV Tuner")
    v_low = cv2.getTrackbarPos("V Lower", "HSV Tuner")
    v_high = cv2.getTrackbarPos("V Upper", "HSV Tuner")
    
    # 创建掩码
    lower = np.array([h_low, s_low, v_low])
    upper = np.array([h_high, s_high, v_high])
    mask = cv2.inRange(hsv, lower, upper)
    res = cv2.bitwise_and(img, img, mask=mask)
    
    # 显示结果
    cv2.imshow("Original", img)
    cv2.imshow("Mask", mask)
    cv2.imshow("Result", res)
    
    # 按ESC退出
    if cv2.waitKey(1) == 27:
        print(f"Lower HSV: [{h_low}, {s_low}, {v_low}]")
        print(f"Upper HSV: [{h_high}, {s_high}, {v_high}]")
        break

cv2.destroyAllWindows()

运行这个工具后,拖动滑动条直到掩码刚好覆盖你要识别的红/紫色区域,然后打印出的数值就是你需要的HSV范围。

内容的提问来源于stack exchange,提问作者kavi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 22:38:15