38.图像修复
图像修复技术就是利用图像中损坏区域边缘的像素,根据像素值的大小以及像素间的结构关系,估计出损坏区域可能的像素排列,从而去除图像中受污染的区域。图像修复不仅可以去除图像中得“划痕”,还可以去除图像中得水印、日期等。OpenCV 4提供了能够对含有较少污染或者水印的图像进行修复的inpaint()函数,该函数的函数原型在代码清单8-26中给出。
代码清单8-26 inpaint()函数清单 void cv::inpaint(InputArray src, InputArray inpaintMask, OutputArray dst, double inpaintRadius, int flags )
- src:输入待修复图像,当图像为单通道时,数据类型可以是CV_8U、CV_16U或者CV_32F,当图像为三通道时数据类型必须是CV_8U。
- inpaintMask:修复掩模,数据类型为CV_8U的单通道图像,与待修复图像具有相同的尺寸。
- dst:修复后输出图像,与输入图像具有相同的大小和数据类型。
- inpaintRadius:算法考虑的每个像素点的圆形邻域半径。
- flags:修复方法标志,可以选择的参数及含义在表8-7给出
该函数利用图像修复算法对图像中指定的区域进行修复,函数无法判定哪些区域需要修复,因此在使用过程中需要明确指出需要修复的区域。函数的第一个参数是需要修复的图像,该函数可以对灰度图像和彩色图像进行修复。修复灰度图像时,图像的数据类型可以为CV_8U、CV_16U或者CV_32F;修复彩色图像时,图像的数据类型只能为CV_8U。第二个参数是修复掩码,即指定图像中需要修复的区域,该参数输入量是一个与图像具有相同尺寸的数据类型为CV_8U的单通道图像,图像中非0像素表示需要修复的区域。函数的第三个 参数是修复后的输出图像,与输入图像具有相同的大小和数据类型。第四个参数表示修复算法考虑的每个像素点的圆形邻域半径。最后一个参数表示修复图像方法标志,可以选择的参数及含义在表8-7给出。该函数虽然可以对图像受污染区域进行修复,但是需要借助污染边缘区域的像素信息,离边缘区域越远的像素估计出的准确性越低,因此如果受污染区域较大,修复的效果就会降低。
代码清单8-27 myInpaint.cpp图像修复 #include <opencv2\opencv.hpp> #include <iostream> using namespace cv; using namespace std; int main() { Mat img1 = imread("inpaint1.png"); Mat img2 = imread("inpaint2.png"); if (img1.empty() || img2.empty()) { cout << "请确认图像文件名称是否正确" << endl; return -1; } imshow("img1", img1); imshow("img2", img2); //转换为灰度图 Mat img1Gray, img2Gray; cvtColor(img1, img1Gray, COLOR_RGB2GRAY, 0); cvtColor(img2, img2Gray, COLOR_RGB2GRAY, 0); //通过阈值处理生成Mask掩模 Mat img1Mask, img2Mask; threshold(img1Gray, img1Mask, 245, 255, THRESH_BINARY); threshold(img2Gray, img2Mask, 245, 255, THRESH_BINARY); //对Mask膨胀处理,增加Mask面积 Mat Kernel = getStructuringElement(MORPH_RECT, Size(3, 3)); dilate(img1Mask, img1Mask, Kernel); dilate(img2Mask, img2Mask, Kernel); //图像修复 Mat img1Inpaint, img2Inpaint; inpaint(img1, img1Mask, img1Inpaint, 5, INPAINT_NS); inpaint(img2, img2Mask, img2Inpaint, 5, INPAINT_NS); //显示处理结果 imshow("img1Mask", img1Mask); imshow("img1修复后", img1Inpaint); imshow("img2Mask", img2Mask); imshow("img2修复后", img2Inpaint); waitKey(); return 0; }