OpenCV学习笔记(十七):图像修补:inpaint()

inpaint()函数

使用区域邻域在图像中还原选定区域。

void inpaint( 
InputArray src, 			// 表示要修复的图像,8位三通道或三通道
InputArray inpaintMask,		// 表示修复模板(掩模),8位单通道,非零区域为修补区域
OutputArray dst, 			// 表示修复后的图像
double inpaintRadius, 		// 表示该算法所考虑的需要修补的每个点的圆形邻域的圆形领域半径。
int flags 					// 表示修复使用的算法	
									// CV_INPAINT_TELEA  Alexandru Telea 算法 .
									// CV_INPAINT_NS 基于 Navier-Stokes 方程的算法
);

感觉两种算法修复效果都还不错,但是都需要事先准备修复模板mask,也就是inpaintMask 这个参数。
例子里面用鼠标在图片上划线,划线的同时也更新了mask,而真正应用的时候需要事先设计好这个mask。

示例:

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

#define WINDOW_NAME0 "【原始图参考】"        //为窗口标题定义的宏 
#define WINDOW_NAME1 "【原始图】"        //为窗口标题定义的宏 
#define WINDOW_NAME2 "【修补后的效果图】"        //为窗口标题定义的宏 

Mat srcImage0,srcImage1, inpaintMask;
Point previousPoint(-1,-1);//原来的点坐标

int main()
{
    //输出一些帮助信息
    printf("\n\n\n\t欢迎来到【图像修复】示例程序~\n");
    printf(  "\n\t请在进行图像修复操作之前,在【原始图】窗口中进行适量的绘制"
        "\n\n\t按键操作说明: \n\n"
        "\t\t【鼠标左键】-在图像上绘制白色线条\n\n"
        "\t\t键盘按键【ESC】- 退出程序\n\n"
        "\t\t键盘按键【1】或【SPACE】-进行图像修复操作 \n\n"   );

    //1、载入原图并显示,初始化掩膜和灰度图
    Mat srcImage = imread("F:/C++/2. OPENCV 3.1.0/TEST/inpaint.jpg", 1);
    if(!srcImage.data ) { printf("读取图片错误,请确定目录下是否有imread函数指定图片存在~! \n"); return false; }

    srcImage0 = srcImage.clone();
    srcImage1 = srcImage.clone();
    inpaintMask = Mat::zeros(srcImage1.size(), CV_8U);

    //显示原始图参考
    imshow(WINDOW_NAME0, srcImage0);
    //显示原始图
    imshow(WINDOW_NAME1, srcImage1);
    //设置鼠标回调消息
    setMouseCallback( WINDOW_NAME1, On_Mouse, 0 );

    //轮询按键,根据不同的按键进行处理
    while (1)
    {
        //获取按键键值
        char c = (char)waitKey();

        //键值为ESC,程序退出
        if( c == 27 )
            break;

        //键值为2,恢复成原始图像
        if( c == '2' )
        {
            inpaintMask = Scalar::all(0);
            srcImage.copyTo(srcImage1);
            imshow(WINDOW_NAME1, srcImage1);
        }

        //键值为1或者空格,进行图像修补操作
        if( c == '1' || c == ' ' )
        {
            Mat inpaintedImage;
            inpaint(srcImage1, inpaintMask, inpaintedImage, 3, CV_INPAINT_TELEA);
            imshow(WINDOW_NAME2, inpaintedImage);
        }
    }

    waitKey(0);
    return 0;
}
static void On_Mouse( int event, int x, int y, int flags, void* )
{
    //鼠标左键弹起消息
    if( event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON) )
        previousPoint = Point(-1,-1);
    //鼠标左键按下消息
    else if( event == CV_EVENT_LBUTTONDOWN )
        previousPoint = Point(x,y);
    //鼠标按下并移动,进行绘制
    else if( event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON) )
    {
        Point pt(x,y);
        if( previousPoint.x < 0 )
            previousPoint = pt;
        //绘制白色线条
        // 同时在源图和掩模图 中绘制涂鸦;
        line( inpaintMask, previousPoint, pt, Scalar::all(255), 5, 8, 0 );
        line( srcImage1, previousPoint, pt, Scalar::all(255), 5, 8, 0 );
        previousPoint = pt;
        imshow(WINDOW_NAME1, srcImage1);
    }
}

结果:

opencv inpaint Opencv inpaint 算法_#define


CV_INPAINT_TELEA 算法:

opencv inpaint Opencv inpaint 算法_键值_02


CV_INPAINT_NS 算法:

opencv inpaint Opencv inpaint 算法_窗口标题_03