• 图像修复中的TV模型


    转载至http://blog.csdn.net/hujingshuang/article/details/44257179

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

    简介:整体变分(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源码实现:

    1.  1 img=double(imread('lena.jpg'));
       2 mask=imread('mask.jpg');
       3 a1=find(mask>127);
       4 b1=find(mask<=127);
       5 mask(a1)=0;
       6 mask(b1)=255;
       7 [m n]=size(img);
       8 for i=1:m
       9     for j=1:n
      10         if mask(i,j)==0
      11            img(i,j)=0; 
      12         end
      13     end
      14 end
      15 imshow(img,[]);     %合成的需要修复的图像
      16 
      17 lambda=0.2;
      18 a=0.5;%避免分母为0
      19 imgn=img;
      20 for l=1:1500         %迭代次数
      21     for i=2:m-1
      22         for j=2:n-1
      23             if mask(i,j)==0     %如果当前像素是被污染的像素,则进行处理
      24                 Un=sqrt((img(i,j)-img(i-1,j))^2+((img(i-1,j-1)-img(i-1,j+1))/2)^2);
      25                 Ue=sqrt((img(i,j)-img(i,j+1))^2+((img(i-1,j+1)-img(i+1,j+1))/2)^2);
      26                 Uw=sqrt((img(i,j)-img(i,j-1))^2+((img(i-1,j-1)-img(i+1,j-1))/2)^2);
      27                 Us=sqrt((img(i,j)-img(i+1,j))^2+((img(i+1,j-1)-img(i+1,j+1))/2)^2);
      28 
      29                 Wn=1/sqrt(Un^2+a^2);
      30                 We=1/sqrt(Ue^2+a^2);
      31                 Ww=1/sqrt(Uw^2+a^2);
      32                 Ws=1/sqrt(Us^2+a^2);
      33 
      34                 Hon=Wn/((Wn+We+Ww+Ws)+lambda);
      35                 Hoe=We/((Wn+We+Ww+Ws)+lambda);
      36                 How=Ww/((Wn+We+Ww+Ws)+lambda);
      37                 Hos=Ws/((Wn+We+Ww+Ws)+lambda);
      38 
      39                 Hoo=lambda/((Wn+We+Ww+Ws)+lambda);
      40                 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);
      41                 imgn(i,j)= value;
      42             end
      43         end
      44     end
      45     img=imgn; 
      46 end
      47 figure;
      48 imshow(img)

      opencv源码实现:


    2.  1 #include <iostream>
       2 #include <stdlib.h>
       3 #include <cv.h>
       4 #include <math.h>
       5 #include <opencv2/highgui/highgui.hpp>
       6 #include <opencv2/core/core.hpp>
       7 #include <opencv2/imgproc/imgproc.hpp>
       8 
       9 using namespace cv;
      10 
      11 int main(void)
      12 {
      13     //读取原始图像及掩模图像
      14     IplImage *src_uint8 = cvLoadImage("src.jpg", CV_LOAD_IMAGE_GRAYSCALE);
      15     IplImage *mask = cvLoadImage("mask.jpg", CV_LOAD_IMAGE_GRAYSCALE);
      16     //合成需要修复的图像
      17     int M = mask->height;
      18     int N = mask->width;
      19     int i, j;
      20     CvMat *src = cvCreateMat(M, N, CV_32FC1);//存放浮点图像
      21     cvConvert(src_uint8, src);
      22     for (i = 0; i < M; i++)
      23     {
      24         for (j = 0; j < N; j++)
      25         {
      26             if ((mask->imageData + i * mask->widthStep)[j] < 0)//理解此处判别条件,根据情况自行更改
      27             {
      28                 ((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j] = 0.0;
      29             }
      30             if (((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j] < 0)
      31             {
      32                 ((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j] += 256.0;
      33             }
      34         }
      35     }
      36     cvConvert(src, src_uint8);
      37     cvShowImage("需要修复的图像", src_uint8);
      38     cvWaitKey(0);
      39 
      40     double t = getTickCount();//当前滴答数
      41     float lambda = 0.2;
      42     float delta = 0.5;
      43     float UO, UN, UW, US, UE, UNE, UNW, USW, USE;
      44     float Un, Ue, Uw, Us;
      45     float Wn, We, Ww, Ws;
      46     float Hon, Hoe, How, Hos;
      47     float Hoo;
      48     int iteration = 500;
      49     while(iteration)
      50     {
      51         for (i = 1; i < M - 1; i++)
      52         {
      53             for (j = 1; j < N - 1; j++)
      54             {
      55                 if (((char *)(mask->imageData + i * mask->widthStep))[j] < 0)//坏损区
      56                 {
      57                     UO = ((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j];
      58                     UN = ((float*)(void*)(src->data.ptr + (size_t)src->step*(i-1)))[j];
      59                     US = ((float*)(void*)(src->data.ptr + (size_t)src->step*(i+1)))[j];
      60                     UE = ((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j+1];
      61                     UW = ((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j-1];
      62 
      63                     UNE = ((float*)(void*)(src->data.ptr + (size_t)src->step*(i-1)))[j+1];
      64                     UNW = ((float*)(void*)(src->data.ptr + (size_t)src->step*(i-1)))[j-1];
      65                     USE = ((float*)(void*)(src->data.ptr + (size_t)src->step*(i+1)))[j+1];
      66                     USW = ((float*)(void*)(src->data.ptr + (size_t)src->step*(i+1)))[j-1];
      67 
      68                     Un = sqrt((UO - UN) * (UO - UN) + ((UNW - UNE) / 2.0) * ((UNW - UNE) / 2.0));
      69                     Ue = sqrt((UO - UE) * (UO - UE) + ((UNE - USE) / 2.0) * ((UNE - USE) / 2.0));
      70                     Uw = sqrt((UO - UW) * (UO - UW) + ((UNW - USW) / 2.0) * ((UNW - USW) / 2.0));
      71                     Us = sqrt((UO - US) * (UO - US) + ((USW - USE) / 2.0) * ((USW - USE) / 2.0));
      72 
      73                     Wn = 1.0/sqrt(Un * Un + delta * delta);
      74                     We = 1.0/sqrt(Ue * Ue + delta * delta);
      75                     Ww = 1.0/sqrt(Uw * Uw + delta * delta);
      76                     Ws = 1.0/sqrt(Us * Us + delta * delta);
      77 
      78                     Hon = Wn/(Wn+We+Ww+Ws+lambda);
      79                     Hoe = We/(Wn+We+Ww+Ws+lambda);
      80                     How = Ww/(Wn+We+Ww+Ws+lambda);
      81                     Hos = Ws/(Wn+We+Ww+Ws+lambda);
      82 
      83                     Hoo = lambda/(Wn+We+Ww+Ws+lambda);
      84                     ((float*)(void*)(src->data.ptr + (size_t)src->step*i))[j]=(Hon*UN+Hoe*UE+How*UW+Hos*US+Hoo*UO);
      85                 }
      86             }
      87         }
      88         iteration--;
      89     }
      90     cvConvert(src, src_uint8);
      91     t = ((double)getTickCount() - t)/getTickFrequency();
      92     printf("算法用时:%f秒
      ", t);
      93     cvShowImage("修复结果", src_uint8);
      94     cvWaitKey(0);
      95 }

    由于迭代次数和浮点数的运算,使得算法时间较长,效果如下,仔细观察可以看出仍有细节处修复效果不是很理想。在TV模型之后,又出现了许多改进的TV模型,在速度和效果上都比理想,此处不深入探讨。

  • 相关阅读:
    提升树在回归方法中的应用
    前向分布算法
    提升树
    AdaBoost算法学习笔记
    统计学习方法-提升方法
    序列最小最优化算法
    mysql-profiling详解
    mysql,简单介绍一下索引
    MySQL Explain详解
    spring的事务传播行为
  • 原文地址:https://www.cnblogs.com/hxjbc/p/6675901.html
Copyright © 2020-2023  润新知