OpenCV(學習筆記7)-圖像修復

圖像或者說圖片經常被噪聲腐蝕,或者說是舊照片的劃痕。

圖像修復技術簡單來說,就是利用那些被破壞區域的邊緣,即是邊緣的顏色和結構,繁殖和混合到損壞的圖像中,來進行修復圖像。下面的OpenCV代碼主要做的是將圖像中的字跡進行消除的效果。
如果圖像損壞的區域不是太大,修復效果可以達到很好的效果。畢竟修復的能力是有限的。

inpaint函數
在OpenCV中,圖像修補技術由inpaint函數實現,用來從掃描圖像中清除灰塵和劃痕,或者從靜態圖像或視頻中去除不需要的物體。
函數聲明如下:

void inpaint(InputArray src, InputArray inpaintMask, OutputArray dst, double inpaintRadius, int flags)

第一個參數,InputArray類型的src,也就是輸入圖像,用Mat類對象就可以了。並且要是8位單通道或者三通道圖像。
第二個參數,InputArray類型的inpaintMask,修復掩膜,爲8位單通道圖像。其中非0像素表示要修復的區域。
第三個參數,OutputArray類型的dst,函數調用後的運算結果保存在這裏,和輸入圖像有着一樣的大小和類型。
第四個參數,double類型的inpaintRadius,需要修補的每個點的圓形鄰域,爲修復算法參考的半徑。
第五個參數,int類型的flags,修補方法的標識符。如下
**INPAINT_NS 基於Navier-Stokes方程的方法
INPAINT_TELEA Alexandru Telea方法**

代碼如下:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/photo/photo.hpp"

#include <iostream>
using namespace cv;
using namespace std;


#define WINDOW_NAME1 "【原始圖】"
#define WINDOW_NAME2 "【修補後】"

Mat srcImage1, inpaintMask;
// 原來的點座標
Point previousPoint(-1, -1);

static void On_Mouse(int event, int x, int y, int flags, void *)
{
    if(event == EVENT_LBUTTONUP || !(flags & EVENT_FLAG_LBUTTON))
        previousPoint = Point(-1, -1);
    else if(event == EVENT_LBUTTONDOWN)
        previousPoint = Point(x, y);
    else if(event == EVENT_MOUSEMOVE && (flags & 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);
    }
}


int main(int argc, char ** argv)
{
    Mat srcImage = imread("1.jpg", -1);
    if(!srcImage.data)
    {
        printf("讀取照片錯誤,請確定目錄下是否有imread函數指定的圖片存在!\n");
        return false;
    }
    srcImage1 = srcImage.clone();
    inpaintMask = Mat::zeros(srcImage1.size(), CV_8U);

    // 顯示原圖
    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, INPAINT_TELEA);
            imshow(WINDOW_NAME2, inpaintedImage);
        }

    }
    return 0;
}

程序運行如下:
這裏寫圖片描述

這裏寫圖片描述

關於OpenCV和圖像處理以及模式識別更多的學習資料將繼續更新,敬請關注本博客。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章