轮廓检测:减少opencv/python图像上的眩光
我正在为下面的图像进行轮廓检测,但是由于闪电条件,在图像显示眩光的地方检测不完整。我试图删除它们,以获得更好的轮廓检测 这是原始图像 这是灰度+阈值图像,在该图像上运行cv2.connectedComponentsWithStats来检测对象。我已经把我需要减少暴露的区域围起来了。(因为我使用的是反向阈值二元INV过滤器,所以这些区域显示为黑色) 如下文所示,检测到的对象区域不完整,cv2.connectedComponentsWithStats不会检测到对象的完整区域 当然,在裁剪轮廓组件上计算的轮廓本身也是错误的: 因此,轮廓本身当然是错误的: 以下是我迄今为止所做的工作:轮廓检测:减少opencv/python图像上的眩光,python,opencv,image-processing,Python,Opencv,Image Processing,我正在为下面的图像进行轮廓检测,但是由于闪电条件,在图像显示眩光的地方检测不完整。我试图删除它们,以获得更好的轮廓检测 这是原始图像 这是灰度+阈值图像,在该图像上运行cv2.connectedComponentsWithStats来检测对象。我已经把我需要减少暴露的区域围起来了。(因为我使用的是反向阈值二元INV过滤器,所以这些区域显示为黑色) 如下文所示,检测到的对象区域不完整,cv2.connectedComponentsWithStats不会检测到对象的完整区域 当然,在裁剪轮廓组
def getFilteredContours(image, minAreaFilter=20000) -> np.array:
ret = []
ctrs,_ = cv2.findContours(image, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
ctrs = sorted(ctrs, key=cv2.contourArea, reverse=True)
for i, c in enumerate(ctrs):
# Calculate the area of each contour
area = cv2.contourArea(c)
if area < minAreaFilter:
break
ret.append(c)
return ret
birdEye = cv2.imread(impath)
gray = cv2.cvtColor(birdEye, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)
threshImg = cv2.threshold(gray, 180, 255, cv2.THRESH_BINARY_INV)[1]
(numLabels, labels, stats, centroids) = cv2.connectedComponentsWithStats(
threshImg, 4, cv2.CV_32S)
#then for each identified component we extract the component and get the contour
filteredIdx = getFilteredLabelIndex(stats)
for labelId in filteredLabelId:
componentMask = (labels == i).astype("uint8") * 255
ctrs, _ = cv2.findContours(image, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
ctrs = sorted(ctrs, key=cv2.contourArea, reverse=True)
ctr = max(ctrs, key=cv2.contourArea)
cv2.drawContours(birdEye, [cntrs], -1, (255, 0, 255), 3)
cv2.imshow("original contour", birdEye)
cv2.waitKey(0)
cv2.destroyAllWindows()
def getFilteredContours(图像,minAreaFilter=20000)->np.array:
ret=[]
ctrs,=cv2.findContours(图像,cv2.RETR\u树,cv2.CHAIN\u近似值\u无)
ctrs=已排序(ctrs,键=cv2.1,反向=真)
对于枚举中的i、c(CTR):
#计算每个轮廓的面积
面积=cv2。轮廓面积(c)
如果面积<最小面积过滤器:
打破
ret.append(c)
回程网
birdEye=cv2.imread(impath)
灰色=cv2.CVT颜色(鸟瞰,cv2.COLOR\u BGR2GRAY)
灰色=cv2.高斯模糊(灰色,(5,5,0)
threshImg=cv2.阈值(灰色,180255,cv2.THRESH\u BINARY\u INV)[1]
(数字标签、标签、统计信息、质心)=cv2.connectedComponentsWithStats(
阈值,4,cv2.CV_32S)
#然后对每个识别出的分量进行提取,得到轮廓
filteredix=getFilteredLabelIndex(统计)
对于filteredLabelId中的labelId:
组件掩码=(标签==i).astype(“uint8”)*255
ctrs,=cv2.findContours(图像,cv2.RETR\u树,cv2.CHAIN\u近似值\u无)
ctrs=已排序(ctrs,键=cv2.1,反向=真)
ctr=最大值(ctrs,键=cv2.轮廓面积)
cv2.绘制等高线(birdEye,[cntrs],-1,(255,0255),3)
cv2.imshow(“原始轮廓”,birdEye)
cv2.等待键(0)
cv2.destroyAllWindows()
欢迎提出任何建议
谢谢
Pat我的建议是在cv2中使用膨胀和侵蚀功能(或关闭功能) 如果使用
cv2.deflate
功能,白色区域比现在大
相反,如果使用cv2.correase
功能,白色区域比现在小
此迭代消除了黑色区域的噪声
闭合功能是先膨胀后侵蚀
参见https://docs.opencv.org/master/d9/d61/tutorial_py_morphological_ops.html
您可以先使用填充背景
cv2.floodFill
应用您的示例图像可获得良好的效果。结果很好,因为背景相对均匀。
floodFill
使用颜色信息,而其他算法仅使用亮度。背景有轻微的亮度梯度,“泛光填充”算法处理得很好 您可以使用以下阶段:
- 将所有(暗)值(例如低于10)替换为10-避免对象内部存在黑色像素的问题
- 使用
填充黑色背景。cv2.floodFill
使用左上角作为“背景”种子颜色(假设像素[10,10]不在对象中) - 转换为灰度
- 应用阈值-将零以上的所有像素转换为255
- 使用“打开”(形态学操作)删除小的异常值
- 找到轮廓线
import cv2
import numpy as np
birdEye = cv2.imread(r"C:\Rotem\tools.jpg")
# Replace all (dark) values below 10 with 10 - avoiding issues where there are black pixels inside an object
birdEye = np.maximum(birdEye, 10)
foreground = birdEye.copy()
seed = (10, 10) # Use the top left corner as a "background" seed color (assume pixel [10,10] is not in an object).
# Use floodFill for filling the background with black color
cv2.floodFill(foreground, None, seedPoint=seed, newVal=(0, 0, 0), loDiff=(5, 5, 5, 5), upDiff=(5, 5, 5, 5))
# Convert to Grayscale
gray = cv2.cvtColor(foreground, cv2.COLOR_BGR2GRAY)
# Apply threshold
thresh = cv2.threshold(gray, 1, 255, cv2.THRESH_BINARY)[1]
# Use opening for removing small outliers
thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)))
# Find contours
cntrs, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# Draw contours
cv2.drawContours(birdEye, cntrs, -1, (255, 0, 255), 3)
# Show images for testing
cv2.imshow('foreground', foreground)
cv2.imshow('gray', gray)
cv2.imshow('thresh', thresh)
cv2.imshow('birdEye', birdEye)
cv2.waitKey()
cv2.destroyAllWindows()
前台:
birdEye
输出:轮廓检测功能将二值图像作为输入。你知道如何获得二值图像吗?是的,我确实更新了我的问题。我建议你看看漫射光,这样你的图像可以减少眩光。这看起来很棒,有没有办法平滑轮廓?它们看起来有点粗糙。你的图像右边和下方的寄生虫轮廓怎么样,我能过滤掉吗?嗯,这里有些奇怪,我按原样运行了你的代码,我的前景图像看起来不是黑色的。你错过什么了吗?奇怪。。。有时发布的图像会被修改。尝试从您的帖子下载图像,并将其用作输入。原始图像中的寄生虫轮廓为黑色。我们可以把它裁剪出来,也可以遮盖它。平滑边缘可能是一项挑战。形态学手术可能会有所帮助