OpenCV图像修复cv2.inpaint()的使用

 更新时间:2021年08月10日 16:21:39   作者:程序媛一枚~  
这篇博客将介绍如何通过OpenCV中图像修复的技术——cv2.inpaint() 去除旧照片中的小噪音、笔划等。并提供一个可交互式的程序,感兴趣的可以了解一下

这篇博客将介绍如何通过OpenCV中图像修复的技术——cv2.inpaint() 去除旧照片中的小噪音、笔划等。并提供一个可交互式的程序,利用OpenCV的快速行进和流体力学俩种修复算法对自己的图片进行修复。

大多数人家里都会有一些旧的老化照片,上面有一些黑点、笔划等。如何复原呢?


在绘制工具中擦除:将简单地用无用的白色结构替换黑色结构,效果并不理想。OpenCV中图像修复的技术——基本思想很简单:用相邻像素替换这些坏标记,使其看起来像邻居。

  • cv2.INPAINT_TELEA(Fast Marching Method 快速行进算法)
  • cv2.INPAINT_NS(Fluid Dynamics Method 流体力学算法)
  • OpenCV未实现的:Content-Aware Fill 内容感知填充算法,这是Adobe Photoshop中使用的一种高级修复技术。

cv2.inpaint() 优点:修复效果更加自然;
缺点:修复时需要提供原图以及mask图(与原图一致只有被污染的像素区域有值);

1. 效果图

官方原始图 VS mask图 VS 快速行进算法修复效果 VS 流体力学修复效果 如下:

在这里插入图片描述

接下来用可交互的例子实现自己的图片修复;

原始图 VS Mask图 VS 快速行进算法修复效果图如下:
原始图随意用鼠标左键移动绘制点、线,右键移动绘制矩形来随机增加一些被污染的区域;
并根据原始图生成mask图,mask图是与原始图具有相同大小,并且只有被污染的区域是白色像素的图。可以看到修复效果还是挺好的~

在这里插入图片描述

原始图 VS Mask图 VS 流体力学算法修复效果图如下:
原始图随意用鼠标左键移动绘制点、线,右键移动绘制矩形来随机增加一些被污染的区域;
mask图是与原始图具有相同大小,并且只有被污染的区域是白色像素的图。可以看到修复效果还是挺好的~

在这里插入图片描述

快速行进算法与流体力学算法修复的效果图差别不太大;

2. 原理

  • cv2.INPAINT_TELEA (Fast Marching Method 快速行进算法),对位于点附近、边界法线附近和边界轮廓上的像素赋予更多权重。一旦一个像素被修复,它将使用快速行进的方法移动到下一个最近的像素。
  • cv2.INPAINT_NS(Fluid Dynamics Method 流体力学算法),使用了流体力学的一些方法,基本原则是启发式的。首先沿着边从已知区域移动到未知区域(因为边是连续的)。它在匹配修复区域边界处的渐变向量的同时,继续等高线(连接具有相同强度的点的线,就像等高线连接具有相同高程的点一样)。
  • OpenCV未实现的:Content-Aware Fill 内容感知填充算法,这是Adobe Photoshop中使用的一种高级修复技术。

3. 源码

# 图像修复交互式案例——通过水流填充算法来修复被破坏的图像区域;
# 使用俩种方法进行修复
# cv2.INPAINT_TELEA (Fast Marching Method 快速行进算法),对位于点附近、边界法线附近和边界轮廓上的像素赋予更多权重。一旦一个像素被修复,它将使用快速行进的方法移动到下一个最近的像素。
# cv2.INPAINT_NS 流体力学算法,使用了流体力学的一些方法,基本原则是启发式的,首先沿着边从已知区域移动到未知区域(因为边是连续的)。它在匹配修复区域边界处的渐变向量的同时,继续等高线(连接具有相同强度的点的线,就像等高线连接具有相同高程的点一样)。

# USAGE 
# python inpaint.py D:/deepLearning/py-demo/20210808/images/ml.jpg

# 按下鼠标左键,添加点、线,按下鼠标右键,添加矩形框,以制作被污染的需要修复图像
# 按下空格键:执行修复功能
# 按下r键:重置待修复的mask
# 按下esc键,退出
import cv2
import numpy as np


class Sketcher:
    def __init__(self, windowname, dests, colors_func):
        self.prev_pt = None  # 线起始点
        self.drag_start = None  # 矩形起点
        self.drag_rect = None  # 矩形(左上角,右下角)坐标
        self.windowname = windowname
        self.dests = dests
        self.colors_func = colors_func
        self.dirty = False
        self.drawing = False
        self.mode = False
        self.show()
        cv2.setMouseCallback(self.windowname, self.on_mouse)

    def show(self):
        cv2.imshow(self.windowname, self.dests[0])

    def on_mouse(self, event, x, y, flags, param):
        pt = (x, y)
        if event == cv2.EVENT_LBUTTONDOWN:
            self.prev_pt = pt
            self.drawing = True
        elif event == cv2.EVENT_RBUTTONDOWN:
            # 第一次初始化时设定pt,往后保留上一个点作为矩形起点
            if self.drag_start == None:
                self.drag_start = pt

        if self.prev_pt and flags & cv2.EVENT_FLAG_LBUTTON:
            for dst, color in zip(self.dests, self.colors_func()):
                cv2.line(dst, self.prev_pt, pt, color, 5)
            self.dirty = True
            self.prev_pt = pt
            self.show()

        if self.drag_start and flags & cv2.EVENT_FLAG_RBUTTON:
            xo, yo = self.drag_start
            x0, y0 = np.minimum([xo, yo], [x, y])
            x1, y1 = np.maximum([xo, yo], [x, y])
            self.drag_rect = None
            if x1 - x0 > 0 and y1 - y0 > 0:
                self.drag_rect = (x0, y0, x1, y1)
                for dst, color in zip(self.dests, self.colors_func()):
                    cv2.rectangle(dst, (x0, y0), (x1, y1), color, -1)
                self.dirty = True
                self.drag_start = None
                self.drag_rect = None
                self.show()
            else:
                self.drag_start = pt

    @property
    def dragging(self):
        return self.drag_rect is not None


def main():
    import sys
    try:
        fn = sys.argv[1]
    except:
        fn = 'images/ml_.jpg'

    img = cv2.imread(fn)
    if img is None:
        print('Failed to load image file:', fn)
        sys.exit(1)

    img_mark = img.copy()
    mark = np.zeros(img.shape[:2], np.uint8)
    sketch = Sketcher('img', [img_mark, mark], lambda: ((255, 255, 255), 255))

    while True:
        ch = cv2.waitKey()
        if ch == 27:
            break
        if ch == ord(' '):
            cv2.imshow('mask', mark)
            fmmres = cv2.inpaint(img_mark, mark, 3, cv2.INPAINT_TELEA)
            nsres = cv2.inpaint(img_mark, mark, 3, cv2.INPAINT_NS)
            cv2.imshow('inpaint fmm res', fmmres)
            cv2.imshow('inpaint ns res', nsres)
        if ch == ord('r'):
            img_mark[:] = img
            mark[:] = 0
            sketch.show()

    print('Done')


if __name__ == '__main__':
    main()
    cv2.destroyAllWindows()

参考 https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_photo/py_inpainting/py_inpainting.html#inpainting

到此这篇关于OpenCV图像修复cv2.inpaint()的使用的文章就介绍到这了,更多相关OpenCV图像修复cv2.inpaint()内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python图片转gif方式(将静态图转化为分块加载的动态图)

    Python图片转gif方式(将静态图转化为分块加载的动态图)

    这篇文章主要介绍了Python图片转gif方式(将静态图转化为分块加载的动态图),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • Python验证码截取识别代码实例

    Python验证码截取识别代码实例

    这篇文章主要介绍了Python验证码截取识别代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • python正则表达式re.sub各个参数的超详细讲解

    python正则表达式re.sub各个参数的超详细讲解

    Python 的 re 模块提供了re.sub用于替换字符串中的匹配项,下面这篇文章主要给大家介绍了关于python正则表达式re.sub各个参数的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-07-07
  • python实现word/excel/ppt批量转pdf的示例代码

    python实现word/excel/ppt批量转pdf的示例代码

    这篇文章主要为大家详细介绍了如何利用python实现word、excel、ppt批量转pdf文件,文中的示例代码讲解详细,有需要的小伙伴可以参考下
    2023-09-09
  • python 上下文管理器使用方法小结

    python 上下文管理器使用方法小结

    本文介绍了Python中的上下文管理器,以及如何结合with语句来使用上下文管理器,并且总结了一下with 语句的执行流程。在很多情况下,with语句可以简化代码,并增加代码的健壮性。
    2017-10-10
  • python通过matplotlib生成复合饼图

    python通过matplotlib生成复合饼图

    这篇文章主要介绍了python通过matplotlib生成复合饼图,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-02-02
  • Pycharm sqllite连接使用教程

    Pycharm sqllite连接使用教程

    SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎,这篇文章主要介绍了Pycharm连接sqllite的图文教程,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友可以参考下
    2021-10-10
  • 一小时快速入门Python教程

    一小时快速入门Python教程

    这篇文章主要讲述了几个例子,通过简单的demo让有写代码经验的你能够快速的入门Python的使用,大大提升你的学习效率
    2021-06-06
  • python 协程并发数控制

    python 协程并发数控制

    这篇文章主要介绍了python 协程并发数控制,文章基于python的相关资料展开对主题烦人详细内容介绍,需要的小伙伴可以参考一下
    2022-05-05
  • 使用Python实现为PDF文件添加图章

    使用Python实现为PDF文件添加图章

    在日常工作中,我们经常需要给PDF文档添加一些标识,比如公司的图章或水印图章,所以本文就来为大家详细介绍一下如何使用Python实现为PDF文件添加图章,需要的可以参考下
    2023-11-11

最新评论