【问题标题】:How to get rid of thin and small areas in a single larger contour?如何去除单个较大轮廓中的细小区域?
【发布时间】:2021-02-24 19:12:04
【问题描述】:

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

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)

输入图像:

输出图像:

期望的输出:

所有图片都会出现这种情况。

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

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

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

【问题讨论】:

  • 比较你的输出和期望的输出:看起来你想要移除的大部分都是凸区域。是否可以创建一个像这样去除凸起部分的遮罩:stackoverflow.com/questions/35226993/…?您的所有目标轮廓都是不同的颜色吗?您可以获取结果并仅在“红色”颜色空间中找到最大的轮廓。
  • @WesH 我试图去除凸出部分,但这些点真的很奇怪,完全不是我们期望的那样。我所有的目标轮廓将主要是单一颜色的对象。
  • 我们无法猜测您想从这张图片中提取什么。
  • @YvesDaoust OP 提供了他/她想要的示例。最后一张图片,“期望的输出”。
  • @vwertuzy 我可以毫无问题地使用(用换行符替换;)提取图像屏幕:img = cv2.imread('in.png', cv2.COLOR_BGR2GRAY); out = np.zeros_like(img); reds = image_vec[:, :, 2]; _, reds = cv2.threshold(reds, 240, 255, cv2.THRESH_TOZERO); cont, _ = cv2.findContours(reds, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE); cv2.drawContours(out, cont, 0, (0, 255, 0), 2, cv2.LINE_AA); cv2.imshow("result", out); cv2.waitKey(0)

标签: python opencv image-processing computer-vision opencv-python


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2014-08-23
    • 2019-12-24
    • 2018-06-16
    • 2020-07-11
    • 1970-01-01
    • 1970-01-01
    • 2018-02-24
    • 2022-01-23
    • 1970-01-01
    相关资源
    最近更新 更多