从图像中删除线条用于数字检测的笔记本 python
Removing lines from an image a notebook for digit detection python
我需要在一张方格纸上删除下图中数字的线条,而不会使我的数字变形。没有这个,我的数字检测算法就会失败,因为在感兴趣的区域中存在纸张的划线伪影。
没有任何伪影的更清晰的文件版本
好的,这可能有点复杂,因为笔记本线条的颜色与数字的颜色非常接近,正如您的示例所示。我想,绿色框是您添加的,而不是数据本身的一部分。
您没有说明您使用的是哪个框架,因此我将仅提供一些解决此问题的一般提示。
第一步是一些阈值。您可以使用二进制阈值或更好的一些具有正确大小 windows 的自适应阈值。你将不得不对此进行试验。阈值化的结果将是二值图像。仍然有线条。
第二步将使用形态学操作来清除图像。如果您不确定什么是形态学,请看这个 morphology tutorial.
大约一半的时候,有一些从图像中删除线条的示例。最大的问题是,有些数字还包含水平线。因此,一种选择是使用相当小的形态内核(可能是 3 行和 1 列),因为笔记本线条更细。并更新识别器,以识别甚至扭曲的数字。这应该是可行的,因为所有的数字都会以同样的方式被扭曲。
傅里叶域变换的经典任务。
- 执行傅里叶变换:
import numpy as np
from scipy.misc import imshow, imsave, imread
img = imread("10XIn.jpg")[:,:,:3]
imggray = np.mean(img, -1)
imfft = np.fft.fft2(imggray)
mags = np.abs(np.fft.fftshift(imfft))
angles = np.angle(np.fft.fftshift(imfft))
visual = np.log(mags)
visual2 = (visual - visual.min()) / (visual.max() - visual.min())*255
visual2 将如下所示:
注意穿过中心的对角线 - 它代表您的线条。
现在,我已经为这条线手动创建了掩码,但理想情况下您可以通过编程将其过滤掉
然后我们读取掩码并画出线条:
mask = imread("fftimg4_mask.jpg")[:,:,:3]
mask = (np.mean(mask,-1) > 20)
visual[mask] = np.mean(visual)
然后反转fft:
newmagsshift = np.exp(visual)
newffts = newmagsshift * np.exp(1j*angles)
newfft = np.fft.ifftshift(newffts)
imrev = np.fft.ifft2(newfft)
newim2 = 255 - np.abs(imrev).astype(np.uint8)
imsave("fftimg2.jpg", newim2 )
这里是newim2
当然,您可以在傅立叶 space 中进行更精确的修补,也可以将结果应用回原始图像以保持颜色,但我认为这 post 说明了这个想法。
另一种方法是利用已知结构。
- 去偏斜图像(偏斜可以在opencv中用霍夫变换找到)
- 在行总和中找到峰值
- 物理克隆线上方和线下方的像素
我刚刚为另一个数据集实现了这个,附有示例。这可以进一步调整。
我需要在一张方格纸上删除下图中数字的线条,而不会使我的数字变形。没有这个,我的数字检测算法就会失败,因为在感兴趣的区域中存在纸张的划线伪影。
没有任何伪影的更清晰的文件版本
好的,这可能有点复杂,因为笔记本线条的颜色与数字的颜色非常接近,正如您的示例所示。我想,绿色框是您添加的,而不是数据本身的一部分。
您没有说明您使用的是哪个框架,因此我将仅提供一些解决此问题的一般提示。
第一步是一些阈值。您可以使用二进制阈值或更好的一些具有正确大小 windows 的自适应阈值。你将不得不对此进行试验。阈值化的结果将是二值图像。仍然有线条。
第二步将使用形态学操作来清除图像。如果您不确定什么是形态学,请看这个 morphology tutorial.
大约一半的时候,有一些从图像中删除线条的示例。最大的问题是,有些数字还包含水平线。因此,一种选择是使用相当小的形态内核(可能是 3 行和 1 列),因为笔记本线条更细。并更新识别器,以识别甚至扭曲的数字。这应该是可行的,因为所有的数字都会以同样的方式被扭曲。
傅里叶域变换的经典任务。
- 执行傅里叶变换:
import numpy as np
from scipy.misc import imshow, imsave, imread
img = imread("10XIn.jpg")[:,:,:3]
imggray = np.mean(img, -1)
imfft = np.fft.fft2(imggray)
mags = np.abs(np.fft.fftshift(imfft))
angles = np.angle(np.fft.fftshift(imfft))
visual = np.log(mags)
visual2 = (visual - visual.min()) / (visual.max() - visual.min())*255
visual2 将如下所示:
注意穿过中心的对角线 - 它代表您的线条。
现在,我已经为这条线手动创建了掩码,但理想情况下您可以通过编程将其过滤掉
然后我们读取掩码并画出线条:
mask = imread("fftimg4_mask.jpg")[:,:,:3]
mask = (np.mean(mask,-1) > 20)
visual[mask] = np.mean(visual)
然后反转fft:
newmagsshift = np.exp(visual)
newffts = newmagsshift * np.exp(1j*angles)
newfft = np.fft.ifftshift(newffts)
imrev = np.fft.ifft2(newfft)
newim2 = 255 - np.abs(imrev).astype(np.uint8)
imsave("fftimg2.jpg", newim2 )
这里是newim2
当然,您可以在傅立叶 space 中进行更精确的修补,也可以将结果应用回原始图像以保持颜色,但我认为这 post 说明了这个想法。
另一种方法是利用已知结构。
- 去偏斜图像(偏斜可以在opencv中用霍夫变换找到)
- 在行总和中找到峰值
- 物理克隆线上方和线下方的像素
我刚刚为另一个数据集实现了这个,附有示例。这可以进一步调整。