图像修补
Image Inpaintinghomepod
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 cv2
img=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()
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 , 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 发表的⽂章实现的。它是基于快速⾏进算法的。以图像中⼀个要修补的区域为例。算法从这
个区域的边界开始向区域内部慢慢前进,⾸先填充区域边界像素。它要选取待修补像素周围的⼀个⼩的邻域,使⽤这个邻域内的归⼀化加权和
joanne 台湾予更⾼的权
更新待修复的像素值。权重的选择是⾮常重要的。对于靠近带修复点的像素点,靠近正常边界像素点和在轮廓上的像素点给予更⾼的权
当⼀个像素被修复之后,使⽤快速⾏进算法(FMM)移动到下⼀个最近的像素。FMM 保证了靠近已知(没有退化的)像素点的坏点先重。当⼀个像素被修复之后,使⽤快速⾏进算法(FMM)移动到下⼀个最近的像素
被修复,这与⼿⼯启发式操作⽐较类似。可以通过设置标签参数为 cv2.INPAINT_ TELEA 来使⽤此算法。
基于流体动第⼆个算法是根据 Bertalmio,Marcelo,Andrea_L.Bertozzi, 和 Guillermo_Sapiro在 2001 年发表的⽂章实现的。这个算法是基于流体动⼒学并使⽤了偏微分⽅程。基本原理是启发式的。它⾸先沿着正常区域的边界向退化区域的前进(因为边界是连续的,所以退化区域⾮边界⼒学并使⽤了偏微分⽅程
与正常区域的边界应该也是连续的)。它通过匹配待修复区域中的梯度向量来延伸等光强线
匹配待修复区域中的梯度向量来延伸等光强线(isophotes,由灰度值相等的点练成的线)。为
了实现这个⽬的,作者是⽤来流体动⼒学中的⼀些⽅法。完成这⼀步之后,通过填充颜⾊来使这个区域内的灰度值变化最⼩。可以通过设置标
签参数为 cv2.INPAINT_NS 来使⽤此算法。
第⼀幅图是退化的输⼊图像,第⼆幅是掩模图像。第三幅是使⽤第⼀个算法的结果,最后⼀副是使⽤第⼆个算法的结果。
⼀、图像修复简介
图像修复是图像复原中的⼀个重要内容,其⽬的是利⽤图像现有的信息来恢复丢失的信息。可⽤于旧照⽚中丢失信息的恢复,视频⽂字去除以及视频错误隐藏等。简⾔之,图像修复就是对图像上信息缺损区域进⾏信息填充的过程,其⽬的就是为了对有信息缺损的图像进⾏复原,并且使得观察者⽆法察觉到图像曾经缺损或者已经修复
图像修复技术简单来说,就是利⽤那些被破坏区域的边缘,即是边缘的颜⾊和结构,繁殖和混合到损
坏的图像中,来进⾏修复图像
⽬前存在两⼤类图像修复技术:⼀类是⽤于修复⼩尺度缺损的数字图像修补(inpainting)技术。即,利⽤待修补区域的边缘信息,同时采⽤⼀种由粗到精的⽅法来估计等照度线的⽅向,并采⽤传播机制将信息传播到待修补的区域内,以便达到较好的修补效果;另外⼀类是⽤于填充图像⼤块丢失信息的图像补全技术。⽬前,这⼀技术分为以下两种⽅法:⼀种是基于图像分解的修复⽅法,其主要思想是将图像分解为结构部分和纹理部分。其中,结构部分⽤inpainting的技术来修复,⽽纹理部分则采⽤纹理合成的⽅法来填充。另⼀种⽅法是⽤基于块的纹理合成技术来填充丢失的信息,其主要思想是:⾸先从待修补区域的边界上选取⼀个像素点,同时以该点为中⼼,根据图像的纹理特征,选择⼤⼩合适的纹理块,然后在待修补区域的周围寻与之最相近的纹理匹配块来替代该纹理块。近⼏年来,利⽤纹理合成来修复⼤块丢失信息的图像合成技术得到了相当的研究,也取得了⼀定的成果。需要提醒的是,图像修复技术是⼀种对视觉感知过程的学习和理解。它是⼀个不确定问题,没有唯⼀解的存在,解的合理性取决于视觉系统的接受程度。换⾔之,为了达到较好的视觉效果,我们必须让修复效果更加符合视觉感知的特性,使得图像看起来浑然⼀体,没有修改过的痕迹。
⼆、原理介绍
如何修复⼀个像素点的?
经典玄幻小说排行榜
参考上图,Ω区域是待修复的区域;δΩ指Ω的边界);要修复Ω中的像素,就需要计算出新的像素值来代替原值。赞美西湖的古诗
显然,我们需要的是⽤邻域Bε(p)中的所有点计算p点的新灰度值。显然,各个像素点所起的作⽤应该是不同的,也就引⼊了权值函数来决定哪些像素的值对新像素值影响更⼤,哪些⽐较⼩。采⽤下⾯的公式(公式2):
这⾥的w(p, q)就是权值函数,是⽤来限定邻域中各像素的贡献⼤⼩的。
w(p, q) = dir(p, q) ·dst(p, q) · lev(p, q)张翰再次见郑爽2016
其中,d0和 T0分别为距离参数和⽔平集参数,⼀般都取为
对 p点的贡献最⼤;⼏何距离因⼦ dst(p,q)保证了离 p点越近的像素点对
怎么制作动态图片三、图像修复应⽤
基于OpenCV的两种去⽔印⽅案
1. 基于 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 = s(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 = 0
else:
reverse_val = 255 - src[row, col, channel]
val = 255 - reverse_val * 256 / mask[row, col, channel]
if val < 0:
val = 0
save[row, col, channel] = val
cv2.imwrite(save_dir, save)
第⼆种⽅⾯明显⽐第⼀种要好,但是⽔印的边⾓处理不好,可以先⽤⼆在⽤⼀,效果会更好
发布评论