[英]Python Image Processing - How to remove certain contour and blend the value with surrounding pixels?
我正在做一个带有深度图像的项目。 但是我的深度相机存在噪音和像素读取失败的问题。 有一些点和轮廓(尤其是边缘)的值为零。 如何忽略这个零值并将其与周围的值混合? 我已经尝试过dilation
和erosion
(变形图像处理),但我仍然无法获得正确的组合。 它确实消除了一些噪音,但我只需要在所有点上去掉零
图片示例:
零值是最深的蓝色(我正在使用颜色图)
为了说明我想要做什么,请参考这张糟糕的油漆图:
我想摆脱黑点(例如黑色值为 0 或某个值),并将其与周围混合。 是的,我可以使用np.where
或类似的 function 对现场进行本地化,但我不知道如何混合它。 也许要应用过滤器? 我需要在 stream 中执行此操作,所以我需要一个相当快的过程,也许 10-20 fps 就可以了。 先感谢您!
更新:
除了补漆还有其他方法吗? 我已经寻找了各种修复,但我不需要像修复那样复杂。 我只需要将它与简单的线条、曲线或形状和一维混合。 我认为inpaint是一种矫枉过正。 此外,我需要它们足够快以用于视频 stream 10-20 fps,甚至更好。
这是在 Python/OpenCV 中执行此操作的一种方法。
使用中值滤波来填补空洞。
输入:
import cv2
import numpy as np
import math
# read image
img = cv2.imread('spots.png')
# convert to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# threshold
mask = cv2.threshold(gray,0,255,cv2.THRESH_BINARY)[1]
# erode mask to make black regions slightly larger
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
mask = cv2.morphologyEx(mask, cv2.MORPH_ERODE, kernel)
# make mask 3 channel
mask = cv2.merge([mask,mask,mask])
# invert mask
mask_inv = 255 - mask
# get area of largest contour
contours = cv2.findContours(mask_inv[:,:,0], cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
contours = contours[0] if len(contours) == 2 else contours[1]
perimeter_max = 0
for c in contours:
perimeter = cv2.arcLength(c, True)
if perimeter > perimeter_max:
perimeter_max = perimeter
# approx radius from largest area
radius = int(perimeter_max/2) + 1
if radius % 2 == 0:
radius = radius + 1
print(radius)
# median filter input image
median = cv2.medianBlur(img, radius)
# apply mask to image
img_masked = cv2.bitwise_and(img, mask)
# apply inverse mask to median
median_masked = cv2.bitwise_and(median, mask_inv)
# add together
result = cv2.add(img_masked,median_masked)
# save results
cv2.imwrite('spots_mask.png', mask)
cv2.imwrite('spots_mask_inv.png', mask_inv)
cv2.imwrite('spots_median.png', median)
cv2.imwrite('spots_masked.png', img_masked)
cv2.imwrite('spots_median_masked.png', median_masked)
cv2.imwrite('spots_removed.png', result)
cv2.imshow('mask', mask)
cv2.imshow('mask_inv', mask_inv )
cv2.imshow('median', median)
cv2.imshow('img_masked', img_masked)
cv2.imshow('median_masked', median_masked)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
阈值图像作为掩码:
反转掩码:
中值滤波图像:
蒙面图像:
蒙面中值滤波图像:
结果:
也许使用 NaN 调整的高斯滤波器足够好且足够快? 当您将零点/黑点视为 NaN 时,此方法也适用于较大的黑色区域。
# import modules
import matplotlib.pyplot as plt
import numpy as np
import skimage
import skimage.filters
# set seed
np.random.seed(42)
# create dummy image
# (smooth for more realisitc appearance)
size = 50
img = np.random.rand(size, size)
img = skimage.filters.gaussian(img, sigma=5)
# create dummy missing/NaN spots
mask = np.random.rand(size, size) < 0.02
img[mask] = np.nan
# define and apply NaN-adjusted Gaussian filter
# (https://stackoverflow.com/a/36307291/5350621)
def nangaussian(U, sigma=1, truncate=4.0):
V = U.copy()
V[np.isnan(U)] = 0
VV = skimage.filters.gaussian(V, sigma=sigma, truncate=truncate)
W = 0*U.copy()+1
W[np.isnan(U)] = 0
WW = skimage.filters.gaussian(W, sigma=sigma, truncate=truncate)
return VV/WW
smooth = nangaussian(img, sigma=1, truncate=4.0)
# do not smooth full image but only copy smoothed NaN spots
fill = img.copy()
fill[mask] = smooth[mask]
# plot results
vmin, vmax = np.nanmin(img), np.nanmax(img)
aspect = 'auto'
plt.subplot(121)
plt.title('original image (white = NaN)')
plt.imshow(img, aspect=aspect, vmin=vmin, vmax=vmax)
plt.axis('off')
plt.subplot(122)
plt.title('filled image')
plt.imshow(fill, aspect=aspect, vmin=vmin, vmax=vmax)
plt.axis('off')
OpenCV和Skimage中的图像修复太慢,这是一个已知问题。 我不认为你可以在不深入算法的情况下加快速度。
如果您真的对“传统的”(即没有深度学习的)修复算法感兴趣并准备实施一个,我强烈建议您查看soupault/scikit-inpaint#4 。 该算法在视觉上与双谐波方法的性能相同或更好,并且一旦正确转换为代码,即使对于大图像也可以非常快。
事实上,从性能的角度来看,双谐波修复的实现远非最佳。 当前版本非常简单,因为它是以 nD 输入支持为主要目标而编写的。
对实施的可能改进包括但不限于:
bilaplacians 的预生成(atm 它是为每个被屏蔽的像素分别计算的)
掩码分割成独立的连接区域(构建了atm单个巨大的矩阵)
Cythonization(不确定我是否能够在 Cython atm 中编写 nD 代码)
更快的 linsolve
并行实施。
作为一种中间解决方案,可以尝试为 2D(+color) 实现更快的 Cythonized 版本(还要考虑上述其他点),因为它预计是最常见的用例。
如果您只是在寻找“快速且足够好”的修复方法,请查看 GitHub 上众多基于深度学习的修复解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.