我想删除图像上的水平黑线:
为此,我插值了每一列像素的RGB值。
黑线消失了,但我认为优化这个功能是可能的:
def fillMissingValue(img_in):
img_out = np.copy(img_in)
#Proceed column by column
for i in tqdm(range(img_in.shape[1])):
col = img_in[:,i]
col_r = col[:,0]
col_g = col[:,1]
col_b = col[:,2]
r = interpolate(col_r)
g = interpolate(col_g)
b = interpolate(col_b)
img_out[:,i,0] = r
img_out[:,i,1] = g
img_out[:,i,2] = b
return img_out
def interpolate(y):
x = np.arange(len(y))
idx = np.nonzero(y)
interp = interp1d(x[idx],y[idx],fill_value="extrapolate" )
return interp(x)
if __name__ == "__main__":
img = cv2.imread("lena.png")
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, (1024,1024))
start = time.time()
img2 = fillMissingValue(img)
end = time.time()
print("Process time: {}".format(np.round(end-start,3)))
你有什么想法吗?我想通过识别黑线的位置来做一个预处理步骤。因此只能插值相邻的像素。但我不认为它更快
目前的结果:
发布于 2022-02-16 23:38:43
interp1d
不是很有效。
正如@ChristophRackwitz在注释中建议的那样,您可以检测行的位置并使用OpenCV提供的修补方法:
img = cv2.imread('lena.jpg')
# Locate the relatively black lines
threshold = 25
lineIdx = np.where(np.mean(img, axis=(1,2)) < threshold)
# Perform inpainting on the located lines
mask = np.zeros(img.shape[:2], dtype=np.uint8)
mask[lineIdx] = 255
# Actual inpainting.
# Note: using 2 or 1 instead of 3 make the computation
# respectively ~2 and ~4 time faster on my machine but
# the result is not as beautiful with 3.
img2 = cv2.inpaint(img, mask, 3, cv2.INPAINT_NS)
计算部分在我的机器上需要87 ms,而您的代码需要342 ms。请注意,由于JPEG压缩,结果不太好。你可以画出邻里的线条。因此,为了获得更好的结果,代价是计算速度更慢(在我的机器上大约慢了2.5 )。
另一种解决方案是自己在Numpy中执行插值:
%%time
# Locate the relatively black lines
threshold = 25
lineIdx = np.where(np.mean(img, axis=(1,2)) < threshold)[0]
lineIdxSet = set(lineIdx)
img2 = img.copy()
start, end = None, None
interpolate = False
for i in range(img.shape[0]+1):
if i in lineIdxSet:
if start is None:
start = i
end = i
else:
if not (start is None):
assert not (end is None)
# The first lines are black
if start <= 0:
i0, i1 = end+1, end+1
# The last lines are black
elif end >= img.shape[0]-1:
i0, i1 = start-1, start-1
# usual case
else:
i0, i1 = start-1, end+1
# The full image is black
if i0 < 0 or i1 >= img.shape[0]:
continue
end = min(end, img.shape[0]-1)
# Actual linear interpolation (of a bloc of lines)
coef = np.linspace(0, 1, end-start+3)[1:-1].reshape(-1, 1)
l0 = img[i0].reshape(-1)
l1 = img[i1].reshape(-1)
img2[start:end+1] = (coef * l0 + (1.0-coef) * l1).reshape(-1, img.shape[1], 3)
start, end = None, None
这段代码在我的机器上只占用5毫秒。结果应该类似于您的原始代码之一,除了它工作逐行,而不是一列一列,并且检测不是独立于每个颜色通道。注意,当大型线条块是黑色时,修补方法会提供更漂亮的结果。
https://stackoverflow.com/questions/71129710
复制相似问题