图像修复

很多时候遇到受损的图片我们需要利用机器视觉的手段对其进行修复,opencv中提供了inpaint函数实现了这一功能。

1.先来看一个例子

  • 首先读入图片:
import numpy as np
import cv2 as cv
img = cv.imread('src.jpg')
polluted = cv.imread('polluted.png',0)


分别是原图和污损图。

  • 下面我们使用阈值分割来得到污损图的掩膜:
_,mask = cv2.threshold(cv2.cvtColor(pllute,cv2.COLOR_BGR2GRAY),10,255,cv2.THRESH_BINARY_INV)
cv2.imshow('mask',mask);cv2.waitKey(1000);cv2.destroyAllWindows()

得到如下的掩膜图;

  • 最后调用函数对图像进行修复
dst = cv.inpaint(polluted ,mask,3,cv.INPAINT_TELEA)
cv2.imshow('inpainted',dst)
cv2.imshow('src',src)
cv2.waitKey(0)
cv2.destroyAllWindows()


左图是修复图,右图是原图。
img from Animade

2.参数解析

图像修复函数inpaint主要参数如下:

inpaint(src, inpaintMask, inpaintRadius, flags[, dst]) -> dst
.   这是一个利用领域信息恢复图像的函数.
.
.   src 为输入图像
.   inpaintMask 为单通道二值图掩膜,其中非零位置为需要修复的位置
.   dst  为输出图像,与输入大小等同 .
.   inpaintRadius  为领域大小,在修复时考虑周围像素的范围
.   修复方法的flag:
.   -   **INPAINT_NS** [Navier-Stokes based方法](https://ieeexplore.ieee.org/document/990497)
.   -   **INPAINT_TELEA** [Alexandru Telea方法](https://www.tandfonline.com/doi/abs/10.1080/10867651.2004.10487596)
.

3.原理实现

Navier-Stokes based方法
论文摘要:这种方法利用了经典流体动力学中的思想,将等照度线连续的从待修补区域周围传播到修补区域中去。主要的观点在于将图像强度视为了二维不可压缩流的流函数(stream function),其中图像强度的拉普拉斯量为流体的旋量、并将它通过矢量场定义的流函数输运到待修补区域。最终得到的算法会通过连续照度来匹配受损区域的梯度矢量。它直接依赖于流体力学中的纳维叶斯托克斯方程,具有较强的理论和数值优势。

Fast Marching Method
这篇文章提出的是基于快速行进算法的图像修复,其主要思想则是基于沿图像梯度传播平滑估计器。图像的平滑主要来自于受损图像领域的加权平均。同时将缺失的区域视为水平集,并用FMM(Fast Marching Method)来描述为图像信息的传播。

Image Prior
目前深度学习方法对于图像修复也有了很大的进展


ref:
1.OpencvDoc:https://docs.opencv.org/3.4/df/d3d/tutorial_py_inpainting.html
2.Deeplearning:https://arxiv.org/pdf/1711.10925.pdf
3.Code:https://github.com/atiyo/deep_image_prior
4.Fast Marching:https://blog.csdn.net/seamanj/article/details/51991067

Image Inpainting

Goal

In this chapter,

  • We will learn how to remove small noises, strokes etc in old photographs by a method called inpainting
  • We will see inpainting functionalities in OpenCV.

Basics

Most of you will have some old degraded photos at your home with some black spots, some strokes etc on it. Have you ever thought of restoring it back? We can’t simply erase them in a paint tool because it is will simply replace black structures with white structures which is of no use. In these cases, a technique called image inpainting is used. The basic idea is simple: Replace those bad marks with its neighbouring pixels so that it looks like the neigbourhood. Consider the image shown below (taken from Wikipedia):

Several algorithms were designed for this purpose and OpenCV provides two of them. Both can be accessed by the same function, cv2.inpaint()

First algorithm is based on the paper “An Image Inpainting Technique Based on the Fast Marching Method” by Alexandru Telea in 2004. It is based on Fast Marching Method. Consider a region in the image to be inpainted. Algorithm starts from the boundary of this region and goes inside the region gradually filling everything in the boundary first. It takes a small neighbourhood around the pixel on the neigbourhood to be inpainted. This pixel is replaced by normalized weighted sum of all the known pixels in the neigbourhood. Selection of the weights is an important matter. More weightage is given to those pixels lying near to the point, near to the normal of the boundary and those lying on the boundary contours. Once a pixel is inpainted, it moves to next nearest pixel using Fast Marching Method. FMM ensures those pixels near the known pixels are inpainted first, so that it just works like a manual heuristic operation. This algorithm is enabled by using the flag, cv2.INPAINT_TELEA.

Second algorithm is based on the paper “Navier-Stokes, Fluid Dynamics, and Image and Video Inpainting” by Bertalmio, Marcelo, Andrea L. Bertozzi, and Guillermo Sapiro in 2001. This algorithm is based on fluid dynamics and utilizes partial differential equations. Basic principle is heurisitic. It first travels along the edges from known regions to unknown regions (because edges are meant to be continuous). It continues isophotes (lines joining points with same intensity, just like contours joins points with same elevation) while matching gradient vectors at the boundary of the inpainting region. For this, some methods from fluid dynamics are used. Once they are obtained, color is filled to reduce minimum variance in that area. This algorithm is enabled by using the flag, cv2.INPAINT_NS.

Code

We need to create a mask of same size as that of input image, where non-zero pixels corresponds to the area which is to be inpainted. Everything else is simple. My image is degraded with some black strokes (I added manually). I created a corresponding strokes with Paint tool.

import numpy as np
import cv2img = cv2.imread('messi_2.jpg')
mask = cv2.imread('mask2.png',0)dst = cv2.inpaint(img,mask,3,cv2.INPAINT_TELEA)cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

See the result below. First image shows degraded input. Second image is the mask. Third image is the result of first algorithm and last image is the result of second algorithm.

Additional Resources

  1. Bertalmio, Marcelo, Andrea L. Bertozzi, and Guillermo Sapiro. “Navier-stokes, fluid dynamics, and image and video inpainting.” In Computer Vision and Pattern Recognition, 2001. CVPR 2001. Proceedings of the 2001 IEEE Computer Society Conference on, vol. 1, pp. I-355. IEEE, 2001.
  2. Telea, Alexandru. “An image inpainting technique based on the fast marching method.” Journal of graphics tools 9.1 (2004): 23-34.

Exercises

  1. OpenCV comes with an interactive sample on inpainting, samples/python2/inpaint.py, try it.
  2. A few months ago, I watched a video on Content-Aware Fill, an advanced inpainting technique used in Adobe Photoshop. On further search, I was able to find that same technique is already there in GIMP with different name, “Resynthesizer” (You need to install separate plugin). I am sure you will enjoy the technique.

图像修补就是使用坏点周围的像素取代坏点,这样它看起来和周围像素就比较像了。

OpenCV 使用函数 cv2.inpaint() 来实施。 
第一个算法是根据 Alexandru_Telea 在 2004 发表的文章实现的。它是基于快速行进算法的。以图像中一个要修补的区域为例。算法从这个区域的边界开始向区域内部慢慢前进,首先填充区域边界像素。它要选取待修补像素周围的一个小的邻域,使用这个邻域内的归一化加权和更新待修复的像素值。权重的选择是非常重要的。对于靠近带修复点的像素点,靠近正常边界像素点和在轮廓上的像素点给予更高的权重当一个像素被修复之后,使用快速行进算法(FMM)移动到下一个最近的像素。FMM 保证了靠近已知(没有退化的)像素点的坏点先被修复,这与手工启发式操作比较类似。可以通过设置标签参数为 cv2.INPAINT_ TELEA 来使用此算法。 
第二个算法是根据 Bertalmio,Marcelo,Andrea_L.Bertozzi, 和 Guillermo_Sapiro在 2001 年发表的文章实现的。这个算法是基于流体动力学并使用了偏微分方程。基本原理是启发式的。它首先沿着正常区域的边界向退化区域的前进(因为边界是连续的,所以退化区域非边界与正常区域的边界应该也是连续的)。它通过匹配待修复区域中的梯度向量来延伸等光强线(isophotes,由灰度值相等的点练成的线)。为了实现这个目的,作者是用来流体动力学中的一些方法。完成这一步之后,通过填充颜色来使这个区域内的灰度值变化最小。可以通过设置标签参数为 cv2.INPAINT_NS 来使用此算法。

第一幅图是退化的输入图像,第二幅是掩模图像。第三幅是使用第一个算法的结果,最后一副是使用第二个算法的结果。 

一、图像修复简介

图像修复是图像复原中的一个重要内容,其目的是利用图像现有的信息来恢复丢失的信息。可用于旧照片中丢失信息的恢复,视频文字去除以及视频错误隐藏等。简言之,图像修复就是对图像上信息缺损区域进行信息填充的过程,其目的就是为了对有信息缺损的图像进行复原,并且使得观察者无法察觉到图像曾经缺损或者已经修复

     图像修复技术简单来说,就是利用那些被破坏区域的边缘,即是边缘的颜色和结构,繁殖和混合到损坏的图像中,来进行修复图像

目前存在两大类图像修复技术:一类是用于修复小尺度缺损的数字图像修补(inpainting)技术。即,利用待修补区域的边缘信息,同时采用一种由粗到精的方法来估计等照度线的方向,并采用传播机制将信息传播到待修补的区域内,以便达到较好的修补效果;另外一类是用于填充图像大块丢失信息的图像补全技术。目前,这一技术分为以下两种方法:一种是基于图像分解的修复方法,其主要思想是将图像分解为结构部分和纹理部分。其中,结构部分用inpainting的技术来修复,而纹理部分则采用纹理合成的方法来填充。另一种方法是用基于块的纹理合成技术来填充丢失的信息,其主要思想是:首先从待修补区域的边界上选取一个像素点,同时以该点为中心,根据图像的纹理特征,选择大小合适的纹理块,然后在待修补区域的周围寻找与之最相近的纹理匹配块来替代该纹理块。近几年来,利用纹理合成来修复大块丢失信息的图像合成技术得到了相当的研究,也取得了一定的成果。需要提醒的是,图像修复技术是一种对视觉感知过程的学习和理解。它是一个不确定问题,没有唯一解的存在,解的合理性取决于视觉系统的接受程度。换言之,为了达到较好的视觉效果,我们必须让修复效果更加符合视觉感知的特性,使得图像看起来浑然一体,没有修改过的痕迹。

二、原理介绍

opencv提供了2中方法,这里主要说的是INPAINT_TELEA

参考文献为Alexandru Telea于2004年发表于Journal of GraphicTools上An ImageInpainting Technique Based On the Fast Marching Method”也称为FMM算法

如何修复一个像素点的?

参考上图,Ω区域是待修复的区域;δΩ指Ω的边界);要修复Ω中的像素,就需要计算出新的像素值来代替原值。

现在假设p点是我们要修复的像素。以p为中心选取一个小邻域B(ε),该邻域中的点像素值都是已知的(只要已知的)。(这个ε就是opencv函数中参数 inpaintRadius)

现在假设p点是我们要修复的像素。以p为中心选取一个小邻域B(ε),该邻域中的点像素值都是已知的(只要已知的)。(这个ε就是opencv函数中参数 inpaintRadius)

q为 Bε(p)中的一点,由q点计算P的灰度值公式如下

显然,我们需要的是用邻域Bε(p)中的所有点计算p点的新灰度值。显然,各个像素点所起的作用应该是不同的,也就引入了权值函数来决定哪些像素的值对新像素值影响更大,哪些比较小。采用下面的公式(公式2):

这里的w(p, q)就是权值函数,是用来限定邻域中各像素的贡献大小的。

w(p, q) = dir(p, q) ·dst(p, q) · lev(p, q)

其中,d0和 T0分别为距离参数和水平集参数,一般都取为 1。方向因子 dir(p,q)保证了越靠近法线方向 N = ?T的像素点对 p点的贡献最大;几何距离因子 dst(p,q)保证了离 p点越近的像素点对p点贡献越大;水平集距离因子lev(p,q)保证了离经过点 p的待修复区域的轮廓线越近的已知像素点对点 p的贡献越大。

三、图像修复应用

基于OpenCV的两种去水印方案

1. 基于 inpaint 方法(网上的方法,处理质量较低)

  • 算法理论:基于Telea在2004年提出的基于快速行进的修复算法(FMM算法),先处理待修复区域边缘上的像素点,然后层层向内推进,直到修复完所有的像素点
  • 处理方式:由ui人员制作出黑底白色水印且相同位置的水印蒙版图(必须单通道灰度图),然后使用inpaint方法处理原始图像,具体使用时可把水印区放粗,这样处理效果会好点

需要带水印的图,和该图一样大小的的黑底白色水印且位置相同的水印图

    test_dir = 'xxx'mask_dir = 'xxx'save_dir ='xxx'src = cv2.imread(rental_dir)mask = cv2.imread(wm_dir, cv2.IMREAD_GRAYSCALE)dst = cv2.inpaint(src, mask, 3, cv2.INPAINT_TELEA)cv2.imwrite(save_dir, dst)

2. 基于像素的反色中和(处理质量较高)

参考自ps去水印原理,通过一张白底的反色水印图来中和原图水印

需要到水印的图,和该图一样大小的白底棕色(128,128,128)的水印且位置相同的水印图,128的效果比较好

    test_dir = 'xxx'mask_dir = 'xxx'save_dir ='xxx'src = cv2.imread(test_dir)mask = cv2.imread(mask_dir)save = numpy.zeros(src.shape, numpy.uint8)for row in range(src.shape[0]):for col in range(src.shape[1]):for channel in range(src.shape[2]):if mask[row, col, channel] == 0:val = 0else:reverse_val = 255 - src[row, col, channel]val = 255 - reverse_val * 256 / mask[row, col, channel]if val < 0:val = 0save[row, col, channel] = valcv2.imwrite(save_dir, save)

第二种方面明显比第一种要好,但是水印的边角处理不好,可以先用二在用一,效果会更好

参考自https://my.oschina.net/u/2400083/blog/732321

python 快速行进 算法 图像修补相关推荐

  1. 快速行进算法(fast_marching_kroon)的matlab代码

    快速行进算法(fast_marching_kroon)的matlab代码 快速行进算法用于求解程函方程得到走时场,源代码转载于link 文章目录 快速行进算法(fast_marching_kroon) ...

  2. 一个简单的MATLAB脚本——快速行进算法(FMM))

    一个简单的MATLAB脚本--快速行进算法(FMM) 介绍快速行进算法(FMM)的简单MATLAB脚本,不到20行代码实现快速行进算法的运算结果,而且计算速度非常快.给了两个实例模型来说明计算结果. ...

  3. 3D 快速行进算法(Fast Marching Method in 3D case)

    Intro 快速行进算法用来高效求解程函方程(Eikonal Equation) F ∥ ∇ U ∥ = 1 F\Vert\nabla U\Vert = 1 F∥∇U∥=1, F为速度场函数( Vel ...

  4. python快速幂算法解决大数取模

    1.前置性质 模运算的性质 [(a mod n)×(b mod n)] mod n = (a×b) mod n 指数可以拆分成二进制的形式,如9拆分成 1001 根据二进制的计算,1001 = ((1 ...

  5. Python快速幂算法实现

    求a的n次方 def fastpower(a,n):ans = 1while n:if n&1:ans *= aa *= an >>= 1return ans 求a的n次方对b取余 ...

  6. python 查找算法_python快速查找算法应用实例

    文实例讲述了Python快速查找算法的应用,分享给大家供大家参考. 具体实现方法如下: import random def partition(list_object,start,end): rand ...

  7. 图像处理:基于cv2.inpaint()图像修补

    前言 今天我们将学习如何通过一种"修复"的方法消除旧照片中的小噪音,笔画等.当然,经过我的测试你也可以将其用于削弱混杂了其他的颜色的图像. 实验背景 大多数人家都会有一些旧的的旧化 ...

  8. cv2图像修补inpaint

    本篇博客主要介绍cv2模块中的图像修补inpaint. cv2中主要提供了两种进行图像修补的算法: 1.基于快速行进算法 cv2.INPAINT_TELEA. 2.基于流体动力学并使用了偏微分方程 c ...

  9. 使用Python和OpenCV在图像之间执行超快速的颜色转换

    使用Python和OpenCV在图像之间执行超快速的颜色转换 1. 效果图 2. 原理 2.1 颜色转移算法 2.2 步骤 2.3 算法改进 3. 源码 参考 这篇博客将介绍如何使用Python和Op ...

最新文章

  1. 《Java核心技术 卷Ⅱ 高级特性(原书第10版)》一3.7.5 使用StAX写出XML文档
  2. 《阿里巴巴编码规范(JAVA)》学习认证考后感
  3. python gevent 协程
  4. boost::replace_copy相关的测试程序
  5. 限制外来计算机访问,准入网关|网络准入控制|非法接入检测|限制非法访问解决方案...
  6. 新版chrome调整开发者工具位置方式改变
  7. php大数组查找算法,PHP简单的数组查找算法分享
  8. 为什么c语言软件调试不出来,急急急……求指导,程序调试不出来
  9. nusoap传递数组对象
  10. Tomcat学习总结(7)——Tomcat与Jetty比较
  11. java 二进制 归属权限_java 二进制 权限管理
  12. 《区块链技术指南》摘要
  13. 计算机硬件的五大部分由谁提出,存储程序原理是由谁于1946年提出的,它明确了计算机硬件组成的五大部分() - 问答库...
  14. 前端点击图片将跳出显示框显示图片
  15. html制作网易云音乐登录系统,JavaScript实现[网易云音乐Web站登录窗口]拖拽功能...
  16. 项目一:SORM基本框架之基本思路
  17. Host Context配置
  18. 进程的状态和转换 三态模型和五态模型
  19. iframe框架的使用
  20. 在阿里云上打造属于你自己的APEX完整开发环境 (安装CentOS, Tomcat, Nginx)

热门文章

  1. php 函数 变量,PHP函数中变量的说明
  2. anaconda怎么使用编写python_怎样使用anaconda编辑python
  3. 实现php实现价格的排序,php 数组动态添加实现代码(最土团购系统的价格排序)_PHP教程...
  4. 为什么我还没 Fix 你的 Issue
  5. 福布斯:2016年物联网预测和市场估算总结
  6. 记linux与Windows之间实现文件实时同步的方案
  7. hdu 5534(dp)
  8. Vbox在Linux 5上安装Oracle 11gR2 RAC
  9. lucene 索引流程整理笔记
  10. oracle cpu分配,CPU 分配 - Oracle VM Server for SPARC 2.0 管理指南