首页 > 解决方案 > 删除二进制阈值图像中具有连接边缘的小破折号

问题描述

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

在此处输入图像描述

在此处输入图像描述

标签: pythonopencvimage-processing

解决方案


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

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

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

在此处输入图像描述

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

在此处输入图像描述

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);

推荐阅读