计算机视觉Opencv实验合集——实验一:图像修复

Opencv图像修复的基本概念:

大多数人会在家里放一些旧的退化照片,上面有一些黑点,一些笔画等。你有没有想过恢复它?我们不能简单地在绘画工具中擦除它们,因为它将简单地用白色结构替换黑色结构,这是没有用的。在这些情况下,使用称为图像修复的技术。基本思路很简单:用相邻像素替换那些坏标记,使其看起来像邻域。考虑下面显示的图像

计算机视觉Opencv实验合集——实验一:图像修复_第1张图片

Opencv方法介绍:

 cv.inpaint(src, inpaintMask, inpaintRadius, flags) -> dst

Parameters

src
输入 8 位、16 位无符号或 32 位浮点 1 通道或 8 位 3 通道图像。
inpaintMask
修复蒙版,8 位 1 通道图像。非零像素表示需要上漆的区域。
dst
输出与 src 相同大小和类型的图像。
inpaintRadius
算法考虑的每个点的圆形邻域的半径。
flags
修复方法可以是 cv::INPAINT_NS 或 cv::INPAINT_TELEA

src:通俗来说就是输入图像,一般用cv2.imread读取

inpaintMask:通俗来说就是要修复图片的地方在哪,通常是用cv2.zeros(原图尺寸),需要修复的地方变为255

inpaintRadius:通俗来说就是根据修复算法后,每个像素点作为一个圆心,该参数作为半径展开进行修复

flags:修复算法,截止到目前只有两种:

第一种算法基于 2004 年由 Alexandru Telea 撰写的“基于快速行进方法的图像修复技术”。它基于快速行进方法。考虑图像中要修复的区域。算法从该区域的边界开始,然后进入区域内,逐渐填充边界中的所有内容。它需要在邻域像素周围的一个小邻域进行修复。该像素由邻域中所有已知像素的归一化加权和代替。选择权重是一个重要的问题。对于靠近该点的那些像素,靠近边界的法线和位于边界轮廓上的那些像素,给予更多的权重。一旦像素被修复,它将使用快速行进方法移动到下一个最近的像素。 FMM 确保首先修复已知像素附近的像素,这样它就像手动启发式操作一样工作。使用标志 cv.INPAINT_TELEA 启用此算法。

第二种算法基于 Bertalmio,Marcelo,Andrea L. Bertozzi 和 Guillermo Sapiro 在 2001 年的论文“Navier-Stokes,流体动力学和图像和视频修补”。该算法基于流体动力学和利用偏微分方程。基本原则是 heurisitic。它首先沿着已知区域的边缘行进到未知区域(因为边缘是连续的)。它继续等照片(连接具有相同强度的点的线,就像轮廓连接具有相同高度的点一样),同时在修复区域的边界处匹配渐变矢量。为此,使用来自流体动力学的一些方法。获得颜色后,填充颜色以减少该区域的最小差异。使用标志 cv.INPAINT_NS 启用此算法。

实验详解:

 这一次我们需要自己输入一张图片,通过鼠标在原图画布上通过涂白来提供要修复的点,最后通过使用该函数进行修复,最后与原图进行比较

1.导入需要的库

import numpy as np
import cv2

2. 建立一个画图板

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画线方法
                cv2.line(dst,self.prev_pt,pt,color,5)
            self.dirty = True
            self.prev_pt = pt
            self.show()

3.main函数建立

def main():
    img = cv2.imread(r'')#填入你所实验的图片,下面是一系列基本操作
    img = cv2.resize(img,(512,512))
    img_mask = img.copy()
    inpaintMask = np.zeros(img.shape[:2],np.uint8)#设置mask
    sketch = SKetcher('image',[img_mask,inpaintMask],lambda :((255,255,255),255))#对输入图和mask实时调用
    while True:
        ch = cv2.waitKey()
        if ch == ord('q'):#按键q表示退出
            break
        if ch == ord('n'):#按键n表示修补展示,使用的修补算法是cv2.INPAINT_NS
            res = cv2.inpaint(src = img_mask, inpaintMask = inpaintMask, inpaintRadius=3 , flags=cv2.INPAINT_NS)
            cv2.imshow('output', res)
        if ch == ord('r'):#按键r表示复原,可再重新画图修补
            img_mask[:] = img
            inpaintMask[:] = 0
            sketch.show()

4.最后调用

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

实验效果:

 

最后附上完整代码:

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(r'')
    img = cv2.resize(img,(512,512))
    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()
if __name__ == '__main__':
    main()
    cv2.destroyWindow()

本次Opencv实验展示了计算摄影中的图片修复功能,官方文档请看OpenCV: OpenCV Tutorials

如有错误或遗漏,希望小伙伴批评指正!!!! 

希望这篇博客对你有帮助!!! 

实验二:计算机视觉Opencv实验合集——实验二:特征匹配-CSDN博客

你可能感兴趣的:(Opencv系列,计算机视觉,opencv,人工智能)