opencv-inpainting图像修复
图像修复技术的原理是什么呢?
简而言之,就是利用那些已经被破坏的区域的边缘, 即边缘的颜色和结构,根据这些图像留下的信息去推断被破坏的信息区的信息内容,然后对破坏区进行填补 ,以达到图像修补的目的
#include<opencv2/opencv.hpp> #include<iostream> int main(int argc, char** argv) { cv::Mat imageSource = cv::imread("D:/bb/tu/9.png"); imshow("原图", imageSource); cv::Mat imageGray; cv::cvtColor(imageSource, imageGray, cv::COLOR_RGB2GRAY, 0); //注意:不能用cv::COLOR_BGR2BGRA 替换cv::COLOR_RGB2GRAY,否则inpaint报错,我也不知原因,知道的请告知 13116140007 cv::Mat imageMask = cv::Mat(imageSource.size(), CV_8UC1, cv::Scalar::all(0)); cv::threshold(imageGray, imageMask, 245, 255, cv::THRESH_BINARY); cv::Mat Kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)); cv::dilate(imageMask, imageMask, Kernel);//对Mask膨胀处理,增加Mask面积 cv::Mat dst; cv::inpaint(imageSource, imageMask, dst, 5, cv::INPAINT_TELEA); /* 第一个参数src,输入的单通道或三通道图像 第二个参数inpaintMask,图像的掩码,单通道图像,大小跟原图像一致,inpaintMask图像上除了需要修复的部分之外其他部分的像素值全部为0 第三个参数dst,输出的经过修复的图像; 第四个参数inpaintRadius,修复算法取的邻域半径,用于计算当前像素点的差值 第五个参数flags,修复算法,有两种:INPAINT_NS 和INPAINT_TELEA */ imshow("Mask", imageMask); imshow("修复后", dst); cv::waitKey(0); return 0; }
上面就是修复效果,感觉很不错吧!不过仔细一看,感觉跟原图还是发生了一些差异,比如图中剑圣头上的那颗亮点,颜色发生了变化。这个就是修复后的副作用!毕竟作出了修复,付点代价还是要的。受损是由于图像全区域做阈值处理获得的掩码,图像上部分区域也被当做掩码对待,导致部分图像受损
上面提到其他无辜的区域会受损,这个问题能解决一下吗?可以的,那就得自己定义一块需要修复的区域,不需要修复的区域我们不动它就是了【就是修改mask】
#include<opencv2/opencv.hpp> #include<iostream> cv::Point ptL, ptR; //鼠标画出矩形框的起点和终点 cv::Mat imageSource, imageSourceCopy; cv::Mat ROI; //原图需要修复区域的ROI void OnMouse(int event, int x, int y, int flag, void* param) { if (event == cv::EVENT_LBUTTONDOWN) { ptL = cv::Point(x, y); ptR = cv::Point(x, y); } if (flag == cv::EVENT_FLAG_LBUTTON) { ptR = cv::Point(x, y); imageSourceCopy = imageSource.clone(); cv::rectangle(imageSourceCopy, ptL, ptR, cv::Scalar(255, 0, 0)); imshow("原图", imageSourceCopy); } if (event == cv::EVENT_LBUTTONUP) { if (ptL != ptR) { ROI = imageSource(cv::Rect(ptL, ptR)); imshow("ROI", ROI); } } //单击鼠标右键开始图像修复 if (event == cv::EVENT_RBUTTONDOWN) { imageSourceCopy = ROI.clone(); cv::Mat Gray; cvtColor(ROI, Gray, cv::COLOR_RGB2GRAY); //转换为灰度图 cv::Mat imageMask = cv::Mat(ROI.size(), CV_8UC1, cv::Scalar::all(0)); //通过阈值处理生成Mask threshold(Gray, imageMask, 245, 255, cv::THRESH_BINARY); cv::Mat Kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)); dilate(imageMask, imageMask, Kernel); //对Mask膨胀处理 inpaint(ROI, imageMask, ROI, 9, cv::INPAINT_TELEA); //图像修复 imshow("修复后", imageSource); } } int main(int argc, char** argv) { imageSource = cv::imread("D:/bb/tu/9.png"); imshow("原图", imageSource); cv::setMouseCallback("原图", OnMouse); cv::waitKey(0); return 0; }