如何使用 Python OpenCV 定义阈值来仅检测图像中的绿色物体?
- 2025-01-09 08:47:00
- admin 原创
- 160
问题描述:
我想从自然环境中拍摄的图像中仅检测绿色物体。我该如何定义它?
因为在这里我想传递阈值,比如说“x”。通过这个 x,我希望只有绿色物体才能呈现出一种颜色(白色),而其他物体必须呈现另一种颜色(黑色)。
我该怎么做?
解决方案 1:
单程
我制作了一个 HSV 颜色图。使用此图比以前更容易、更准确地找到颜色范围。
也许我应该在 HSV 中使用 (40, 40,40) ~ (70, 255,255)来找到绿色。
另一种方式
转换为 HSV 颜色空间,
使用
cv2.inRange(hsv, hsv_lower, hsv_higher)
即可获得绿色面具。
我们对这朵向日葵使用的范围(在 HSV 中):(36,0,0)〜(86,255,255)。
源图像:
被掩盖的绿色区域:
更多步骤:
核心源代码:
import cv2
import numpy as np
## Read
img = cv2.imread("sunflower.jpg")
## Convert to HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
## Mask of green (36,25,25) ~ (86, 255,255)
# mask = cv2.inRange(hsv, (36, 25, 25), (86, 255,255))
mask = cv2.inRange(hsv, (36, 25, 25), (70, 255,255))
## Slice the green
imask = mask>0
green = np.zeros_like(img, np.uint8)
green[imask] = img[imask]
## Save
cv2.imwrite("green.png", green)
相似的:
使用
cv::inRange
(OpenCV)选择正确的HSV上下边界进行颜色检测
解决方案 2:
简介:
使用LAB 颜色空间可以很容易地应用阈值来检测绿色。
LAB 颜色空间也有 3 个通道,但与 RGB 颜色空间(其中所有 3 个都是颜色通道)不同,LAB 中有2 个颜色通道和1 个亮度通道:
L通道:表示图像中的亮度值
A通道:代表图像中的红色和绿色
B通道:代表图像中的蓝色和黄色
观察下图:
绿色和红色在 A 通道的两端表示。在此通道上对任一两端应用合适的阈值可以分割出绿色或红色。
演示:
以下图片按顺序排列:
1.原始图像 -->> 2. LAB 转换图像的 A 通道
3.阈值 -->> 4.原始图像上的蒙版
示例 1:
示例 2:
示例 3:
代码:
代码只有几行:
# read image in BGR
img = cv2.imread('image_path')
# convert to LAB space
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
# store the a-channel
a_channel = lab[:,:,1]
# Automate threshold using Otsu method
th = cv2.threshold(a_channel,127,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)[1]
# Mask the result with the original image
masked = cv2.bitwise_and(img, img, mask = th)
例外:
如果绿色明显,上述方法将非常有效。但应用自动阈值可能并不总是有效,尤其是当同一张图片中存在各种深浅不一的绿色时。
在这种情况下,可以在 A 通道上手动设置阈值。
img = cv2.imread('flower.jpg')
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
a_channel = lab[:,:,1]
# manually set threshold value
th = cv2.threshold(a_channel, 105, 255, cv2.THRESH_BINARY_INV)
# perform masking
masked = cv2.bitwise_and(img, img, mask = th)
Threshold image Masked image
解决方案 3:
您可以使用简单的 HSV 颜色阈值脚本,使用轨迹栏确定磁盘上任何图像的下限/上限颜色范围。只需更改 中的图像路径cv2.imread()
。隔离绿色的示例:
import cv2
import numpy as np
def nothing(x):
pass
# Load image
image = cv2.imread('1.jpg')
# Create a window
cv2.namedWindow('image')
# Create trackbars for color change
# Hue is from 0-179 for Opencv
cv2.createTrackbar('HMin', 'image', 0, 179, nothing)
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 HSV min/max values
hMin = sMin = vMin = hMax = sMax = vMax = 0
phMin = psMin = pvMin = phMax = psMax = pvMax = 0
while(1):
# 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 maximum HSV values to display
lower = np.array([hMin, sMin, vMin])
upper = np.array([hMax, sMax, vMax])
# Convert to HSV format and color threshold
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, lower, upper)
result = cv2.bitwise_and(image, image, 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 result image
cv2.imshow('image', result)
if cv2.waitKey(10) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
HSV 下限/上限颜色阈值范围
(hMin = 52 , sMin = 0, vMin = 55), (hMax = 104 , sMax = 255, vMax = 255)
一旦确定了lower
HSVupper
颜色范围,就可以像这样分割所需的颜色:
import numpy as np
import cv2
image = cv2.imread('1.png')
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower = np.array([52, 0, 55])
upper = np.array([104, 255, 255])
mask = cv2.inRange(hsv, lower, upper)
result = cv2.bitwise_and(image, image, mask=mask)
cv2.imshow('result', result)
cv2.waitKey()
扫码咨询,免费领取项目管理大礼包!