我正在尝试确定图像是否包含沙漏的特定形状。形状始终处于固定位置并具有固定大小。然而,背景不同,它会影响形状的颜色。参见示例 1、2 和 3:、、
如果沙漏是空的,则图像仅包含背景。检测这种形状以最大限度地减少误报和漏报的最佳方法是什么?
thresholding
(静态和自适应)似乎不太可靠,因为以下代码对于第二个示例来说效果不佳:
图像缺少某些部分:
import cv2
img = cv2.imread('hourglass.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 70, 255, cv2.THRESH_BINARY)[1]
cv2.imshow("thresh", thresh)
cv2.waitKey(0)
我考虑过手动检查沙漏所在的像素颜色是否接近,但这看起来很“hacky”,并且可能会根据阈值的选择给出错误的结果
我对构成图像中沙漏的有趣像素做了一个(相当粗糙的)蒙版,如下 -
mask.png
:
然后我将您的图像转换为 HSV 色彩空间并分离出 饱和度 通道。一般来说,当图像饱和且鲜艳时,该值会较高;而当图像不太鲜艳、饱和度较低且灰色较多时,该值会较低。然后我计算了遮蔽区域中图像的平均值和标准差,然后再次计算了遮蔽区域之外的区域。
我假设沙漏所在的地方平均值会很低,因为沙漏所在的地方不饱和,并且沙漏所在的地方方差也会很低,因为沙漏内的变化很小。设定结果阈值以匹配您的数据。
#!/usr/bin/env python3
import cv2 as cv
# Load mask with interesting pixels masked as white
mask = cv.imread('mask.png', cv.IMREAD_GRAYSCALE)
def processOne(filename, mask):
# Load image, convert to HSV, and split out S component
im = cv.imread(filename)
HSV = cv.cvtColor(im, cv.COLOR_BGR2HSV)
_, S, _ = cv.split(HSV)
# Calculate masked mean and stddev of S component
mean, stddev = cv.meanStdDev(S,mask=mask)
print(f'File: {filename}, MASKED AREA {mean=}, {stddev=}')
mean, stddev = cv.meanStdDev(S,mask=~mask)
print(f'File: {filename}, UNMASKED AREA {mean=}, {stddev=}')
processOne('h1.png', mask)
processOne('h2.png', mask)
processOne('h3.png', mask)
输出:
File: h1.png, MASKED AREA mean=array([[13.89722222]]), stddev=array([[10.40768909]])
File: h1.png, UNMASKED AREA mean=array([[74.00181488]]), stddev=array([[33.2070991]])
File: h2.png, MASKED AREA mean=array([[55.66944444]]), stddev=array([[22.63463815]])
File: h2.png, UNMASKED AREA mean=array([[144.43647913]]), stddev=array([[18.2676475]])
File: h3.png, MASKED AREA mean=array([[15.55833333]]), stddev=array([[12.96799211]])
File: h3.png, UNMASKED AREA mean=array([[96.01270417]]), stddev=array([[32.66029606]])