【图像修复】浅析:图像修复中的TV模型

前言图像修复是一项非常有意义的研究工作,比如我们生活中的照片被污染,再比如名贵字画、国家文物壁画等珍贵物品被破坏,这些都需要图像修复工作来完成。

简介整体变分(Total Variation)的方法最早是用来对受到噪声污染的图像进行降噪的,在这方面的应用最早是由L.Rudin和S.Osher等人在1992年提出的,2002年Chan等人把TV模型推广到图像修补中,并提出了基于TV模型的图像修补方法,同时说明了TV修补模型的缺点,进一步提出了CDD修补模型(curvature driven diffusions),此修补模型改正了TV修补模型的缺陷,对图像的修补具有很好的效果。

一、TV模型介绍

如图所示:D区域是被污染区(待修复),E是D的邻域


下面直接给出TV模型的数学公式:

                      ①

其中:u是图像中的像素点,λ为设定的参数

在该模型基础上,考虑到噪声的影响,边界E区域产生的噪声不能超过一定的范围;根据最佳猜测和贝叶斯理论,要求图像u在满足约束条件下使它的能量泛函最小,因此约束条件记做:公式②。根据拉格朗日乘数法,将①②方程转化成为一个求极值的方程,对其求导数并令其等于0,可得到如下方程:


其中:div代表散度(关于图像中的散度解释,可见此处:在图像处理中,散度 div 具体的作用是什么?


由于图像是离散的数值,故可看做如下构成。其中:O为污染点,邻域B=(N,S,W,E),半像素邻域B' =(n,s,w,e)。


因此,离散化后可得到表达式:


化简得到最终的表达式:


其中:λe(O)为中心O处的λ参数,与上λe一致;uo为O点修复后的像素,另一个为O点修复前的原始像素。将上式迭代,知道达到较好的修复效果。

到此,TV模型的理论推导已完成。接下来就是要编程实现其功能。

matlab源码实现:

img=double(imread('lena.jpg'));
mask=imread('mask.jpg');
a1=find(mask>127);
b1=find(mask<=127);
mask(a1)=0;
mask(b1)=255;
[m n]=size(img);
for i=1:m
    for j=1:n
        if mask(i,j)==0
           img(i,j)=0; 
        end
    end
end
imshow(img,[]);     %合成的需要修复的图像

lambda=0.2;
a=0.5;%避免分母为0
imgn=img;
for l=1:1500         %迭代次数
    for i=2:m-1
        for j=2:n-1
            if mask(i,j)==0     %如果当前像素是被污染的像素,则进行处理
                Un=sqrt((img(i,j)-img(i-1,j))^2+((img(i-1,j-1)-img(i-1,j+1))/2)^2);
                Ue=sqrt((img(i,j)-img(i,j+1))^2+((img(i-1,j+1)-img(i+1,j+1))/2)^2);
                Uw=sqrt((img(i,j)-img(i,j-1))^2+((img(i-1,j-1)-img(i+1,j-1))/2)^2);
                Us=sqrt((img(i,j)-img(i+1,j))^2+((img(i+1,j-1)-img(i+1,j+1))/2)^2);

                Wn=1/sqrt(Un^2+a^2);
                We=1/sqrt(Ue^2+a^2);
                Ww=1/sqrt(Uw^2+a^2);
                Ws=1/sqrt(Us^2+a^2);

                Hon=Wn/((Wn+We+Ww+Ws)+lambda);
                Hoe=We/((Wn+We+Ww+Ws)+lambda);
                How=Ww/((Wn+We+Ww+Ws)+lambda);
                Hos=Ws/((Wn+We+Ww+Ws)+lambda);

                Hoo=lambda/((Wn+We+Ww+Ws)+lambda);
                value = Hon*img(i-1,j)+Hoe*img(i,j+1)+How*img(i,j-1)+Hos*img(i+1,j)+Hoo*img(i,j);
                imgn(i,j)= value;
            end
        end
    end
    img=imgn; 
end
figure;
imshow(img)
opencv源码实现:

#include <iostream>
#include <stdlib.h>
#include <cv.h>
#include <math.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace cv;

int main(void)
{
	//读取原始图像及掩模图像
	IplImage *src_uint8 = cvLoadImage("src.jpg", CV_LOAD_IMAGE_GRAYSCALE);
	IplImage *mask = cvLoadImage("mask.jpg", CV_LOAD_IMAGE_GRAYSCALE);
	//合成需要修复的图像
	int M = mask->height;
	int N = mask->width;
	int i, j;
	CvMat *src = cvCreateMat(M, N, CV_32FC1);//存放浮点图像
	cvConvert(src_uint8, src);
	for (i = 0; i < M; i++)
	{
		for (j = 0; j < N; j++)
		{
			if ((mask->imageData + i * mask->widthStep)[j] < 0)//理解此处判别条件,根据情况自行更改
			{
				((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j] = 0.0;
			}
			if (((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j] < 0)
			{
				((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j] += 256.0;
			}
		}
	}
	cvConvert(src, src_uint8);
	cvShowImage("需要修复的图像", src_uint8);
	cvWaitKey(0);

	double t = getTickCount();//当前滴答数
	float lambda = 0.2;
	float delta = 0.5;
	float UO, UN, UW, US, UE, UNE, UNW, USW, USE;
	float Un, Ue, Uw, Us;
	float Wn, We, Ww, Ws;
	float Hon, Hoe, How, Hos;
	float Hoo;
	int iteration = 500;
	while(iteration)
	{
		for (i = 1; i < M - 1; i++)
		{
			for (j = 1; j < N - 1; j++)
			{
				if (((char *)(mask->imageData + i * mask->widthStep))[j] < 0)//坏损区
				{
					UO = ((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j];
					UN = ((float*)(void*)(src->data.ptr + (size_t)src->step*(i-1)))[j];
					US = ((float*)(void*)(src->data.ptr + (size_t)src->step*(i+1)))[j];
					UE = ((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j+1];
					UW = ((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j-1];

					UNE = ((float*)(void*)(src->data.ptr + (size_t)src->step*(i-1)))[j+1];
					UNW = ((float*)(void*)(src->data.ptr + (size_t)src->step*(i-1)))[j-1];
					USE = ((float*)(void*)(src->data.ptr + (size_t)src->step*(i+1)))[j+1];
					USW = ((float*)(void*)(src->data.ptr + (size_t)src->step*(i+1)))[j-1];

					Un = sqrt((UO - UN) * (UO - UN) + ((UNW - UNE) / 2.0) * ((UNW - UNE) / 2.0));
					Ue = sqrt((UO - UE) * (UO - UE) + ((UNE - USE) / 2.0) * ((UNE - USE) / 2.0));
					Uw = sqrt((UO - UW) * (UO - UW) + ((UNW - USW) / 2.0) * ((UNW - USW) / 2.0));
					Us = sqrt((UO - US) * (UO - US) + ((USW - USE) / 2.0) * ((USW - USE) / 2.0));

					Wn = 1.0/sqrt(Un * Un + delta * delta);
					We = 1.0/sqrt(Ue * Ue + delta * delta);
					Ww = 1.0/sqrt(Uw * Uw + delta * delta);
					Ws = 1.0/sqrt(Us * Us + delta * delta);

					Hon = Wn/(Wn+We+Ww+Ws+lambda);
					Hoe = We/(Wn+We+Ww+Ws+lambda);
					How = Ww/(Wn+We+Ww+Ws+lambda);
					Hos = Ws/(Wn+We+Ww+Ws+lambda);

					Hoo = lambda/(Wn+We+Ww+Ws+lambda);
					((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j]=(Hon*UN+Hoe*UE+How*UW+Hos*US+Hoo*UO);
				}
			}
		}
		iteration--;
	}
	cvConvert(src, src_uint8);
	t = ((double)getTickCount() - t)/getTickFrequency();
	printf("算法用时:%f秒\n", t);
	cvShowImage("修复结果", src_uint8);
	cvWaitKey(0);
}
由于迭代次数和浮点数的运算,使得算法时间较长,效果如下,仔细观察可以看出仍有细节处修复效果不是很理想。在TV模型之后,又出现了许多改进的TV模型,在速度和效果上都比理想,此处不深入探讨。


本文所需的实验材料都已打包上传,点击此处下载:http://download.csdn.net/detail/hujingshuang/8500553

如有疑问请加群:数字图像处理群:389011389

特别注意:

1、本博客例程仅做学习交流用,切勿用于商业用途。

2、欢迎交流,转载请注明出处:http://blog.csdn.net/hujingshuang/article/details/44257179

  • 11
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
纹理合成是一种常见的图像修复算法,它通过给定一小块纹理样本来生成外观相似的大片图像。最简单的纹理合成方法是基于图像自相似的原理,通过在当前图像寻找纹理类似的匹配块进行补全,这一类方法以结构传播为代表,可以较好地补全较小的区域。传统的图像修复技术包括基于结构和纹理两种方法。基于结构的修复算法利用结构传播和曲率扩散等方法,可以修复小块区域的破损。而基于纹理的修复算法则通过纹理合成算法,如基于patch的纹理合成算法,来修复破损区域的纹理。然而,这些传统的修复算法在破损区域越来越大时,修复效果会下降,并且会存在图像模糊、结构扭曲、纹理不清晰和视觉不连贯等问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [【计算摄影】浅析图像修复背后的核心技术](https://blog.csdn.net/hacker_long/article/details/117719230)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [基于微软开源深度学习算法,用 Python 实现图像和视频修复](https://blog.csdn.net/dQCFKyQDXYm3F8rB0/article/details/117969955)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值