python - 删除二值阈值图像中具有连接边缘的小破折号

标签 python opencv image-processing

我有一个二值阈值图像,我想从图像中删除小破折号。与圆相连。我的主要重点是提取圆弧。

  • 原始图片:

enter image description here

  • 输出图像为:

enter image description here

最佳答案

因为我们有一个空心形状,所以我采取了懒惰的方法。这是解决问题的平滑方法,相对简单(检查从内部到外部的距离),但它会丢失细节,因为它是在简单闭合形状的假设下运行的。如果这还不够好,请告诉我;有更复杂的方法可以做你想做的事情,可以得到更清晰的结果。

所以基本步骤是这样的:首先,使用 findContours 获取形状的内层和外层(膨胀直到得到两个,在这种情况下我们不需要这样做,因为它已经这样做了)。

然后,计算每个点到另一个轮廓上最近点的距离。从图中您可以很好地了解我们在这里要做什么。破折号是相对统一的图表的明显异常值。这里我手动将截止值设置为 10,但我们可以使用平均值和标准差来自动设置截止值。

enter image description here

一旦我们删除了离群点,我们就可以使用轮廓重新绘制形状。

enter image description here

import cv2
import numpy as np

# returns a smoothed contour
def smoothed(contour, dists, cutoff):
    smooth_con = [];
    for a in range(len(dists)):
        if dists[a] < cutoff:
            smooth_con.append(contour[a]);
    return np.asarray(smooth_con);

# get the distance list for an array of points
def distList(src, other):
    dists = [];
    for point in src:
        point = point[0]; # drop extra brackets
        _, dist = closestPoint(point, other);
        dists.append(dist);
    return dists;

# returns squared distance of two points
def squaredDist(one, two):
    dx = one[0] - two[0];
    dy = one[1] - two[1];
    return dx*dx + dy*dy;

# find closest point (just do a linear search)
def closestPoint(point, arr):
    # init tracker vars
    closest = None;
    best_dist = 999999999;

    # linear search
    for other in arr:
        other = other[0]; # remove extra brackets
        dist = squaredDist(point, other);
        if dist < best_dist:
            closest = other;
            best_dist = dist;
    return closest, best_dist;

# load image
img = cv2.imread("circle_dashed.png");

# make a mask
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY);
mask = cv2.inRange(gray, 0, 100);

# get contours # OpenCV 3.4, if you're using OpenCV 2 or 4, it returns (contours, _)
_, contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE);
print(len(contours)); # we have two, inner and outer, no need to dilate first

# split
one = contours[0];
two = contours[1];

# get distances
one_dists = distList(one, two);
two_dists = distList(two, one);

# dump values greater than 10
smooth_one = smoothed(one, one_dists, 10);
smooth_two = smoothed(two, two_dists, 10);

# draw new contour
blank = np.zeros_like(mask);
cv2.drawContours(blank, [smooth_one], -1, (255), -1);
cv2.drawContours(blank, [smooth_two], -1, (0), -1);

# show
cv2.imshow("Image", img);
cv2.imshow("Smooth", blank);
cv2.waitKey(0);

关于python - 删除二值阈值图像中具有连接边缘的小破折号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66420186/

相关文章:

python - 我必须按周期更改什么?

python - 在python3的模块中导入兄弟文件

c++ - 将图像转换为灰度时在 OpenCV 中出现异常

python - 如何使用OpenCV python自动检测图像的修剪和裁切部分?

python - 将函数应用于包含日期时间的数据框列

python - 为什么我的代码很慢(它还能工作吗)? [欧拉计划 12][Python 3.3]

python - 在具有大量噪声的二值图像上检测圆形形状

python - 如何查找图像中是否存在颜色

image-processing - 高斯滤波器的差异?

opencv - 在二值图像中定位单词