首页 > 解决方案 > 如何去除单个较大轮廓中的细小区域?

问题描述

我试图想出一种方法来从一个较大的轮廓中去除更小的细节,我可以在图像中找到这些细节。

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)

输入图像:

在此处输入图像描述

输出图像:

在此处输入图像描述

期望的输出:

在此处输入图像描述

所有图像都会发生这种情况。

我尝试过使用腐蚀和膨胀,但每张图像的效果都不同。

我想知道是否有一种方法可以找到两个未连接的接近像素,形成一个分支,然后连接这两个像素。

在我通过的每张图像中,我都会有一个巨大的轮廓,因此不存在重叠或更小但有用的轮廓的问题。

标签: pythonopencvimage-processingcomputer-visionopencv-python

解决方案


我能够通过以下方式摆脱“分支状”微小和不需要的区域:(参考所提供的代码)

- 创建“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 

推荐阅读