opencv學習筆記七十一:影象修復
阿新 • • 發佈:2018-12-17
當我們的照片有劃痕或遭到人為的塗鴉(比如馬賽克)時, 如果我們想讓這些遭到破壞的圖片儘可能恢復到原樣,Opencv能幫我們做到嗎?答案是肯定的。
那麼影象修復技術的原理是什麼呢?
簡而言之,就是利用那些已經被破壞的區域的邊緣, 即邊緣的顏色和結構,根據這些影象留下的資訊去推斷被破壞的資訊區的資訊內容,然後對破壞區進行填補 ,以達到影象修補的目的。
OpenCV中就是利用inpaint()這個函式來實現修復功能的。
void inpaint( InputArray src, InputArray inpaintMask, OutputArray dst, double inpaintRadius, int flags );
-
第一個引數src,輸入的單通道或三通道影象;
-
第二個引數inpaintMask,影象的掩碼,單通道影象,大小跟原影象一致,inpaintMask影象上除了需要修復的部分之外其他部分的畫素值全部為0;
-
第三個引數dst,輸出的經過修復的影象;
-
第四個引數inpaintRadius,修復演算法取的鄰域半徑,用於計算當前畫素點的差值;
-
第五個引數flags,修復演算法,有兩種:INPAINT_NS 和I NPAINT_TELEA;
#include<opencv2\opencv.hpp> using namespace cv; int main() { imshow("原圖", imageSource); Mat imageGray; //轉換為灰度圖 cvtColor(imageSource, imageGray, CV_RGB2GRAY, 0); imshow("gray", imageGray); //通過閾值處理生成Mask Mat imageMask = Mat(imageSource.size(), CV_8UC1, Scalar::all(0)); imshow("imageMask", imageMask); threshold(imageGray, imageMask, 240, 255, THRESH_BINARY); //對Mask膨脹處理,增加Mask面積 Mat Kernel = getStructuringElement(MORPH_RECT, Size(3, 3)); dilate(imageMask, imageMask, Kernel); //影象修復 inpaint(imageSource, imageMask, imageSource, 5, INPAINT_TELEA); imshow("Mask", imageMask); imshow("修復後", imageSource); waitKey(); }
下面是修復效果,效果看上去很不錯,但仔細一看 ,還是有些細節跟原圖發生了差異,比如刀和頭上那個亮點,這是因為生成掩模的時候這些區域的亮度和白色的叉痕亮度相近,所以也成為了被修復的的物件。
想要消除這些差異,可設定ROI區域,只對ROI區域的影象形成掩模和修復,其它區域不動。
//影象修復 #include<opencv2\opencv.hpp> using namespace cv; void callback(int event, int x, int y, int flags, void* userdata); Point ptL, ptR; Mat src, srcCopy,ROI,gray; int main() { src = imread("6.jpg"); if (src.empty()) { printf("could not load image!"); return -1; } namedWindow("input"); imshow("input", src); setMouseCallback("input", callback); waitKey(); } void callback(int event, int x, int y, int flags, void* userdata) { if (event == CV_EVENT_LBUTTONDOWN) { ptL = Point(x, y); ptR = Point(x, y); } if (flags == CV_EVENT_FLAG_LBUTTON) { ptR = Point(x, y); srcCopy = src.clone(); rectangle(srcCopy, ptL, ptR, Scalar(255, 0, 0),2); imshow("srcCopy", srcCopy); } if (event == CV_EVENT_LBUTTONUP) { if (ptL!= ptR) { ROI = src(Rect(ptL, ptR)); imshow("ROI", ROI); } } if (event == CV_EVENT_RBUTTONDOWN) { //灰度化 cvtColor(ROI, gray, CV_BGR2GRAY); //通過閾值處理生成Mask Mat imageMask = Mat(ROI.size(), CV_8UC1, Scalar::all(0)); threshold(gray, imageMask, 240, 255, THRESH_BINARY); //對Mask膨脹處理,增加Mask面積 Mat Kernel = getStructuringElement(MORPH_RECT, Size(3, 3)); dilate(imageMask, imageMask, Kernel); imshow("Mask", imageMask); //影象修復 inpaint(ROI, imageMask, ROI, 5, INPAINT_TELEA); imshow("修復後", src); } }
下面是修復效果,效果比上面好很多: