基于MATLAB的图像去遮挡修复数字图像处理系统

article/2024/12/22 13:38:25

资源下载地址:https://download.csdn.net/download/sheziqiong/85639467

一、总述

本次设计要求将图片前景的黑色栏杆去除,恢复遮挡部分。要求修改的图片有两张,第一张图片的前景栏杆较窄,第二张图片的前景栏杆大部分较窄,有一根栏杆较粗。

​ (原图片一和图片二)

为了去除遮挡部分,首先需要找到遮挡部分的位置,即 mask,这一步使用一系列图像处理的方法来完成。

针对第一张图片,由于遮挡物较窄,我使用了 Fast Marching Method 算法来实现去遮挡,该算法运算较快,对窄遮挡物去除效果较好,但对宽遮挡物(宽度大于 15 像素)进行修复时会出现模糊现象(Telea, 2004)。因此,针对第二张图片的宽栏杆部分,我使用了 criminisi 算法来进行修复,该算法运算较慢,但对宽遮挡物修复效果极佳(Criminisi, Perez, &Toyama, 2003)。

此外,我对 criminisi 算法做了一点改动,大大提高了它的运算速度,同时保证修复质量。

为了便于可执行文件的使用,我制作简单的 UI 界面。

去遮挡算法难以用矩阵运算实现,只能使用 for 循环,因此运算速度整体较慢。为了减少运算时间,我缩小了图片尺寸。

二、提取遮挡物

为了去遮挡,首先需要得到遮挡物的位置,即 mask。为此我进行了一系列图像处理的操作。这一部分的算法可拓展性较差,只适用于这次作业的两张图片,且参数之间的依赖性较强。两张图片中的栏杆都是以直线的形式呈现,所以这一部分算法的基本思路是利用直线检测提取位置。

2.1 图片一中栏杆位置的提取

对应代码:get_mask/get_mask_1.m

首先将图片二值化并去除图片下方的黑色部分,避免对直线检测结果造成干扰。

​ (图片一二值化)

接下来,对二值化后的图片使用 Hough 变换,Hough 变换是把图像空域中的点转化到 ρ—θ 空间,使用如下公式:

ρ = xcosθ + ysinθ

其中 ρ 和 θ 表示极坐标中直线到原点的距离以及距离垂线的角度。因此,图像中的一个点对应 Hough 空间中的一条正弦曲线,而图像中的一条直线对应 Hough 空间中多条正弦曲线的交点。

使用 Hough 变换检测直线的另一个好处是可以知道直线的起止点,这对本例是十分有用的。Hough 变换检测到的直线如下图所示。

​ (Hough 变换检测直线)

Hough 变换得到的曲线中,有一些冗余的检测结果,也有一条直线没有检测到,因此我们需要做一些进一步的处理。

在 get_mask/lines_integrate.m 函数中,我首先将 ρ—θ 直线转换成 k—b 斜率截距型,方便后面的计算。再将重复的直线去掉,判断标准是两直线角度差以及距离。

处理之后,将直线按从上到下的顺序排列,并利用上下两条直线间的距离找到遗漏直线的位置,补上遗漏的直线。下面是补上遗漏直线后的处理结果:

​ (去掉重复直线并补上遗漏直线)

找到所有直线的位置后,下面就需要用这些直线填补出栏杆的 mask,这个 mask 是和原图一样大小的矩阵,在有栏杆的地方矩阵值为 1(或 255),在没有栏杆的地方矩阵值为 0.

get_mask/maskFromlines.m 函数是这一算法的实现,基本思路是遍历直线上每一列的像素点(竖线是遍历每一行),寻找这一点附近灰度值的局部最小值点,将这一最小值点附近一部分点(具体多少点由超参决定,其实就是栏杆的宽度)的 mask 设为 1。下面是得到的图片一中栏杆的 mask。

​ (图片一中栏杆的 mask)

2.2 图片二中栏杆位置的提取

对应代码:get_mask_2.m

图片二的处理比图片一的处理更复杂,但大体思路相同。

图片二中间有一条栏杆宽度很大,需要先将这根栏杆的位置找到并除去,方便后面直线检测的顺利进行。

首先依然是将图片二值化,去除下方的黑色干扰部分。

寻找宽栏杆时要利用宽栏杆中点附近黑点更多的特点,找到宽栏杆中若干点。具体操作时,我在图片中间隔相等的四行进行扫描,对每一个点,计算它附近一定大小的领域中黑点的数量,每一行中领域黑点数量最多的那个点应该就在宽栏杆内部。找到的宽栏杆内部四个点纵向均匀分布,从这个四个点分别向左向右出发,找到宽栏杆共八个边界点。

找到的四个内部点(红点)和八个边界点(黄点)如下图所示。

​ (宽栏杆边界点、内部点和边界线)

宽栏杆八个边界点中左右各有四个边界点,利用这些边界点可以拟合出宽栏杆的边界线,如上图绿线所示。

得到宽栏杆左右边界线后,就可以得到其左边区域和右边区域,并去除宽栏杆。

图片二中的直线有很多断裂部分,如果直接使用直线检测效果不佳,因此我先对其进行膨胀处理。如下图,直线的连接度高了许多。

​ (图片二的二值化、去除宽栏杆、膨胀处理结果)

之后就能使用图片一中类似的步骤来检测直线了,但是,由于图片二中宽栏杆左右部分直线的斜率不同,位置不同,所以需要分别进行处理。直线检测结果如下图所示。

​ (图片二中扁栏杆位置检测)

​ (图片二中的扁栏杆 mask 在原灰度图上的位置)

​ (图片二中的宽栏杆 mask 在原灰度图上的位置)

三、FFM 算法修复图片一

代码:FFM_inpaint 文件夹中 inpaint_FMM.m, nearest_interp.m, myMinheap.m, solve_T.m, compute_outside.m

Fast Marching Method 算法其实是一种插值方法,其特殊之处在于插值权重的确定以及最佳修复点的快速查找。

考虑下面图中的情况:区域 Ω 是图片需要修复的区域,Ω 是 Ω 的边缘.现在需要修复 p 点的像素值,我们用已知像素区域中 p 的一小片圆形领域( )中的像素做插值:

下面我们来介绍怎样计算权重w(p,q ),怎样快速找到最佳修复点以及算法流程。

算法实现中用到了F(i,j )和T(i,j)两个关键的矩阵,T(i,j)表示点(i,j) 到待修补区域边缘的距离。F(i,j )表示点(i,j)的性质,待修补区域中的点值为 2(内部点,未知点),待修补区域边界点值为 1,已知像素区域的点值为 0。这两个矩阵都会在代码运行过程中动态更新。

3.1 权重的计算

权重的计算综合考虑了各个方面,具体地,w(p,q ) = |dir(p,q)*𝑑𝑠𝑡(𝑝, 𝑞) ∗ 𝑙𝑒𝑣(𝑝, 𝑞)|。p 是需要修复的点,q 是其已知像素领域𝐵(𝜀)中的一个点。

其中,dir(p,q)保证沿着 N§向量方向的点有更大的权重,𝑁(𝑝) = ∇𝑇(𝑝𝑖 , 𝑝𝑗),即 T 矩阵在 p 处的梯度,实际表示 δΩ 在 p 点处指向 Ω 内部的垂线。p-q 表示 q 指向 p 的向量。

𝑑𝑠𝑡(𝑝, 𝑞)保证距离 p 近的点有更大的权重,||𝑝 − 𝑞||^2表示 p 到 q 距离的平方,d0 一般取 1。

𝑙𝑒𝑣(𝑝, 𝑞)保证距离待修复区域边缘(δΩ)近的点有更大的权重

3.2 快速查找最佳修复点

FFM 算法很重要的一个特点是快速查找最佳修复点,因为在修复图片的过程中,我们可以随意挑选一个边缘点,然后对它旁边的未知点进行修复,但这样的修复效果很差。例如修复下方左图中的中间白色区域,按中间图黑线所示的顺序进行修复效果差,因为内层的点原本是未知区域,其像素值是计算出来的,可信度差。但如果按右边图黑线所示顺序修复效果相对较好。

上述两种修复方式的区别在于,边缘点的选择方式,如果我们优先选择 T 矩阵值更小的边缘点,则能保证选择的边缘点可信度更高。

为了快速找到 T 矩阵值最小的边缘点,我们可以维护一个最小堆,提高运算速度。

T矩阵的计算其实是一个方程的解,我们下面会提到。

3.3 算法流程

算法的输入是一张 rgb 图片、mask 矩阵(需要修复的区域值大于0,以及修复半径,即圆形领域B(𝜀)的半径。

  • 首先求出初始 F 矩阵,具体做法是将 mask 矩阵用进行膨胀得到 F’,将 F’大于 0 的部分置为 1, F_temp=F’-F 表示边缘点,则 F=2F’-F_temp,这样得到的 F 满足:待修补区域中的点值为 2(内部点,未知点),待修补区域边界点值为 1,已知像素区域的点值为 0。

  • 然后初始化 T 矩阵,具体做法是先将内部点的 T 值置为很大的一个值(1e6),边缘点值为 0,然后计算部分外部点的 T 值。只计算部分外部点的 T 值的原因是修复过程中只用到待修复区域周围的一部分外部点。计算外部点的 T 值其实是将 F 中的 0 和 2 替换(即内部点和外部点替换),再用我们下面要介绍的流程进行。

  • T矩阵与 F 矩阵初始化成功后,我们先找到边缘点坐标以及它们的F矩阵值,放进最小堆 heap 里,就可以开始修复循环了。

下面是修复循环在论文中的伪代码,其中,NarrowBand 指待修复区域边缘点,简单来说就是每一轮从最小堆 heap 里提取出 T 值最小的边缘点 p,找到 p 上下左右的点中待修复的点,插值计算这个点的像素值,T 矩阵值,在 F 矩阵中将它设为边缘点,并把它放入最小堆 heap 中,循环直到没有边缘点为止。

​ (FFM 算法循环部分的伪代码)

3.4 修复结果

下面是图片一的修复结果,可以看出结果基本看不到栏杆的痕迹,且图片比较自然,看不出修复痕迹,而且图片其他部分不会受影响。

​ (用 FFM 算法修复图片一)

下面是使用 FFM 算法修复图片二的结果,可以看到中间的宽栏杆有一定程度的模糊,其他部分效果较好。

​ (用 FFM 算法修复图片二)

四、criminisi 算法修复图片二

criminisi 算法的本质是查找已知像素区域中的小方块补到未知部分,如下图所示,Ω 是待修复区域,φ是已知像素区域。修补 p 附件小块 Ψ 时,找到与之匹配度最高的小块 Ψq’,并将它补到 Ψp的位置。算法的关键是找到最高优先级的 p,再找到与之领域正方形小块 Ψp 匹配度最高的Ψq′。

4.1 修复优先级

我们在三.2 中已经阐述了修复顺序的重要性,criminisi 算法中也是如此, 考虑下图中的情况

定义边缘点 p 的优先级 P§,

P ( p ) = C ( p ) ∗ D ( p ) P(p) = C(p)*D(p) P(p)=C(p)D(p)

C§表示 p 点附近已知像素区域部分的比重,D§表示 p 点图片像素值梯度的垂线与待修复区域边缘线单位垂线 n p n_p np的内积大小。α一般取255。

计算出所有边缘点的优先级后,挑出优先级最高的边缘点进行修复。

4.2 寻找最佳匹配

挑出优先级最高的边缘点 p 后,要对 p 的正方形领域 Ψp 进行修复,需要在全图范围内找到与之匹配度最高的小块 Ψq′,具体方法是求出图片中每个正方形块 Ψq 与 Ψp 的已知部分的像素值差的平方和,二者相差最小的块即为 Ψq′。

注意这里的像素值差是指在 LAP 空间中的像素值差,因为 LAP 空间更能体现图片的纹理结构。因此,需要在初始化时将 rgb 图片转换得到LAP 图片。

4.3 算法流程

算法的输入是一张 rgb 图片、mask 矩阵(需要修复的区域值大于0),以及修复块半径,即正方形修补块的边长。

算法的具体流程也很清楚:

  • 先求出图片像素值梯度的垂线(这里的像素值指在 rgb 空间中的值),做一些初始化。

  • 进入算法循环,先根据当前的 mask 求出边缘点,再循环求出每个边缘点的 C 值,求出所有边缘点的 D 值,用 C 和 D 数组求出优先级 P,挑出优先级最高的边缘点 p。找到边缘点 p 领域 Ψp 的最佳匹配 Ψq′,复制 Ψq′的 rgb 值、lap 值;更新 C(使 Ψp 中未知像素点的 C 值都等于 p 点 C 值);更新 mask(Ψp 中点的 mask 都设为 0,即已知点)。

  • 循环(2)中流程,直到没有未知点为止。

4.4 结果

下图是用 criminisi 算法修复图片二的结果,为了减少运算时间,图片缩的比较小,可以看出宽栏杆部分的修复效果比用 FFM 算法修复的效果好一些,没有出现模糊,但还是有待改进。

​ (用 criminisi 算法修复图片二)

具体运行算法过程中,其实是先用 FFM 算法进行修复,再用 criminisi 算修复宽栏杆部分。

UI 界面

资源下载地址:https://download.csdn.net/download/sheziqiong/85639467


http://chatgpt.dhexx.cn/article/J5RVSwOH.shtml

相关文章

含冰蓄冷空调的冷热电联供型微网多时间尺度优化调度(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

MATLAB(1)

MATLAB 第一章 MATALB基础技能 第1节 MATLAB窗口 1、语言修改 中文版:预设——MATLAB——常规 英文版:Preferences——MATLAB——General 2、布局 中文版:布局 英文版:layout 3、帮助 可以搜索一些指令 第2节 命令行 …

matlab使用

目录: 导入数据randpermrng&&randnormrnd矩阵定义使用 sizeinv数据归一化定义作用方式 reshape括号()[]{} 创建模型layers与optionstrainNetworkpredict绘图numelfloormeanstd./与/ones函数normpdf函数sum函数hist函数repmat函数 导入数据 load&#xff1a…

matlab画散点图,图例总显示不对

在matlab中画5个颜色的散点图,点击生成图例,图例不是显示每一类的点,而是把所有的点都显示出来了。但如果自己使用 legend 生成图例的话,显示的也是同一个颜色的。。。求助,这个是哪里出了问题,怎么解决&am…

C语言 编一程序,交换两个字符变量的值并输出

编一程序&#xff0c;交换两个字符变量的值并输出。 #include<stdio.h> main() {char ch1A,ch2B,chTemp;//Temp是临时的意思&#xff0c;代表中转站 &#xff0c;在C语言中是通用的printf("ch1%c,ch2%c\n",ch1,ch2);chTempch1;ch1ch2;ch2chTemp;;printf(&quo…

js拼接字符串与变量

使用eval&#xff08;&#xff09;方法可将拼接后的字符串与变量转变为变量 var field_test 我是小白鼠一号; var field_test 我是小白鼠二号; // 然后在JS里尝试将前面的语言简写当成变量&#xff0c;拼接后面的字符串 var lang field; var test1 lang _test; var …

C语言字符变量输出值,C语言,交换任意两个字符型变量的值并输出结果。要求:利用getchar和putchar函数。...

C语言,交换任意两个字符型变量的值并输出结果。要求:利用getchar和putchar函数。以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! C语言,交换任意两个字符型变量的值并输出结果。要求:利用getchar和putchar函…

判断字符变量是否为字母或者是数字

原型&#xff1a;extern int isalnum(int c); 用法&#xff1a; 1 #include <ctype.h>/* 包含 <ctype.h> */ 功能&#xff1a;判断 字符变量c是否为字母或数字 说明&#xff1a;当c为数字0-9或字母a-z及A-Z时&#xff0c;返回非零值&#xff0c;否则返回零。

【C语言】字符变量间的减法

一、核心 核心点&#xff1a;字符变量之间的相减就是对应的ASCII对应相减。 #include<stdio.h> int k1; main(){int i 4;fun(i);printf("\n%d,%d",i,k);scanf("%d",&i); }fun(int m) {mk;km;{char kA; //重新定义一个变量k,字符变量&#xff0c…

字符变量存放多个字符

在我们的认知中&#xff0c;不会有字符变量中存放多个字符的情况&#xff08;不要说\n、\t等&#xff0c;这些本来就被C语言标准定义为是一个字符&#xff09;&#xff0c;因为一个字符变量就只占1个字节空间&#xff0c;只能存放一个字符&#xff0c;但往下看&#xff0c;你会…

字符变量与字符常量

字符变量是存放字符常量的char类型的变量 字符常量是字面量&#xff0c;即单独出现在表达式中的字面上的字符&#xff0c;如 a 。 二者的重要区别为所占字节大小的不同&#xff0c;如下&#xff1a; 字符变量占1个字节&#xff0c;字符常量占4个字节&#xff08;C语言中是如此&…

C语言中的字符常量与变量

字符常量与变量 在这一节中&#xff0c;我们来讨论字符与字符串。 1. 字符常量 如果我想在屏幕上打印"HelloWorld"。应该怎样做呢&#xff1f;大家应该很熟悉这个代码了。 #include <stdio.h> int main() {printf("HelloWorld\n");return 0; }我们…

BadeLua插件熟悉

BabeLua简介 BabeLua是一款基于VS2012/2013&#xff08;简称VS&#xff09;的免费开源的Lua集成开发环境。 具体介绍和使用方法在&#xff1a;http://www.cocoachina.com/bbs/read.php?tid205043 中有详细介绍 BabeLua简介   BabeLua是一款基于VS2012/2013&#xff08;简…

VS安装扩展BabeLua下载很慢问题

参考这位博主的方法&#xff0c;原本显示下载速度正常了&#xff0c;但是没有成功&#xff0c;没显示下载完成。 VS下载插件很慢的一种解决方法_F_Arisa的博客-CSDN博客 又参考了其他方法&#xff0c;结合起来下载成功了。 点击详细信息跳转网页&#xff0c;下载完关闭VS的情…

cocos2dx 3.16 VS+BabeLua lua环境配置与代码调试

我这里用的是cocos2dx 3.16&#xff0c;VS2015 用命令行 cocos new tank -p com.wutian.tank -l lua -d I:\WorkShop\Programs\Cocos2dx\tank 创建一个cocos2dx项目&#xff0c;中间会提示找不到某些文件&#xff0c;不用理会感觉是cocos2dx的坑 这些东西弄好之后开始为调试…

Cocos2dx 3.4 BabeLua 3.0.1.0 Windows下lua环境配置

Cocos2dx BabeLua3.0.1.0 Windows下lua环境配置 author 路人 time 2015.08.24 updateTime nonereference http://www.cocoachina.com/bbs/read.php?tid-205043-page-1.html reference http://blog.csdn.net/babestudio/article/details/27228865这篇文章用于VS 2013里cocos…

Cocos2d-lua(二)VS装入BabeLua插件

为什么装BabeLua插件&#xff0c;因为方便我们开发lua项目&#xff0c;对BabeLua插件的功能这里不介绍了&#xff08;百度一下&#xff09;&#xff0c;谁用谁知道。 一、装入插件BabeLua 1.打开VS --> 工具 --> 扩展和更新 --> 联机 --> 搜索BabeLua --> 下载…

vs2015 + BabeLua + Cocos2d-x 3.10配置

以前只用过vs2015cocos2d-x 3.9写过小游戏&#xff0c;新下载了3.10&#xff0c;想学习下Lua的使用 电脑是win10 64位&#xff0c;装的是vs2015 1. 安装cocos&#xff0c;官网下载cocos2d-x 3.10 3.10版本 Cocos2d-x与Cocos整合升级为Cocos引擎&#xff0c;下载后是exe程序&…

Visual Studio BabeLua配置

环境&#xff1a; Visual Studio 2013, Cocos 3.10, Lua5.1 window7(64) BabeLua简介&#xff1a; 基于VS免费开源的Lua集成开发插件&#xff0c;用于Lua编辑和调试相关。 其功能特性有&#xff1a; Lua语法高亮&#xff0c;语法检查 自动补全&#xff0c;一键注释 格式化代码&…

cocos2dx+vs2012+lua开发环境配置+BabeLua

cocos2dx版本&#xff1a;cocos2dx3.2 lua插件&#xff1a;babelua 1.5.3 下载地址&#xff1a;http://pan.baidu.com/s/1i3mPD8h 第一步&#xff1a;先关闭vs&#xff0c;双击下载下来的BabeLua.vsix&#xff0c;双击按照提示安装 第二步&#xff1a;用cocos2dx新建一个LUA的…