繁体   English   中英

仅保留图像中 object 的外边缘

[英]Keep only outer edges of object in an image

我有许多灰度图像,如下左图所示。 我只想保留图像中 object 的外边缘,使用 python,最好是 OpenCV。我试过 OpenCV 腐蚀,然后得到下面正确的图像。 然而,如图所示,object 内部仍然有较亮的区域。我想移除那些区域,只保留外边缘。 实现这一目标的有效方法是什么? 简单的阈值处理是行不通的,因为 object 内部的明亮“条纹”有时可能比边缘更亮。 边缘检测也将检测“主要”边缘内的边缘。

右图——“eroded_areas”是通过以下代码实现的:

   im = cv2.imread(im_path, cv2.IMREAD_GRAYSCALE)
   im_eroded = copy.deepcopy(im)
   kernel_size=3
   kernel = np.ones((kernel_size, kernel_size), np.uint8)
   im_eroded = cv2.erode(im_eroded, kernel, iterations=1)
   eroded_areas = im - im_eroded
   plt.imshow(eroded_areas)

在此处输入图像描述

这是 Python/OpenCV 中的一种方法。

  • 将输入读取为灰度
  • 做大津阈值
  • 获取轮廓并过滤掉非常小的缺陷
  • 在黑色背景上绘制白色轮廓
  • 保存结果

输入:

在此处输入图像描述

import cv2
import numpy as np

# read the input as grayscale
img = cv2.imread('long_blob.png', cv2.IMREAD_GRAYSCALE)

# threshold
thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]

# get contours and filter out small defects
result = np.zeros_like(img)
contours = cv2.findContours(thresh , cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
for cntr in contours:
    area = cv2.contourArea(cntr)
    if area > 20:
        cv2.drawContours(result, [cntr], 0, 255, 1)
        
# save results
cv2.imwrite('long_blob_contours.png', result)

# show results
cv2.imshow('thresh', thresh)
cv2.imshow('result', result)
cv2.waitKey(0)

结果:

在此处输入图像描述

您是否尝试过精明的边缘检测? 它在该算法中有一个非最大抑制步骤,可以去除那些较浅的色调。 我相信 canny 边缘检测器内置于 open cv 但如果没有,这里有它的指南https://en.wikipedia.org/wiki/Canny_edge_detector

打开cv文档https://docs.opencv.org/4.x/da/d22/tutorial_py_canny.html

代号ex

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('messi5.jpg',0)
edges = cv.Canny(img,100,200)
plt.subplot(121),plt.imshow(img,cmap = 'gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(edges,cmap = 'gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])
plt.show()

这应该从第一张图像开始工作,因为灰度逐渐变为更亮和更暗的色调。


如果这仍然不起作用,也许您可以尝试先使用像素级乘法使高音更高而低音更低,然后在执行“im_eroded = cv2.erode(im_eroded, kernel, iterations=1)”步骤后运行阈值.


我只是有一个更简单的解决方案,可能只适用于您当前的示例图像。 因为你已经完美地掩盖了它,你可以把所有不是纯黑色的东西都变成纯白色,然后在它上面运行一个边缘检测器。 它应该能够得到主要轮廓和那些小孔而忽略那些较浅的条纹。


可能有更好的方法来做到这一点,但这是我目前得到的最好的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM