【第二部分 图像处理】第4章 Opencv图像处理高阶【3图像修复】

2024-08-30 13:32

本文主要是介绍【第二部分 图像处理】第4章 Opencv图像处理高阶【3图像修复】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

3.1图像修复概述

在实际应用中,我们的图像常常会被噪声腐蚀,这些噪声或是镜头上的灰尘或水滴,或是旧照片的划痕,或者是图像遭到人为的涂画(比如马赛克)或者图像的部分本身已经损坏。如果我们想让这些受到破坏的额图片尽可能恢复到原样,Opencv能帮我们做到吗?
OpenCV真的有这个妙手回春的功能!别以为图像修补的工作只能用PS或者美图秀秀那些软件去做,其实由程序员自己写代码去做更加高效!
图像修复技术的原理是什么呢?简而言之,就是利用那些已经被破坏的区域的边缘, 即边缘的颜色和结构,根据这些图像留下的信息去推断被破坏的信息区的信息内容,然后对破坏区进行填补 ,以达到图像修补的目的。

3.2图像修复API:inpaint()函数

 inpaint()函数讲解

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

【参数】
第一个参数,src,输入的单通道或三通道图像;
第二个参数,inpaintMask,图像的掩码,单通道图像,大小跟原图像一致,inpaintMask图像上除了需要修复的部分之外其他部分的像素值全部为0;
第三个参数,dst,输出的经过修复的图像;
第四个参数,inpaintRadius,修复算法取的邻域半径,用于计算当前像素点的差值;
第五个参数,flags ,修复算法,有两种:INPAINT_NS 和I NPAINT_TELEA;
 INPAINT_NS Navier-Stokes based method.
 INPAINT_TELEA Method by Alexandru Telea [Telea04].
 inpaint()函数源代码

/*【inpaint()源代码】***************************************************************** @Version:OpenCV 3.0.0(Opnencv2和Opnencv3差别不大,Linux和PC的对应版本源码完全一样,均在对应的安装目录下)  * @源码路径:…\opencv\sources\modules\photo\src\inpaint.cpp* @起始行数:810行   
********************************************************************************/
void cv::inpaint( InputArray _src, InputArray _mask, OutputArray _dst,
                  double inpaintRange, int flags )
{
    Mat src = _src.getMat(), mask = _mask.getMat();
    _dst.create( src.size(), src.type() );
    CvMat c_src = src, c_mask = mask, c_dst = _dst.getMat();
    cvInpaint( &c_src, &c_mask, &c_dst, inpaintRange, flags );
}
可以看出inpaint源码中调用的是cvInpaint()函数,其源代码如下。
/*【inpaint()源代码】***************************************************************** @Version:OpenCV 3.0.0(Opnencv2和Opnencv3差别不大,Linux和PC的对应版本源码完全一样,均在对应的安装目录下)  * @源码路径:…\opencv\sources\modules\photo\src\inpaint.cpp* @起始行数:727行   
********************************************************************************/
Void cvInpaint( const CvArr* _input_img, const CvArr* _inpaint_mask, CvArr* _output_img,double inpaintRange, int flags )
{cv::Ptr<CvMat> mask, band, f, t, out;cv::Ptr<CvPriorityQueueFloat> Heap, Out;cv::Ptr<IplConvKernel> el_cross, el_range;CvMat input_hdr, mask_hdr, output_hdr;CvMat* input_img, *inpaint_mask, *output_img;int range=cvRound(inpaintRange);int erows, ecols;input_img = cvGetMat( _input_img, &input_hdr );inpaint_mask = cvGetMat( _inpaint_mask, &mask_hdr );output_img = cvGetMat( _output_img, &output_hdr );if( !CV_ARE_SIZES_EQ(input_img,output_img) || !CV_ARE_SIZES_EQ(input_img,inpaint_mask))CV_Error( CV_StsUnmatchedSizes, "All the input and output images must have the same size" );if( (CV_MAT_TYPE(input_img->type) != CV_8UC1 &&CV_MAT_TYPE(input_img->type) != CV_8UC3) ||!CV_ARE_TYPES_EQ(input_img,output_img) )CV_Error( CV_StsUnsupportedFormat,"Only 8-bit 1-channel and 3-channel input/output images are supported" );if( CV_MAT_TYPE(inpaint_mask->type) != CV_8UC1 )CV_Error( CV_StsUnsupportedFormat, "The mask must be 8-bit 1-channel image" );range = MAX(range,1);range = MIN(range,100);ecols = input_img->cols + 2;erows = input_img->rows + 2;f.reset(cvCreateMat(erows, ecols, CV_8UC1));t.reset(cvCreateMat(erows, ecols, CV_32FC1));band.reset(cvCreateMat(erows, ecols, CV_8UC1));mask.reset(cvCreateMat(erows, ecols, CV_8UC1));el_cross.reset(cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_CROSS,NULL));cvCopy( input_img, output_img );cvSet(mask,cvScalar(KNOWN,0,0,0));COPY_MASK_BORDER1_C1(inpaint_mask,mask,uchar);SET_BORDER1_C1(mask,uchar,0);cvSet(f,cvScalar(KNOWN,0,0,0));cvSet(t,cvScalar(1.0e6f,0,0,0));cvDilate(mask,band,el_cross,1);   // image with narrow bandHeap=cv::makePtr<CvPriorityQueueFloat>();if (!Heap->Init(band))return;cvSub(band,mask,band,NULL);SET_BORDER1_C1(band,uchar,0);if (!Heap->Add(band))return;cvSet(f,cvScalar(BAND,0,0,0),band);cvSet(f,cvScalar(INSIDE,0,0,0),mask);cvSet(t,cvScalar(0,0,0,0),band);if( flags == cv::INPAINT_TELEA ){out.reset(cvCreateMat(erows, ecols, CV_8UC1));el_range.reset(cvCreateStructuringElementEx(2*range+1,2*range+1,range,range,CV_SHAPE_RECT,NULL));cvDilate(mask,out,el_range,1);cvSub(out,mask,out,NULL);Out=cv::makePtr<CvPriorityQueueFloat>();if (!Out->Init(out))return;if (!Out->Add(band))return;cvSub(out,band,out,NULL);SET_BORDER1_C1(out,uchar,0);icvCalcFMM(out,t,Out,true);icvTeleaInpaintFMM(mask,t,output_img,range,Heap);}else if (flags == cv::INPAINT_NS) {icvNSInpaintFMM(mask,t,output_img,range,Heap);} else {CV_Error( cv::Error::StsBadArg, "The flags argument must be one of CV_INPAINT_TELEA or CV_INPAINT_NS" );}
}

3.3图像修复实例

 全区域阈值处理+Mask膨胀处理
代码参看附件【demo1】。

这里写图片描述

图1

由于是图像全区域做阈值处理获得的掩码,图像上部分区域也被当做掩码对待,导致部分图像受损。
 鼠标框选区域+阈值处理+Mask膨胀处理
代码参看附件【demo2】。
这里写图片描述

图2

可以看到,选定区域之外的图像不受修复影响,没有额外的损伤。
 鼠标划定整个区域作为修复对象
这个方法选定一个矩形区域,把整个矩形区域作为要修复的对象,该方法适用于图像结构比较简单,特别是纯色图像,并且选定区域面积占比不大的情况,效果较好。
代码参看附件【demo3】。
这里写图片描述

图3

 图像修复综合实例
代码参看附件【demo4】。
这里写图片描述

图4

本章参考附件

点击进入

这篇关于【第二部分 图像处理】第4章 Opencv图像处理高阶【3图像修复】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1120958

相关文章

闲置电脑也能活出第二春?鲁大师AiNAS让你动动手指就能轻松部署

对于大多数人而言,在这个“数据爆炸”的时代或多或少都遇到过存储告急的情况,这使得“存储焦虑”不再是个别现象,而将会是随着软件的不断臃肿而越来越普遍的情况。从不少手机厂商都开始将存储上限提升至1TB可以见得,我们似乎正处在互联网信息飞速增长的阶段,对于存储的需求也将会不断扩大。对于苹果用户而言,这一问题愈发严峻,毕竟512GB和1TB版本的iPhone可不是人人都消费得起的,因此成熟的外置存储方案开

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

poj 2976 分数规划二分贪心(部分对总体的贡献度) poj 3111

poj 2976: 题意: 在n场考试中,每场考试共有b题,答对的题目有a题。 允许去掉k场考试,求能达到的最高正确率是多少。 解析: 假设已知准确率为x,则每场考试对于准确率的贡献值为: a - b * x,将贡献值大的排序排在前面舍弃掉后k个。 然后二分x就行了。 代码: #include <iostream>#include <cstdio>#incl

【C++高阶】C++类型转换全攻略:深入理解并高效应用

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C++ “ 登神长阶 ” 🤡往期回顾🤡:C++ 智能指针 🌹🌹期待您的关注 🌹🌹 ❀C++的类型转换 📒1. C语言中的类型转换📚2. C++强制类型转换⛰️static_cast🌞reinterpret_cast⭐const_cast🍁dynamic_cast 📜3. C++强制类型转换的原因📝

opencv 滚动条

参数介绍:createTrackbar( trackbarname , "hello" , &alpha_slider ,alpha_max ,  on_trackbar )  ;在标签中显示的文字(提示滑动条的用途) TrackbarName创建的滑动条要放置窗体的名字 “hello”滑动条的取值范围从 0 到 alpha_max (最小值只能为 zero).滑动后的值存放在

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

基于51单片机的自动转向修复系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机

《数据结构(C语言版)第二版》第八章-排序(8.3-交换排序、8.4-选择排序)

8.3 交换排序 8.3.1 冒泡排序 【算法特点】 (1) 稳定排序。 (2) 可用于链式存储结构。 (3) 移动记录次数较多,算法平均时间性能比直接插入排序差。当初始记录无序,n较大时, 此算法不宜采用。 #include <stdio.h>#include <stdlib.h>#define MAXSIZE 26typedef int KeyType;typedef char In

CSP 2023 提高级第一轮 CSP-S 2023初试题 完善程序第二题解析 未完

一、题目阅读 (最大值之和)给定整数序列 a0,⋯,an−1,求该序列所有非空连续子序列的最大值之和。上述参数满足 1≤n≤105 和 1≤ai≤108。 一个序列的非空连续子序列可以用两个下标 ll 和 rr(其中0≤l≤r<n0≤l≤r<n)表示,对应的序列为 al,al+1,⋯,ar​。两个非空连续子序列不同,当且仅当下标不同。 例如,当原序列为 [1,2,1,2] 时,要计算子序列 [