神奇的图像修复技术-使用opencv图像处理
神奇的图片修复技术-使用opencv图像处理欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导
神奇的图像修复技术-使用opencv图像处理
一、效果展示
1.使用opencv进行图像修复,对一张简单缺损的图片进行修复的效果如下图所示:
| 修复前 | 修复后 |
|---|---|
![]() |
![]() |
2.对一个被模糊的网格线污染了的图片进行修复的效果如下图所示:
| 修复前 | 修复后 |
|---|---|
![]() |
![]() |
原始图片和完整代码在github项目中:
https://github.com/zhmc/inpaint_demo
二、使用的opencv函数inpaint基本介绍
C++中cv::inpaint函数声明如下:
void inpaint( const Mat& src, const Mat& inpaintMask,
Mat& dst, double inpaintRange, int flags );
第一个参数src是要修复的图像,Mat类型的,为8位单通道或者三通道图像的输入图像;
第二个参数inpaintMask为修复掩膜,为8位单通道图像,其中非零像素表示要修补的区域;
第三个参数dst为修复后的结果,它和src图像类型是一样的;
第四个参数inpaintRange是修复参考圆半径,double类型的,修复算法会使用需要修复点邻近的圆形区域,参照这个圆形区域内的像素点进行插值修复;
最后一个参数flags是修复算法类别,int型的,为修补方法的标识符,两种修补方法分别 cv::INPAINT_NS 或cv::INPAINT_TELEA
python中
dst = cv2.inpaint(src, inpaintMask, inpaintRadius, flags[, dst] )
参数含义和C++中一致;
修复后的图像作为返回值;
flags为cv2.INPAINT_NS或cv2.INPAINT_TELEA
三、简单缺损图片的修复过程
这是一张被白色印记毁损的图片,用于演示图像修复的最简单流程。
首先,需要对图像进行灰度处理。
src_image = cv2.imread("data/1.jpg")
gray_image = cv2.cvtColor(src_image, cv2.COLOR_RGB2GRAY)
然后,进行二值化。
# 二值化
ret, binary = cv2.threshold(gray_image, 245, 255, cv2.THRESH_BINARY)
得到二值化图像如下图:
观察图片发现,存在较多噪点,并不是需要提取的待修复区域。
使用形态学开操作,去除噪点。
# 进行开操作,去除噪音小点。
kernel_3X3 = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
binary_after_open = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel_3X3)
得到过滤后的图片。
这张图片就可以作为图像修复的掩膜。使用修复函数。
restored = cv2.inpaint(src_image, binary_after_open, 9, cv2.INPAINT_NS)
这样就完成了一个缺损图片的修复。
四、复杂缺损图片的修复过程
但是上面完成修复的图片是一个很简单的场景,如果是真实世界一些复杂的缺损图片的修复就比较麻烦了。
如下图,这是一个被网格线毁损的图片,它是由于在相册里被某个网格图案粘合太长时间附上去的。
1.转换灰度图
src_image = cv2.imread("data/2.jpg")
gray_image = cv2.cvtColor(src_image, cv2.COLOR_RGB2GRAY)
2.观察灰度图,发现网格线位于图像中的谷线。 使用Sobel滤波器,对X轴方向和Y轴方向做梯度提取。
# 对X轴方向和Y轴方向做Sobel梯度提取
sX = cv2.Sobel(gray_image, cv2.CV_64F, 1, 0, ksize=3, borderType=cv2.BORDER_REPLICATE)
sY = cv2.Sobel(gray_image, cv2.CV_64F, 0, 1, ksize=3, borderType=cv2.BORDER_REPLICATE)
# 去除负值。这是为了提取单边界,否则网格线两边的梯度绝对值都较大,形成双边缘。
sX[sX < 0] = 0
sY[sY < 0] = 0
3.对sobel梯度值进行exp(0.2), 0.2会稍微减弱峰值。然后进行竖直方向的积分投影。
eX = (sX ** .2).sum(axis=0)
eY = (sY ** .2).sum(axis=1)
Sobel梯度提取图和积分投影图:
4. 构建掩膜。观察图片,发现390是一个划分eX的阈值,480是一个划分eY的阈值
A2 = src_image.copy()
mask = np.zeros(A2.shape[:2], dtype=np.uint8)
mask[eY > 480, :] = 1
mask[:, eX > 390] = 1
A2[mask.astype(bool), :] = 255
将掩模图绘在原图上,查看效果
5. 使用修复算法
restored = cv2.inpaint(src_image, mask, 1, cv2.INPAINT_NS)
最终修复效果如图所示:
原始图片和完整代码在github项目中:
https://github.com/zhmc/inpaint_demo
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐






所有评论(0)