python - 如何去除单个较大轮廓中的细小区域?
问题描述
我试图想出一种方法来从一个较大的轮廓中去除更小的细节,我可以在图像中找到这些细节。
import cv2
import numpy as np
image_vec = cv2.imread('0000000000.eigo.png', cv2.COLOR_BGR2GRAY)
g_blurred = cv2.GaussianBlur(image_vec, (5, 5), 0)
blurred_float = g_blurred.astype(np.float32) / 255.0
edgeDetector = cv2.ximgproc.createStructuredEdgeDetection("model.yml")
edges = edgeDetector.detectEdges(blurred_float) * 255.0
cv2.imwrite('edge-raw.jpg', edges)
def SaltPepperNoise(edgeImg):
count = 0
lastMedian = edgeImg
median = cv2.medianBlur(edgeImg, 3)
while not np.array_equal(lastMedian, median):
zeroed = np.invert(np.logical_and(median, edgeImg))
edgeImg[zeroed] = 0
count = count + 1
if count > 70:
break
lastMedian = median
median = cv2.medianBlur(edgeImg, 3)
edges_ = np.asarray(edges, np.uint8)
SaltPepperNoise(edges_)
cv2.imwrite('edge.jpg', edges_)
#canny edge detection
edges_ = cv2.Canny(edges_, 50, 255)
edges_ = cv2.GaussianBlur(edges_, (5, 5), 0)
cv2.imwrite('edgecanny.png', edges_)
def findSignificantContour(edgeImg):
contours, hierarchy = cv2.findContours(
edgeImg,
cv2.RETR_TREE,
cv2.CHAIN_APPROX_SIMPLE
)
# Find level 1 contours
level1Meta = []
for contourIndex, tupl in enumerate(hierarchy[0]):
# Filter the ones without parent
if tupl[3] == -1:
tupl = np.insert(tupl.copy(), 0, [contourIndex])
level1Meta.append(tupl)
contoursWithArea = []
for tupl in level1Meta:
contourIndex = tupl[0]
contour = contours[contourIndex]
area = cv2.contourArea(contour)
contoursWithArea.append([contour, area, contourIndex])
contoursWithArea.sort(key=lambda meta: meta[1], reverse=True)
largestContour = contoursWithArea[0][0]
return largestContour
contour = findSignificantContour(edges_)
contourImg = np.copy(image_vec)
cv2.drawContours(contourImg, [contour], 0, (0, 255, 0), 2, cv2.LINE_AA, maxLevel=1)
cv2.imwrite('contour.jpg', contourImg)
hh, ww = image_vec.shape[:2]
mask = np.zeros((hh,ww), dtype=np.uint8)
cv2.drawContours(mask, [contour], 0, (255,255,255), cv2.FILLED)
# invert mask so shapes are white on black background
mask_inv = 255 - mask
# create new (blue) background
bckgnd = np.full_like(image_vec, (255,0,0))
# apply mask to image
image_masked = cv2.bitwise_and(image_vec, image_vec, mask=mask)
# apply inverse mask to background
bckgnd_masked = cv2.bitwise_and(bckgnd, bckgnd, mask=mask_inv)
# add together
result = cv2.add(image_masked, bckgnd_masked)
cv2.imwrite("imwrite.png", result)
输入图像:
输出图像:
期望的输出:
所有图像都会发生这种情况。
我尝试过使用腐蚀和膨胀,但每张图像的效果都不同。
我想知道是否有一种方法可以找到两个未连接的接近像素,形成一个分支,然后连接这两个像素。
在我通过的每张图像中,我都会有一个巨大的轮廓,因此不存在重叠或更小但有用的轮廓的问题。
解决方案
我能够通过以下方式摆脱“分支状”微小和不需要的区域:(参考所提供的代码)
- 创建“findSignificantContour()”之前的所有内容保持不变
- 创建“findSignificantContour()”后:
# Call findSignificantContour()
# Create a binary image with contour filled as white and rest black
# Perform erosion on the binary image (will mostly get rid of tinier areas without messing up the actual target)
# make a call to 'findSignificantContour()' and get final contour
# Done! Mask the contour however you want
推荐阅读
- python - 可变数量列的多个条件
- javascript - 循环遍历数组的对象属性并进行比较
- vb.net - 带有 VB.NET 的翘曲矩形面板
- html - 如何防止 NVDA 公布链接的全部内容?
- date - 创建 PySpark 数据框:带年份的月份序列
- python - 如何正确拆分我的训练和推理解码器?
- selenium - 使用 Selenium IDE 被 CSP 阻止的对 eval() 的调用
- java - 如何解决将 Java 8 代码迁移到 Java 11 的依赖项和包问题
- c# - 为什么 webbrowser 在 Visual Studio 2019 中不起作用?
- firebase-storage - 如何在一个文件中描述多个存储桶的 Firebase 存储安全规则?