【问题标题】:Remove Freckles from Simple Binary Image从简单的二值图像中去除雀斑
【发布时间】:2021-05-17 02:55:33
【问题描述】:

我有一个跑步者的以下 NumPy 数组,你可以在这里下载: https://drive.google.com/file/d/1SfIEqGsBV_vA7iP4UjLdklLJlLdDzozL/view?usp=sharing

要显示它,请使用以下代码:

import numpy as np
import matplotlib.pyplot as plt

# load data
data = np.load('running_man.npy')
# plot data
plt.imshow(data)

如您所见,图像中有很多噪点(雀斑)。我想摆脱它并检索跑步者的干净图像。知道怎么做吗?

这是我目前所做的

from skimage import measure
# Find contours at a constant value of 1
contours = measure.find_contours(data, 1, fully_connected='high')

# Select the largest contiguous contour
contour = sorted(contours, key=lambda x: len(x))[-1]

# Create an empty image to store the masked array
r_mask = np.zeros_like(data, dtype='bool')

# Create a contour image by using the contour coordinates rounded to their nearest integer value
r_mask[np.round(contour[:, 0]).astype('int'), np.round(contour[:, 1]).astype('int')] = 1

# Fill in the hole created by the contour boundary
r_mask = ndimage.binary_fill_holes(r_mask)

# Invert the mask since one wants pixels outside of the region
r_mask = ~r_mask

plt.imshow(r_mask)

...但是你可以看到轮廓非常粗糙! 行之有效的是将图像上传到在线 jpg 到 SVG 转换器 -> 这使得线条超级流畅。 ...但我希望能够在 python 中做到这一点。

想法: 我正在寻找可以保持尖角的东西,也许可以检测沿边缘的渐变并仅保持渐变高于某个阈值的点...

【问题讨论】:

  • 这个问题有什么变化吗?
  • @IanChu 是的,我将链接更改为数据。它现在应该可以工作了! (不得不删除旧问题并重新发布,由于某种原因它不起作用)

标签: python-3.x numpy image-processing


【解决方案1】:

对于这个特定的图像,您可以使用 numpy:

import numpy as np
import matplotlib.pyplot as plt

data = np.load('running_man.npy')
data[data > 1] = 0
plt.xticks([])
plt.yticks([])
plt.imshow(data)

【讨论】:

  • 非常感谢您的回答!这个结果相当干净。你能告诉我为什么跑步者周围有一个轻微的绿色边框吗?谢谢。
  • 绿色边框有两个来源。首先,上面的代码不会创建二值图像——原始图像留下了一些像素的中间值。其次,显示图像的函数plt.imshow() 对像素的颜色进行了一些插值,使线条看起来更平滑。您可以使用plt.imshow(data, interpolation="none") 将其关闭,但边缘会更加锯齿状。通常,不可能在二进制光栅图像上获得平滑的边缘。为此,您需要将图像转换为矢量格式,例如 SVG。
  • 非常感谢您的有用评论!是否可以在 python 中将此转换为矢量格式?你知道吗?
  • 我自己没有尝试过,但也许this 会有所帮助。
【解决方案2】:

对于更好地保留角点的方法,我们可以使用中值过滤器,但强制保留角点。

蒙面图像

过滤后的掩码

重新着色

import cv2
import numpy as np

# load image
img = cv2.imread("run.png");
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY);

# make mask
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU);

# median filter
med = cv2.medianBlur(thresh, 11);
med[thresh == 255] = 255;

# inverse filter
mask = cv2.bitwise_not(med);
med = cv2.medianBlur(mask, 3);
med[mask == 255] = 255;

# recolor
color = np.zeros_like(img);
color[med == 0] = (66, 239, 245);
color[med == 255] = (92, 15, 75);

# show
cv2.imshow("colored", color);
cv2.waitKey(0);

【讨论】:

  • 这是一个非常好的方法,但我正在寻找可以保持尖角的东西,即检测沿边缘的渐变并且只保持渐变高于某个阈值的点的东西。 ..
  • 非常感谢!现在好多了!但仍有一些涟漪……您如何看待我建议的渐变方法?
  • 我不知道如何实现这个想法。
  • 好的,不用担心,非常感谢您的回答!
猜你喜欢
  • 2013-04-14
  • 1970-01-01
  • 1970-01-01
  • 2012-07-13
  • 2021-02-28
  • 2015-08-13
  • 1970-01-01
  • 2012-03-08
  • 1970-01-01
相关资源
最近更新 更多