opencv图片操作之图片修复
1.实验目的
熟悉opencv读入图片,以及图片的修复.
2.实验设备
安装了python和pychrm的电脑一台.
3.实验内容
包含图片的导入和显示、修复.
4.实验原理
在实际应用中,我们的图像常常会被噪声腐蚀,这些噪声或是镜头上的灰尘或水滴,或是旧照片的划痕,或者是图像遭到人为的涂画(比如马赛克)或者图像的部分本身已经损坏。
修复图像的原理就是利用那些已经被破坏的区域的边缘, 即边缘的颜色和结构,根据这些图像留下的信息去推断被破坏的信息区的信息内容,然后对破坏区进行填补 ,以达到图像修补的目的。
图1.1.1 原理
如图所示,是图像中待修复的区域,是待修复区域的边界,是该边界上的任意一点。在点周围的图像已知区域内部,选择一个以为尺度的领域。那么,的像素值可以由领域内部的像素值来近似计算得到。我们首先来考虑灰度图(彩图可以类似计算)。当尺度参
足够小的时候,给定点的像素值以及的梯度值
,那么点的一阶估计:
那么,点的像素值可以由下面的式子计算得到:
式中是权重分布函数,为了对整个待修复区域进行修复,我们需要不断迭代上面的式子,并逐渐收缩待修复区域的边界,直到整个区域都被修复为止。也就是说,每次迭代修复的过程都仅处理待修复区域的边界像素,逐步迭代,使得待修复区域逐渐收缩变小。
其中,和分别为距离参数和水平集参数,一般都取为 1。方向因子保证了越靠近法线方向 N = ?T的像素点对 p点的贡献最大;几何距离因子 保证了离p点越近的像素点对p点贡献越大;水平集距离因子保证了离经过点p的待修复区域的轮廓线越近的已知像素点对点p的贡献越大。
Opencv中图像修补技术由inpaint函数实现,基本步骤是先修复区域边缘再逐步向内推进修复,可以用来清除照片灰尘、划痕或者从静态图像及视频中除去不需要的物体。
我们需要构建mask掩模图像也就是二值化图像,用threshold函数(俗称二值化操作)把需要清除的内容变成白色,对二值化图像消除噪声(腐蚀膨胀操作),腐蚀操作的函数为cv2.erode(),参数有mask图像,核,迭代次数;膨胀操作也是一样(cv2.dilate),这样能增强修复效果,最后inpaint函数进行修复。需要的参数:原图;腐蚀膨胀后的mask图;修复算法。
修复算法,有两种:INPAINT_NS(基于Navier-Stokes的方法) 和INPAINT_TELEA。
第一种算法基于Alexandru Telea于2004年发表的“基于快速行进方法的图像修复技术”。它基于快速行进方法。考虑图像中要修复的区域。算法从该区域的边界开始,然后进入区域内,逐渐填充边界中的所有内容。它需要在邻近的像素周围的一个小邻域进行修复。该像素由邻居中所有已知像素的归一化加权和代替。选择权重是一个重要的问题。对于靠近该点的那些像素,靠近边界的法线和位于边界轮廓上的像素,给予更多的权重。一旦像素被修复,它将使用快速行进方法移动到下一个最近的像素。 FMM确保首先修复已知像素附近的像素,这样它就像手动启发式操作一样工作。使用标志cv2.INPAINT_TELEA启用此算法。
第二种算法基于Navier-Stokes。该算法基于流体动力学并利用偏微分方程。基本原则是heurisitic。它首先沿着已知区域的边缘行进到未知区域(因为边缘是连续的)。它继续等照片(连接具有相同强度的点的线,就像轮廓连接具有相同高度的点一样),同时在修复区域的边界处匹配渐变矢量。为此,使用来自流体动力学的一些方法。获得颜色后,填充颜色以减少该区域的最小差异。使用标志cv2.INPAINT_NS启用此算法。
两种算法修复效果都还不错,但是都需要事先准备修复模板mask,也就是inpaint Mask 这个参数。
二值化操作:
图像的二值化就是将图像上的像素点的灰度值设置为0或255,这样将使整个图像呈现出明显的黑白效果。在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。OpenCV中提供了函数threshold()函数实现图像二值化。
cv2.threshold(img,130,255,cv2.THRESH_BINARY)
参数:
img:源图像,可以为8位的灰度图,也可以为32位的彩色图像。(两者由区别)。
第二第三个参数:阈值范围。
第四个参数:阈值类型,可以具体类型如下:
表1.1.1 阈值类型表
THRESH_BINRY | |
---|---|
THRESH_BINARY_INV | |
THRESH_TRUNC | |
THHRESH_TOZERO | |
THRESH_TOZERO_INV | |
THRESH_MASK | |
THRESH_OTSU | Flag,use,Otsu algorithm to choose the optimal threshold value |
THRESH_TRIANGLE | Flag,use,Tnangle algorithm to choose the optimal thresold value |
图1.1.2 阈值类型的变化过程
阈值类型生成的效果如下所示:
表1.1.1 效果图
原图 | |
---|---|
cv2.THRESH_BINARY | |
cv2.THRESH_BINARY_INV | |
cv2.THRESH_TRUNC | |
cv2.THRESH_TOZERO | |
cv2.THRESH_TOZERO_INV | |
cv2.THRESH_OTSU | |
cv2.THRESH_TRIANGLE |
腐蚀:
粗略的说,腐蚀可以使目标区域范围“变小”,其实质造成图像的边界收缩,可以用来消除小且无意义的目标物。式子表达为:
该式子表示用结构B腐蚀A,需要注意的是B中需要定义一个原点,(而B的移动的过程与卷积核移动的过程一致,同卷积核与图像有重叠之后再计算一样)当B的原点平移到图像A的像元(x,y)时,如果B在(x,y)处,完全被包含在图像A重叠的区域,(也就是B中为1的元素位置上对应的A图像值全部也为1)则将输出图像对应的像元(x,y)赋值为1,否则赋值为0。
图1.1.3 腐蚀
B依顺序在A上移动(和卷积核在图像上移动一样,然后在B的覆盖域上进行形态学运算),当其覆盖A的区域为[1,1;1,1]或者[1,0;1,1]时,(也就是B中‘1’是覆盖区域的子集)对应输出图像的位置才会为1。
膨胀:
略地说,膨胀会使目标区域范围“变大”,将于目标区域接触的背景点合并到该目标物中,使目标边界向外部扩张。作用就是可以用来填补目标区域中某些空洞以及消除包含在目标区域中的小颗粒噪声。
该式子表示用结构B膨胀A,将结构元素B的原点平移到图像像元(x,y)位置。如果B在图像像元(x,y)处与A的交集不为空(也就是B中为1的元素位置上对应A的图像值至少有一个为1),则输出图像对应的像元(x,y)赋值为1,否则赋值为0。
图1.1.4 膨胀
也就是说无论腐蚀还是膨胀,都是把结构元素B像卷积操作那样,在图像上平移,结构元素B中的原点就相当于卷积核的核中心,结果也是存储在核中心对应位置的元素上。只不过腐蚀是B被完全包含在其所覆盖的区域,膨胀时B与其所覆盖的区域有交集即可。
缩放基本流程:
导入图像-->转成灰度图像-->二值化处理(获得mask图像俗称掩膜图形)-->构建过滤核-->形态学的膨胀腐蚀操作-->inpant函数修复。
总而言之,图像修复技术在一些简单,颜色单调的图像上进行修复得到的而效果是相当好的,而在一些细节或者复杂的部分进行修复,得到的复原图像的效果就比较一般了。比如在一些背景部分进行修复效果都不错,而在边缘细节上的修复就能看出问题了!
5.实验步骤
打开pycharm。
我们右击相应的文件目录,选择new--->点击Python File,然后输入新建的文件名,点击确定,相应的.py文件就建好了,可以进行编写代码了。
opencv的imread()函数能支持各种静态图像文件格式,imread()函数会删除所有alpha通道的信息(透明度)。
Impoert cv2
img=cv2.imread('images\org.png')
将图像转为灰度图像 。
cap=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
对灰度图像进行二值化处理,阈值很重要,需要自己调节到最佳效果。
ret,mask = cv2.threshold(cap,130,255,cv2.THRESH_BINARY)
够造腐蚀膨胀操作的卷积核。
kernel =cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
腐蚀操作。
erosion = cv2.erode(mask, kernel, iterations=1)
对Mask膨胀处理,增加Mask面积。
dilate = cv2.dilate(erosion, kernel, iterations=1)
修复图像,参数:原图;腐蚀膨胀后的mask图;修复算法取的邻域半径用于计算当前像素点的差值;修复算法,有两种:INPAINT_NS 和I NPAINT_TELEA。
dst = cv2.inpaint(img ,dilate,3,cv2.INPAINT_TELEA)
显示原图像和效果图。
cv2.imshow('ai1',img) ##原图 cv2.imshow('ai2',dst) ##修复后的图像 cv2.waitKey(0)
效果可能不太好,需要调节参数到最优效果。
图1.1.5 运行结果