主题

在本节中我们将描述一种称为图像修复的区域填充算法。

这种图片修复算法的作用是可以通过使用OpenCV模块来进行图片上异常划痕或斑点等噪线、噪点的修复,而且代码相对其他的图片修复算法而言要稍微简单一些。(最后效果类似于PhotoShop)

图像修复算法是计算机仿人视觉中的一类基本算法,算法的主要目标是填充图像或视频内的区域,该区域主要使用二进制掩模来进行标识,填充通常根据需要我们来填充的区域周边的边界信息来完成。

图像修复的最常见应用是用来恢复照片中产生的一些小的噪线等,当然图像修复还可以用于删除图像中的小的不需要的对象,这种时候只需要我们把不需要的对象看作一种特殊的噪线即可。

在本节中,关于图片的修复,我们会简要的讨论在机器仿人视觉中较为常用的两种修复算法,分别是INPAINT_NS和INPAINT_TELEA。

INPAINT_NS

这里我们依靠图片来进行这种算法的说明,原图如下图左边所示,现在假设我们图片破损了,破损区域如下图右

边所示。

那么我们现在的问题就是我们该如何填补这个黑色区域的问题。现在我们想要的一条约束黑线,他应该有两个这样的特征:

(1)我们想要这样一条约束黑线,约束黑线的起点是从下边缘进入黑色区域,然后从上边沿处脱离黑色区域。

(2)曲线的右边的区域应该为蓝色,而约束黑线的左边区域应该为白色。

通过以上简述的两个约束条件,我们可以得知的是,这种算法要求我们得到的约束黑线有以下两个特点:保留原有的边缘特征,以及一条能够继续在平滑区域中传播颜色信息的约束黑线。

这个算法的创始人通过建立了一个偏微分方程来更新具有上述约束的区域内的图像强度,算法比较复杂,所以我们就不再在这里进行过多的描述了,这里给出对应的论文的网站。

INPAINT_TELEA

第二种算法与之前那种算法的区别在于:它不使用拉普拉斯算子作为平滑度的估计(前面那种算法需要使用拉普拉斯算子来进行平滑度的估计)。这种算法使用的是:依靠像素的已知图像邻域边上的加权平均值来对已经破损的图像进行补绘。这里的补绘指的是用我们已知的邻域像素和图像梯度来帮忙估计要修复的像素的颜色,通过这种估计可以来进行图像的修复。

提出这种算法的论文如下所示,感兴趣的读者可以自行前往如下网址。

cv2.inpaint函数

在我们进行图像的修复的时候,我们需要使用到的函数为:cv2.inpaint,这个函数的语法如下所示:

dst = cv2.inpaint(src, inpaintMask, inpaintRadius, flags)

·src:我们要修复的图像。

·inpaintMask:二进制的掩码,这里指的是我们要修复的像素。

·inpaintRadius:表示我们要对图片进行修复的半径。

·flags:我们要选用的修复算法,这里我们使用的主要有上面说过的两种:

(1)cv2.INPAINT_NS

(2)cv2. INPAINT_TELEA

·dst:最后我们得到的结果图像。

INPAINT_NS修复

首先我们先来进行cv2.INPAINT_NS的修复,我们的原图如代码下方图中最左边的所示,示例代码如下所示。

import numpy as np

import cv2

class Sketcher:

def __init__(self, windowname, dests, colors_func):

self.prev_pt = None

self.windowname = windowname

self.dests = dests

self.colors_func = colors_func

self.dirty = False

self.show()

cv2.setMouseCallback(self.windowname, self.on_mouse)

def show(self):

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

cv2.imshow(self.windowname + ": mask", self.dests[1])

# 设置相对应的鼠标事件

def on_mouse(self, event, x, y, flags, param):

pt = (x, y)

if event == cv2.EVENT_LBUTTONDOWN:

self.prev_pt = pt

elif event == cv2.EVENT_LBUTTONUP:

self.prev_pt = None

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()

def main():

# 读取照片

img = cv2.imread("1.jpg")

# 如果没有打开图片,直接返回

if img is None:

return

# 创造一个原图的复制出来,方便后面显示

img_mask = img.copy()

# 创建一个黑色的掩膜

inpaintMask = np.zeros(img.shape[:2], np.uint8)

sketch = Sketcher('image', [img_mask, inpaintMask], lambda : ((255, 255, 255), 255))

while True:

ch = cv2.waitKey()

if ch == ord('q'):

break

if ch == ord('n'):

# 使用图像修复算法

res = cv2.inpaint(src=img_mask, inpaintMask=inpaintMask, inpaintRadius=3, flags=cv2.INPAINT_NS)

cv2.imshow('output', res)

if ch == ord('r'):

img_mask[:] = img

inpaintMask[:] = 0

sketch.show()

print('Completed')

if __name__ == '__main__':

main()

cv2.destroyAllWindows()

运行上述代码,我们先左键拖动我们的鼠标,通过鼠标事件来在我们的图片上进行画图(将我们需要修复的部分用白色部分覆盖)我们鼠标拖动的白色部分其实也就是我们的掩膜,因此会显示在mask的窗口上,(每次进行算法前必须都提前准备好与我们的噪线相对应的掩膜)

通过鼠标拖动将损坏区域完全覆盖以后,我们可以按下q键来进行画布的退出,也可以按下n键来进行NS算法的画面修补,如果需要再查看原图,也按下r键来查看;下图中间的部分表示的是已经被我们画出的白色掩膜包含的图片,下图右侧的图片表示的是通过NS修补后的图片。

可以看到的是,经过NS算法修复之后,原本图中上方的蓝色划线字样已经完全消失了。

注意:如果在运行程序时将噪线完全覆盖后运行NS算法还有残留部分,那么可以增大在原图中残留部分周边的白色部分的面积,通过增大掩膜的方式增大计算,从而做到更好效果的NS修改算法效果。

INPAINT_TELEA修复

在上面的例子中我们已经对有“划痕”的图片进行了INPAINT_NS算法的修复,下面我们来尝试INPAINT_TELEA的修复算法并将两种算法来进行一些简单的比较。我们还是采用上图来进行修复,示例代码如下所示。

import numpy as np

import cv2

class Sketcher:

def __init__(self, windowname, dests, colors_func):

self.prev_pt = None

self.windowname = windowname

self.dests = dests

self.colors_func = colors_func

self.dirty = False

self.show()

cv2.setMouseCallback(self.windowname, self.on_mouse)

def show(self):

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

cv2.imshow(self.windowname + ": mask", self.dests[1])

# 设置相对应的鼠标事件

def on_mouse(self, event, x, y, flags, param):

pt = (x, y)

if event == cv2.EVENT_LBUTTONDOWN:

self.prev_pt = pt

elif event == cv2.EVENT_LBUTTONUP:

self.prev_pt = None

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()

def main():

# 读取照片

img = cv2.imread("1.jpg")

# 如果没有打开图片,直接返回

if img is None:

return

# 创造一个原图的复制出来,方便后面显示

img_mask = img.copy()

# 创建一个黑色的掩膜

inpaintMask = np.zeros(img.shape[:2], np.uint8)

sketch = Sketcher('image', [img_mask, inpaintMask], lambda : ((255, 255, 255), 255))

while True:

ch = cv2.waitKey()

if ch == ord('q'):

break

if ch == ord('t'):

res=cv2.inpaint(src=img_mask,inpaintMask=inpaintMask,inpaintRadius=3, flags=cv2.INPAINT_TELEA)

cv2.imshow('output', res)

if ch == ord('r'):

img_mask[:] = img

inpaintMask[:] = 0

sketch.show()

print('Completed')

if __name__ == '__main__':

main()

cv2.destroyAllWindows()

与前面一样的,这里我们可以使用q键来进行画布的退出,可以按下t键来进行TELEA算法的画面修补,按下r键可以查看我们的原图,运行上述代码后,与之前NS算法一样的操作之后,我们可以得到如下两张图所示的效果,其分别对应:掩膜图以及TELEA修复图。

这里我们可以通过尝试分别在两块代码中加入以下代码显示各自修复的时间来进行比较两种修复算法的修复快慢。

Start=time.time()

#中间过程

......

print(time.time()-Start)

这个时候我们可以发现的是,就上面两个例子而言NS算法所耗费的时间略比TELEA算法的时间要短一些,当然这也与我们选择的掩膜有关:可以看到的是我们在NS中画出的白色掩膜比起我们在TELEA中的掩膜面积要小一些,这个也对我们代码中NS算法最后得出较快的运行结果有关。

感兴趣的读者可以自行对这两种算法进行时间上的比较,就理论上而言,TELEA算法在与NS达到相同的效果的前提下,其所消耗的时间应该要比NS算法要短一些,但我们在实际运用的过程中,我们往往会发现的是,NS算法更能节约一些时间,且在相同计算量下做得比TELEA算法更好。

注意:TELEA算法因为基于的原理是快速匹配算法(Fast Marching Method based),所以我们常常也称其为FMM算法。

总结

(前一段日子在赶着写书,被催稿(吐)导致的本系列咕咕咕了,之后可能还会咕,但是还是会尽量快的更新,谢谢大家支持啦!)

python可以做工业视觉_(Python)从零开始,简单快速学机器仿人视觉Opencv—运用四:图像损痕修复...相关推荐

  1. (Python)从零开始,简单快速学机器仿人视觉Opencv---运用四:图像损痕修复

    教程: 博主之前写了24节关于使用OpenCV的教程,欢迎大家阅读: (Python)从零开始,简单快速学机器仿人视觉Opencv-第一节:OpenCV的图像读取显示及保存 (Python)从零开始, ...

  2. (Python)从零开始,简单快速学机器仿人视觉Opencv---运用二:物体检测

    教程: 博主之前写了22节关于使用OpenCV的教程,欢迎大家阅读: (Python)从零开始,简单快速学机器仿人视觉Opencv-第一节:OpenCV的图像读取显示及保存 (Python)从零开始, ...

  3. (Python)从零开始,简单快速学机器仿人视觉Opencv---运用一:快速截取图像中指定单个物体

    教程: 博主之前写了21节关于使用Opencv的教程,欢迎大家阅读: (Python)从零开始,简单快速学机器仿人视觉Opencv-第一节:OpenCV的图像读取显示及保存 (Python)从零开始, ...

  4. (Python)从零开始,简单快速学机器仿人视觉Opencv---运用三:物体运动跟踪

    教程: 博主之前写了23节关于使用OpenCV的教程,欢迎大家阅读: (Python)从零开始,简单快速学机器仿人视觉Opencv-第一节:OpenCV的图像读取显示及保存 (Python)从零开始, ...

  5. python如何做四象图_(Python)从零开始,简单快速学机器仿人视觉Opencv—第十四节:图像梯度...

    事先说明 图像梯度原理:简单来说就是求导 OpenCV提供了三种不同的梯度滤波器,或者说高通滤波器:Sobel,Scharr和Laplacian.Sobel和Scharr是求一阶或二阶导数.Schar ...

  6. python八角图形绘制_(Python)从零开始,简单快速学机器仿人视觉Opencv—第四节:OpenCV处理鼠标事件...

    准备工作 使用工具:Python3.5 涉及包:cv2 numpy 涉及函数 函数:cv2.setMouseCallback() 任务开始 简单的程序,在图片上双击过的位置绘制一个圆圈 任务1.创建鼠 ...

  7. python配置opencv最简单_(Python)从零开始,简单快速学机器仿人视觉Opencv—第二节:OpenCV的视频操作...

    准备工作 使用库: numpy opencv 任务1 用摄像头捕获视频 cv2.VideoCapture() :0为默认计算机默认摄像头,1可以更换来源: import numpy as np imp ...

  8. (Python)从零开始,简单快速学机器仿人视觉Opencv---第九节:颜色空间转换

    事先准备 使用工具Python3.5 使用包cv2,numpy 涉及函数 cv2.cvtColor() cv2.inRange() 任务1:转换颜色空间   在 OpenCV 中有 超过150 种进行 ...

  9. (Python)从零开始,简单快速学机器仿人视觉Opencv---第十九节:关于轮廓的函数

    1 凸缺陷   找到凸缺陷 hull=cv2.convexHull(cnt,returnPoints=False) defects=cv2.convexityDefects(cnt,hull)   它 ...

最新文章

  1. python语法教程-Python语法教程总结规范
  2. CNCF 宣布 TUF 毕业 | 云原生生态周报 Vol. 33
  3. BZOJ 2655 calc (组合计数、DP、多项式、拉格朗日插值)
  4. Elasticsearch-搜索并获取数据
  5. 一文搞定Qt读写excel以及qt读写xml数据
  6. Exchange Server 的防火墙开放端口
  7. linux和android学习,android学习笔记
  8. 罗永浩又提西门子:希望网友帮介绍西门子管理层
  9. mysql密码加强_MySQL密码增强插件
  10. 《大师谈游戏设计——创意与节奏》【笔记二】
  11. badboy使用简介
  12. js判断数组key是否存在
  13. UWB定位系统场景的分析
  14. SQLite3使用详解之二
  15. 最彻底的玩客云绝育方法-避免持续读写损伤硬盘和资料
  16. deepin更新失败_更新失败
  17. 第14章-1~3 法兰接头预紧力密封接触分析周期对称 (介绍、局部柱坐标系建立、周期对称的设置) Beta选项打开、 cyclic region、symmetry
  18. 大白菜u盘可以装linux,一个U盘搞定mac的安装 可以安装win7
  19. 常用工具软件-官网下载地址
  20. 运行uniapp项目,提示uniapp依赖插件还未加载,请稍后重试

热门文章

  1. 佳能TS3180打印机连接wifi
  2. Java的编程之旅——输出
  3. 学习笔记(6):Google开发专家带你学 AI:入门到实战(Keras/Tensorflow)(附源码)-实战:电影评论分类模型
  4. 苹果iMessage垃圾信息泛滥:运营商难涉及
  5. 小学文化学导数——极限
  6. 数据库基准测试标准 TPC-C or TPC-H or TPC-DS
  7. 动态规划:砍死怪兽的概率
  8. 会成为3G时代的一些经典
  9. 优美抒情钢琴曲《kiss the rain》
  10. 怎么避免下载流氓软件,误下载后怎么处理