OpenCV图像修复

OpenCV图像修复在 OpenCV 的 photo hpp 中定义了一个 inpaint 函数 可以用来实现图像的修复和复原功能 inpaint 函数的原型如下 voidinpaint InputArraysr InputArrayin OutputArrayd doubleinpain intflags

在OpenCV的“photo.hpp”中定义了一个inpaint函数,可以用来实现图像的修复和复原功能,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;



函数实现关键是图像掩码的确定,可以通过阈值筛选或者手工选定,按照这个思路,用三种方法生成掩码,对比图像修复的效果。





方法一、全区域阈值处理+Mask膨胀处理




#include         #include           #include             using namespace cv; //全区域阈值处理+Mask膨胀处理 int main() { Mat imageSource = imread("Test.jpg"); if (!imageSource.data) { return -1; } imshow("原图", imageSource); Mat imageGray; //转换为灰度图 cvtColor(imageSource, imageGray, CV_RGB2GRAY, 0); Mat imageMask = Mat(imageSource.size(), CV_8UC1, Scalar::all(0)); //通过阈值处理生成Mask threshold(imageGray, imageMask, 240, 255, CV_THRESH_BINARY); Mat Kernel = getStructuringElement(MORPH_RECT, Size(3, 3)); //对Mask膨胀处理,增加Mask面积 dilate(imageMask, imageMask, Kernel); //图像修复 inpaint(imageSource, imageMask, imageSource, 5, INPAINT_TELEA); imshow("Mask", imageMask); imshow("修复后", imageSource); waitKey(); }               



原始图像:

OpenCV图像修复

根据阈值处理得到的图像掩码:

OpenCV图像修复

图像复原结果:

OpenCV图像修复

由于是图像全区域做阈值处理获得的掩码,图像上部分区域也被当做掩码对待,导致部分图像受损。


方法二、鼠标框选区域+阈值处理+Mask膨胀处理

#include 
  
    #include 
   
     #include 
    
      #include 
     
       using namespace cv; Point ptL, ptR; //鼠标画出矩形框的起点和终点 Mat imageSource, imageSourceCopy; Mat ROI; //原图需要修复区域的ROI //鼠标回调函数 void OnMouse(int event, int x, int y, int flag, void *ustg); //鼠标圈定区域阈值处理+Mask膨胀处理 int main() { imageSource = imread("Test.jpg"); if (!imageSource.data) { return -1; } imshow("原图", imageSource); setMouseCallback("原图", OnMouse); waitKey(); } void OnMouse(int event, int x, int y, int flag, void *ustg) { if (event == CV_EVENT_LBUTTONDOWN) { ptL = Point(x, y); ptR = Point(x, y); } if (flag == CV_EVENT_FLAG_LBUTTON) { ptR = Point(x, y); imageSourceCopy = imageSource.clone(); rectangle(imageSourceCopy, ptL, ptR, Scalar(255, 0, 0)); imshow("原图", imageSourceCopy); } if (event == CV_EVENT_LBUTTONUP) { if (ptL != ptR) { ROI = imageSource(Rect(ptL, ptR)); imshow("ROI", ROI); waitKey(); } } //单击鼠标右键开始图像修复 if (event == CV_EVENT_RBUTTONDOWN) { imageSourceCopy = ROI.clone(); Mat imageGray; cvtColor(ROI, imageGray, CV_RGB2GRAY); //转换为灰度图 Mat imageMask = Mat(ROI.size(), CV_8UC1, Scalar::all(0)); //通过阈值处理生成Mask threshold(imageGray, imageMask, 235, 255, CV_THRESH_BINARY); Mat Kernel = getStructuringElement(MORPH_RECT, Size(3, 3)); dilate(imageMask, imageMask, Kernel); //对Mask膨胀处理 inpaint(ROI, imageMask, ROI, 9, INPAINT_TELEA); //图像修复 imshow("Mask", imageMask); imshow("修复后", imageSource); } } 
      
     
    
  

鼠标圈定的ROI:

OpenCV图像修复

图像复原结果:

OpenCV图像修复

选定区域之外的图像不受修复影响,没有额外的损伤。


方法三、鼠标划定整个区域作为修复对象


这个方法选定一个矩形区域,把整个矩形区域作为要修复的对象,该方法适用于图像结构比较简单,特别是纯色图像,并且选定区域面积占比不大的情况,效果较好。

#include 
   
     #include 
    
      #include 
     
       #include 
      
        using namespace cv; Point ptL, ptR; //鼠标画出矩形框的起点和终点 Mat imageSource, imageSourceCopy; Mat ROI; //原图需要修复区域的ROI //鼠标回调函数 void OnMouse(int event, int x, int y, int flag, void *ustg); //鼠标圈定区域 int main() { imageSource = imread("Test.jpg"); if (!imageSource.data) { return -1; } imshow("原图", imageSource); setMouseCallback("原图", OnMouse); waitKey(); } void OnMouse(int event, int x, int y, int flag, void *ustg) { if (event == CV_EVENT_LBUTTONDOWN) { ptL = Point(x, y); ptR = Point(x, y); } if (flag == CV_EVENT_FLAG_LBUTTON) { ptR = Point(x, y); imageSourceCopy = imageSource.clone(); rectangle(imageSourceCopy, ptL, ptR, Scalar(255, 0, 0)); imshow("原图", imageSourceCopy); } if (event == CV_EVENT_LBUTTONUP) { if (ptL != ptR) { ROI = imageSource(Rect(ptL, ptR)); imshow("ROI", ROI); waitKey(); } } //单击鼠标右键开始图像修复 if (event == CV_EVENT_RBUTTONDOWN) { imageSourceCopy = Mat(imageSource.size(), CV_8UC1, Scalar::all(0)); Mat imageMask = imageSourceCopy(Rect(ptL, ptR)); //生成一个跟ROI大小一样的值全为1的区域 Mat imageMaskCopy = Mat(imageMask.size(), CV_8UC1, Scalar::all(1)); imageMaskCopy.copyTo(imageMask); inpaint(imageSource, imageSourceCopy, imageSource, 9, INPAINT_TELEA); //图像修复 imshow("Mask", imageSourceCopy); imshow("修复后", imageSource); } } 
       
      
     
   

原始图像:

OpenCV图像修复


图像复原结果:

OpenCV图像修复




版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/227074.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午10:00
下一篇 2026年3月16日 下午10:00


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号