Python 使用OpenCV改善显光条件下的洪水填充效果
我正在尝试用工具对图像进行轮廓检测,因为工具的金属性质会反射光线并产生眩光。为了限制这种影响,我使用了泛洪填充,但这对参数非常敏感 例如,这里是我的原始图像: 这是被洪水淹没的那个 这看起来很棒,不是我尝试的第二张图片: 正如您在泛光图像上看到的,一些工具没有正确处理,因此轮廓检测将无法给出良好的结果 以下是更新版本:Python 使用OpenCV改善显光条件下的洪水填充效果,python,opencv,Python,Opencv,我正在尝试用工具对图像进行轮廓检测,因为工具的金属性质会反射光线并产生眩光。为了限制这种影响,我使用了泛洪填充,但这对参数非常敏感 例如,这里是我的原始图像: 这是被洪水淹没的那个 这看起来很棒,不是我尝试的第二张图片: 正如您在泛光图像上看到的,一些工具没有正确处理,因此轮廓检测将无法给出良好的结果 以下是更新版本: import numpy as np import cv2 def getFilteredLabelIndex(stats, widthLowLimit=50, he
import numpy as np
import cv2
def getFilteredLabelIndex(stats, widthLowLimit=50, heightLowLimit=50, areaLowLimit=7000):
ret = []
for i in range(1, stats.shape[0]):
# extract the connected component statistics for the current label
w = stats[i, cv2.CC_STAT_WIDTH]
h = stats[i, cv2.CC_STAT_HEIGHT]
area = stats[i, cv2.CC_STAT_AREA]
keepWidth = w > widthLowLimit
keepHeight = h > heightLowLimit
keepArea = area > areaLowLimit
if all((keepWidth, keepHeight, keepArea)):
ret.append(i)
return ret
# load our input image, convert it to grayscale, and blur it slightly
impath = "q8djf.png"
originalImage = cv2.imread(impath)
birdEye = originalImage
seed = (35, 35)
originalImage = np.maximum(originalImage, 10)
foreground = originalImage.copy()
# Use floodFill for filling the background with black color
cv2.floodFill(foreground, None, seed, (0, 0, 0),
loDiff=(5, 5, 5), upDiff=(5, 5, 5))
cv2.imshow("foreground", foreground)
gray = cv2.cvtColor(foreground, cv2.COLOR_BGR2GRAY)
cv2.imshow("gray", gray)
threshImg = cv2.threshold(gray, 1, 255, cv2.THRESH_BINARY)[1]
cv2.imshow("threshImg", threshImg)
(numLabels, labels, stats, centroids) = cv2.connectedComponentsWithStats(
threshImg, 4, cv2.CV_32S)
filteredIdx = getFilteredLabelIndex(stats)
for i in filteredIdx:
componentMask = (labels == i).astype("uint8") * 255
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
componentMask = cv2.dilate(componentMask, kernel, iterations=3)
ctrs, _ = cv2.findContours(
componentMask, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
ctrs = sorted(ctrs, key=cv2.contourArea, reverse=True)
cntrs = max(ctrs, key=cv2.contourArea)
cv2.drawContours(birdEye, [cntrs], -1, (255, 0, 255), 3)
cv2.imshow("contour", birdEye)
cv2.imshow("original contour", birdEye)
cv2.waitKey(0)
cv2.destroyAllWindows()
欢迎任何建议。锐化输入图像可能会有所帮助 锐化操作会放大对象和背景之间的差异 我不确定它对其他图像的鲁棒性如何,但它可以提高当前解决方案的鲁棒性 我使用了以下帖子中的锐化解决方案:,但参数不同,锐化效果更强 以下代码演示了该解决方案:
#https://stackoverflow.com/questions/4993082/how-can-i-sharpen-an-image-in-opencv
#锐化图像
模糊=cv2.高斯模糊(birdEye,(0,0,3)
锐利的前景=cv2.addWeighted(birdEye,2,blur,-1,0);
锐利前景=np.最大值(锐利前景,10)
#使用泛光填充以黑色填充背景
#使用loDiff和upDiff(10,10,10)而不是(5,5,5)来夸大问题
cv2.泛光填充(前景清晰,无,种子,(0,0,0),
loDiff=(10,10,10),upDiff=(10,10,10))
带锐化(
sharp_前台
):不进行锐化:
注:
该示例使用
loDiff=(10,10,10)
和upDiff=(10,10,10)
进行演示。尝试保持较低的值。控制照明条件或使用更先进的技术,如深度学习实例分割或对象检测。中级高级技术可以是超像素分割形状匹配、关键点匹配,但通常所有这些技术都有一些边缘化以及它们的优点。如果你的背景总是像那些rwo图像一样好,你可以尝试梯度或边缘提取,并对结果进行聚类以估计对象。然后你可以使用凸包来估计轮廓。嗨,米卡,谢谢你的提示。我不确定深入学习能有多大帮助,因为没有办法知道工具的形状。这不像识别一张脸或一辆汽车,你可以训练一个网络。在我的情况下,工具可以是任何性质的(如果我错了,请纠正我)。至于你的第二点,是的,背景总是一样好,它是一张普通的A4纸。事实上,我正在使用cv2.ConnectedComponents SwithStats图像来识别不同的对象,但同样,这将根据光线条件切割出部分对象。深度学习可以很好地概括,并且是在不受控制的现实生活中工作良好的少数技术之一。您当前的方法非常简单,因此您必须控制环境,或者找到一种方法来自动规范化图像或参数(根据图像),或者进行大量假设。请发布您的代码,谢谢。