python - 如何使用OpenCV检测具有相同颜色的像素区域

标签 python image opencv image-processing computer-vision

使用 OpenCV Python,我想知道什么是最好的方法来识别图像中具有高浓度特定颜色像素的区域,并可能通过在它们周围绘制一个圆圈来“标记”它们。

我尝试使用 findContours 方法,但是一团糟...

我的直觉告诉我必须设置颜色相邻像素的范围 [min : max],然后确定该区域的中心,并在其中绘制一个“O”...


第一个图像是我在处理 BGR 图像(到 HSV 并处理几个颜色掩码)后得到的示例:

检测前的图像

第二张图像是我在检测到该区域后尝试绘制的图像。 是的,我自己添加了黑色圆圈作为示例:-)

检测后的图像

最佳答案

颜色阈值 cv2.inRange()应该在这里工作

这是主要思想

  • 将图像转换为 HSV 格式
  • 使用较低/较高阈值执行颜色分割
  • 用于去除小噪声的形态学变换
  • 找到轮廓并计算轮廓面积

我假设您想检测黄色区域。我们首先将图像转换为 HSV 格式,然后使用具有较低/较高范围的颜色阈值

lower = np.array([33, 0, 238], dtype="uint8")
upper = np.array([135, 189, 255], dtype="uint8")

这会产生一个分段蒙版

enter image description here

检测到黄色区域

enter image description here

从这里我们执行形态学变换以去除小噪声

enter image description here

接下来我们找到轮廓并用 cv2.contourArea() 对面积求和。检测到的区域以黑色突出显示

enter image description here

总面积

87781.5

import numpy as np
import cv2

# Load image and HSV color threshold
image = cv2.imread('1.jpg')
original = image.copy()
image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower = np.array([33, 0, 238], dtype="uint8")
upper = np.array([135, 189, 255], dtype="uint8")
mask = cv2.inRange(image, lower, upper)
detected = cv2.bitwise_and(original, original, mask=mask)

# Remove noise
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=1)

# Find contours and find total area
cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
area = 0
for c in cnts:
    area += cv2.contourArea(c)
    cv2.drawContours(original,[c], 0, (0,0,0), 2)

print(area)
cv2.imshow('mask', mask)
cv2.imshow('original', original)
cv2.imshow('opening', opening)
cv2.imshow('detected', detected)
cv2.waitKey()

您可以使用此脚本来查找颜色阈值范围

import cv2
import sys
import numpy as np

def nothing(x):
    pass

useCamera=False

# Check if filename is passed
if (len(sys.argv) <= 1) :
    print("'Usage: python hsvThresholder.py <ImageFilePath>' to ignore camera and use a local image.")
    useCamera = True

# Create a window
cv2.namedWindow('image')

# create trackbars for color change
cv2.createTrackbar('HMin','image',0,179,nothing) # Hue is from 0-179 for Opencv
cv2.createTrackbar('SMin','image',0,255,nothing)
cv2.createTrackbar('VMin','image',0,255,nothing)
cv2.createTrackbar('HMax','image',0,179,nothing)
cv2.createTrackbar('SMax','image',0,255,nothing)
cv2.createTrackbar('VMax','image',0,255,nothing)

# Set default value for MAX HSV trackbars.
cv2.setTrackbarPos('HMax', 'image', 179)
cv2.setTrackbarPos('SMax', 'image', 255)
cv2.setTrackbarPos('VMax', 'image', 255)

# Initialize to check if HSV min/max value changes
hMin = sMin = vMin = hMax = sMax = vMax = 0
phMin = psMin = pvMin = phMax = psMax = pvMax = 0

# Output Image to display
if useCamera:
    cap = cv2.VideoCapture(0)
    # Wait longer to prevent freeze for videos.
    waitTime = 330
else:
    img = cv2.imread(sys.argv[1])
    output = img
    waitTime = 33

while(1):

    if useCamera:
        # Capture frame-by-frame
        ret, img = cap.read()
        output = img

    # get current positions of all trackbars
    hMin = cv2.getTrackbarPos('HMin','image')
    sMin = cv2.getTrackbarPos('SMin','image')
    vMin = cv2.getTrackbarPos('VMin','image')

    hMax = cv2.getTrackbarPos('HMax','image')
    sMax = cv2.getTrackbarPos('SMax','image')
    vMax = cv2.getTrackbarPos('VMax','image')

    # Set minimum and max HSV values to display
    lower = np.array([hMin, sMin, vMin])
    upper = np.array([hMax, sMax, vMax])

    # Create HSV Image and threshold into a range.
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    mask = cv2.inRange(hsv, lower, upper)
    output = cv2.bitwise_and(img,img, mask= mask)

    # Print if there is a change in HSV value
    if( (phMin != hMin) | (psMin != sMin) | (pvMin != vMin) | (phMax != hMax) | (psMax != sMax) | (pvMax != vMax) ):
        print("(hMin = %d , sMin = %d, vMin = %d), (hMax = %d , sMax = %d, vMax = %d)" % (hMin , sMin , vMin, hMax, sMax , vMax))
        phMin = hMin
        psMin = sMin
        pvMin = vMin
        phMax = hMax
        psMax = sMax
        pvMax = vMax

    # Display output image
    cv2.imshow('image',output)

    # Wait longer to prevent freeze for videos.
    if cv2.waitKey(waitTime) & 0xFF == ord('q'):
        break

# Release resources
if useCamera:
    cap.release()
cv2.destroyAllWindows()

关于python - 如何使用OpenCV检测具有相同颜色的像素区域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57282935/

相关文章:

java - 检查jsp中是否存在图像

当源为 multipart.File 时,image.Decode 的结果为 "unknown format"

python - OpenCV python拜耳转换错误

python - 从 Pandas 数据框中,如何找到每个用户的重复评论数?

python - Selenium Python For 循环遍历 HTML 表 我想迭代第一行而不是所有行

python - 创建需要使用 pdfkit 登录的 https 网页的 PDF

javascript从客户端保存/加载图像+文本数据

python - 将 opencv 图像连同其他数据一起发送到 Flask Server

c++ - OpenCV:归一化图像的像素值

python - 如何将 pandas 数据框转换为没有列标题的字典?