精华内容
下载资源
问答
  • 运动模糊图像复原

    2012-12-07 19:57:30
    运动模糊图像复原 图像复原技术也常被称为图像恢复技术图像复原技术能够去除或减轻在获取数字图像过程中发生的图像质量下降(退化)问题,从而使图像尽可能地接近于真实场景。
  • 图像复原代码。运动模糊图像复原、非约束复原、逆滤波复原、维纳滤波复原等 图像复原代码。运动模糊图像复原、非约束复原、逆滤波复原、维纳滤波复原等
  • matlab运动模糊图像复原 实验报告

    热门讨论 2011-05-08 17:49:44
    matlab运动模糊图像复原matlab运动模糊图像复原matlab运动模糊图像复原matlab运动模糊图像复原matlab运动模糊图像复原
  • 运动模糊图像复原代码,运动长度、运动角度的计算代码,维纳滤波、盲区卷积法、、最小二乘法、lang等方法的代码。有直接复原,效果一般,需要自己输入角度长度。也有先模糊再复原的代码
  • 运动模糊图像复原matllab代码,有需要的同学可以下载查看,有需要类似代码的可以联系本人。
  • 提出了一种改进的运动模糊图像复原算法,先用方向微分思想鉴别出运动模糊方向,然后采用求微分模糊图像自相关函数的方法鉴别模糊尺度,从而构造出最为近似的点扩散函数(Point Spread Function, PSF)。针对振铃...
  • 任务书 1 课程设计目的 1 提高分析 问题解决问题的能力进一步巩固数字图像 处理系统中的基本原理与方法 2 熟悉掌握一门计算机语言可以进行数字图像应用处理 的开发设计 2 课程设计的题目运动模糊 图像复原算法实现及...
  • 旋转运动模糊图像复原,复原效果佳,可以很好的提高图像质量,和图像信噪比
  • 简单运动模糊图像复原GUI设计,我的运行环境2014b,内附使用说明和汇报PPT,可进行读取图片、撤销上一步操作、保存图片、运动模糊、图像复原(包括直接逆滤波、维纳滤波、Lucy-Richardson算法、约束最小二乘法、盲去...
  • 基于互补性的运动模糊图像复原方法 ,王珮,孙瑾秋,图像复原的目的是将原始图像从观测到的降析图像中恢复出来,在多帧图像复原算法中,输入图像帧的选择是很重要的问题,输入图像选��
  • 在图像获取过程中,存在很多造成...介绍了图像一般退化模型和运动模糊退化模型的建立方法;对退化模型的点扩散函数的估计方法进行了分析;对当前的一些复原算法进行了总结。对图像复原技术未来的发展方向进行了预测。
  • 物体和成像系统之间的相对运动导致图像产生运动模糊,降低了图像质量,为了获得更加理想的复原图像,提出一种基于倒谱和快速全变差去卷积相结合的运动模糊图像复原算法。利用倒谱法对运动模糊图像的点扩散函数参数...
  • 以车牌模糊图像复原为例介绍运动模糊图像复原处理
  • 运动图像成像容易导致模糊,基于MATLAB可以做运动图像的修复处理。这个文档给出了具体实现方法。可以参考使用。
  • Deblur:运动模糊图像复原(三)

    千次阅读 2018-10-09 09:32:54
    运动模糊图像复原(三)   Reference: Deblurring Text Images via L0 -Regularized Intensity and Gradient Prior   在运动模糊图像复原(一)中有涉及到模糊模型的估计,这是一个难点,但是没有细说。这篇...

    运动模糊图像复原(三)

     

    Reference

    Deblurring Text Images via L0 -Regularized Intensity and Gradient Prior

     

    在运动模糊图像复原(一)中有涉及到模糊模型的估计,这是一个难点,但是没有细说。这篇文章主要记录一下第四点的内容:使用latent image和blurred image预估当前层级的模糊模型。

    在估计模糊模型之前,输入的latent image和blurred image两张图像,使用2*2的初始梯度核进行卷积之后的结果作为最终输入Bx,By(blurred image对应的水平垂直方向梯度),Lx,Ly(Latent image对应的水平垂直方向梯度),充分利用梯度信息进行模糊核的估计。

    1

    0

    -1

    0

    1

    -1

    0

    0

     

    在论文中,作者只给出了梯度空间下的模糊核估计公式,但并未给出该最小二乘最小化问题的闭环解。那么下面我结合代码给出闭环解公式。

    论文中的梯度空间估计的模糊核k公式如下,其中x表示latent image,y表示blurred image:

    那么,它的最小二乘最小化问题的闭环解如下,为了跟下文内容统一,使用L表示x,B表示y,

    那么,选择迭代方式计算时,推出k的计算公式为:

     

    首次迭代时,核函数设置数值全为1/(kernel_height*kernel_width),大小等于(kernel_width,kernel_height)的矩阵,设为x。

    那么按照如下公式进行:

    此处设置

    首次迭代时,上述公式中的k使用x代替,那么x即为我要的最终结果;

    每次迭代时(从第二次迭代开始),上述公式中的被减数用Ap表示;

    每次迭代时(从第二次迭代开始),上述公式中的输入k即为上一次的结果k’,我用p表示;

    每次迭代的结果都用r表示;

     

    设置最大迭代次数为20.通过多次迭代产生最终的模糊核函数k。

    那么现在的问题是,每次迭代时,如何更新上述变量Ap,r,p呢?

    我设置一个权重alpha来更新x和r: x=x+alpha*p, r=r-alpha*Ap。

    , 其中变量

    当更新变量r之后,可以重新计算变量rsold为rsnew,

    此时可更新变量p=r+(rsnew/rsold)*p,最后再更新rsold<-rsnew.

     

    在这里可以设置一个迭代终止的条件:rsnew的开方小于阈值1e-5。

    最后当迭代结束,归一化模糊核函数x。

    展开全文
  • 本论文主要介绍了对运动车牌模糊图像的复原处理,着重解决了含噪运动模糊图像和局部运动模糊图像复原问题,采用改进的局部运动模糊对象提取算法实现局部运动模糊图像复原
  • 《数字图像处理-MATLAB》运动模糊图像复原 图像复原技术也常被称为图像恢复技术图像复原技术能够去除或减轻在获取数字图像过程中发生的图像质量下降(退化)问题,从而使图像尽可能地接近于真实场景
  • Deblur: 运动模糊图像复原 (一)

    千次阅读 2018-10-08 13:59:24
    本次博文主要想记录一下自己在做运动模糊图像复原时的一些总结和心得感悟,方便以后回顾。 Reference: Deblurring Text Images via L0 -Regularized Intensity and Gradient Prior   主要难点: 估计模糊模型 ...

    本次博文主要想记录一下自己在做运动模糊图像复原时的一些总结和心得感悟,方便以后回顾。

    Reference

    Deblurring Text Images via L0 -Regularized Intensity and Gradient Prior

     

    主要难点: 估计模糊模型

    解决方式:

               ①使用金字塔模型,创建模糊图像相应的层级图像;并根据缩放比例创建模糊模型的大小。可以手动设置金字塔底层模型的大小。

               ②初始化金字塔顶层模型。

               ③根据对应层级模糊图像的L0亮度和梯度 + 对应层级的模糊模型 = 预估当前层级的latent image。可设置多次迭代,更新预估结果。

               ④使用latent image和blurred image预估当前层级的模糊模型。

               ⑤根据金字塔层级,一层层循环进行第③第④步,直至最底层。到这里就可以得到预估的完整模糊模型——kernel。

     

    复原运动模糊的图像:

              Blurred image = deblurred image 卷积 kernel

              可采用快速傅里叶变换,对blurred image进行反卷积得到复原图像。

              注意的点:

    1. Ringing remove 这种畸变会影响复原效果——振铃抑制
    2. 高饱和度的图像,比如过曝图像,需要做特殊处理
    3. 做一些去燥处理

     

    对这种blind deblur方法的理解:

    依赖于intensity和gradient的先验概率设定。在处理中作者设定每次迭代时根据经验更新这两个数值。

    依赖于fft、dst等变换,以及卷积操作。计算量大。

    依赖于图像下采样方法。在计算下采样图像的大小和抽样位置时需要注意。同时对采样的插值方法的差异性值得注意。比如线性插值和双线性插值,两种方法对效果和速率上影响不小。

    振铃失真的去除依赖于拉皮拉斯方法与latent image的差异图。

     

    测试效果:

    C++转换后的代码效果总是低于作者的测试效果。

    对于一些抖动图像的复原效果还是比较理想的。但并非所有抖动图像效果都好。

     

     

    为什么要采用这种方法进行模糊图像的复原?

    1. 可参考文献A Comparative Study for Single Image Blind Deblurring。
    2. 传统方法在某些领域的应用,当前还不能完全用深度学习的方式替代。后续可继续研究深度学习在deblur方面的相关内容。
    展开全文
  • Deblur:运动模糊图像复原(二)

    千次阅读 2018-10-08 16:15:20
    运动模糊图像复原(二) Reference: Deblurring Text Images via L0 -Regularized Intensity and Gradient Prior   上面一文中有涉及到模糊模型的估计,这是一个难点,但是没有细说。这篇文章主要记录一下第三...

    运动模糊图像复原(二)

    Reference

    Deblurring Text Images via L0 -Regularized Intensity and Gradient Prior

     

    上面一文中有涉及到模糊模型的估计,这是一个难点,但是没有细说。这篇文章主要记录一下第三点内容:根据对应层级模糊图像的L0亮度和梯度 + 对应层级的模糊模型 = 预估当前层级的latent image。可设置多次迭代,更新预估结果。

     

    对于金字塔顶层对应的图像,设置相应的模糊核大小,并设置初始核。这里假设最底层金字塔对应的核大小为55*55,即kernel size=55。金字塔层数和最大迭代次数遵循以下公式:

    Pyramid layers: max_iter+1

    对于每层金字塔对应的模糊核大小可以利用如下公式计算:

    , 注意这里需要将计算得到的核大小转换为奇数。

    那么,金字塔层数有7层,初始核为7*7大小,初始核内容设置如下:

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0.5

    0.5

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

    0

     

    对于latent image,论文中按照如下公式计算,x即latent image:

     

    说明一下,表示L0 prior的权重值,实现的时候我设置为0.02。由于上述公式仍有表示不是很清楚的地方,我用代码中用到的公式表示一下。

     

    beta初始值设为2*。后续迭代时需要不断更新beta值,beta=2*beta,当beta≥1e5时,终止迭代,可以输出最终计算出的latant image。

     

    x求解中,傅里叶逆变换之前的分母可以表示为:

    h和v分别表示水平方向和垂直方向的差分。

     

    为什么这个公式成立?

    对于这个问题,之前类似的保留图像边界并平滑图像内部细节的课题,也有遇到过,目前记得不是很清楚,好像是因为输入的k是实对称的原因,所以等式成立。

     

    x求解中,傅里叶逆变换之前的分子可以表示为:

     

    这里值得注意的有两点:

    1. 在求模糊图像二阶差分前,对于一阶差分需要排除一些干扰点。可采用下面公式排除:

    ,保留一阶差分结果, 其他设为0.

        2. 在初次迭代前,对于模糊图像的水平差分和垂直差分,设置初始梯度如下,分别表示水平方向和垂直方向的梯度fx,fy。再对其求fft,变为Fx,Fy。

    那么,

    1

    -1

    1

    -1

     

    我在实际应用中,首次迭代时,设置分母中的梯度使用上述方法计算初始差分,在分子的梯度上使用模糊图像计算差分值。

    展开全文
  • 运动模糊图像的一些复原方法,逆滤波,维纳滤波,LR复原方法
  • 运动模糊的基础知识,和经典方法,初学者很有用,如果需要其他帮助,请留言。
  • 基于TSVD 的图像复原,可达到很好的复原效果,对运动模糊图像的复原尤其有效
  • 申明:本资源提供matlab版的图像复原常用的运动模糊仿真图像生成程序,未经授权,仅供研究使用,不得使用于任何商用场合。 仿真程序提供2种途径:空域仿真方法和频域仿真方法。
  • 针对相机成像时相机抖动、物体运动等导致图像产生运动模糊这一十分具有挑战性的问题,提出基于生成对抗网络的深度卷积神经网络来复原模糊图像的解决方案。该方案省略了模糊核估计的过程,采用端对端的方式直接获取...
  • 维纳滤波运动模糊图像复原

    万次阅读 2017-10-21 14:37:31
    最近需要处理运动模糊图像,查阅了资料发现维纳滤波是个不错的方法,于是借鉴了高人的一些资料,比如:论坛:http://bbs.csdn.net/topics/390338193代码:http://download.csdn.net/detail/suseyaoyao/4976475首先...

    转自:http://www.xuebuyuan.com/694590.html
    最近需要处理运动模糊图像,查阅了资料发现维纳滤波是个不错的方法,于是借鉴了高人的一些资料,比如:

    论坛:http://bbs.csdn.net/topics/390338193

    代码:http://download.csdn.net/detail/suseyaoyao/4976475

    首先非常感谢这位高人的分享!代码我运行了下发现,有几个问题需要解决:第一,图像的模糊距离跟模糊角度需要自己使用其他合适的方法去估计;第二,经过测试,当模糊角度为锐角时,此代码完全可行,当模糊角度为其他数值时,会有内存错误,我试着看懂如何根据模糊大小和模糊角度去得到点扩散函数,惭愧的很,最后没看懂代码的思路。下面把代码和运行结果贴出来,望各位路过的大虾们指导:如何改进代码,使之可以处理任意模糊角度的模糊图像。其中,那个void CY_special(double
    len,double theta,CvMat *&h_last)函数的功能,是根据模糊角度和模糊大小得到点扩散函数。求各位大神指教!(代码看着很长,是因为我把彩图分为三个通道去处理的)

    维纳滤波代码:

    #include<time.h>
    #include<iostream>       //存储int型变量用32位
    #include <stdlib.h>
    #include <cxcore.h>   
    #include "stdio.h"
    #include <string>
    #include <fstream>
    #include <highgui.h> 
    #include <cv.h> 
    #include <windows.h>
    using namespace std;
    using namespace cv;
    
    #define eps 2.22044604925031e-016;
    #define pi 3.1416;
    #define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
    
    # pragma comment(linker, "/NODEFAULTLIB:atlthunk.lib")
    # pragma comment(linker, "/NODEFAULTLIB:LIBCMT")
    # pragma comment(linker, "/NODEFAULTLIB:MSVCRTD")
    BOOL fourn(double * data/*psrc*/, unsigned long nn[]/*w*/, int ndim/*2*/, int isign);
    double CY_sign(double cosphi);
    void CYmeshgrid(int xm,int xn,int ym,int yn,CvMat* &X,CvMat* &Y);
    void CY_special(double len,double theta,CvMat *&h_last);
    void main(int argc, char argv[])
    {
    IplImage *RGB = cvLoadImage("D:\\images\\128.png",-1);
    IplImage* redImage=cvCreateImage(cvGetSize(RGB),IPL_DEPTH_8U,1);    //定义三个通道图像
    IplImage* greenImage=cvCreateImage(cvGetSize(RGB),IPL_DEPTH_8U,1);    
    IplImage* blueImage=cvCreateImage(cvGetSize(RGB),IPL_DEPTH_8U,1);
    cvSplit(RGB,blueImage,greenImage,redImage,NULL);   //通道分割。注意:OpenCV分割成的三个通道参数顺序是:B,G,R
    //cvNamedWindow("RGB");
    //cvShowImage("RGB",RGB);
    
    //处理蓝色通道
    int bHeight = blueImage->height;
    int bLineBytes = blueImage->widthStep;
    int bw = 1;
    int bh = 1;
    //保证离散傅里叶变换的宽度和高度为2的整数幂
    while(bw*2 <= bLineBytes)
    {
    bw = bw*2;
    }
    while(bh*2 <= bHeight)
    {
    bh = bh*2;
    }
    //输入退化图像的长和宽必须为2的整数倍;
    if(bw != (int)bLineBytes)
    {
    return;
    }
    if(bh != (int)bHeight)
    {
    return;
    }
    
    //用于做FFT的数组
    double startime = (double)getTickCount(); // set the begining time
    // 指向源图像倒数第j行,第i个象素的指针   
    
    double *fftSrc, *fftKernel, *laplacianKernel;
    fftSrc = new double [bHeight*bLineBytes*2+1];
    fftKernel = new double [bHeight*bLineBytes*2+1];
    laplacianKernel = new double [bHeight*bLineBytes*2+1];
    unsigned long nn[3] = {0};
    nn[1] = bHeight;
    nn[2] = bLineBytes; 
    LPSTR lpSrc;
    unsigned char pixel;
    double len = 15;     //模糊图像的模糊长度
    double theta = 60;   //模糊图像的模糊角度
    CvMat *h_last;
    CY_special(len,theta,h_last);
    int h_row = h_last->height;
    int h_col = h_last->width;
    for (int j = 0;j < bHeight ;j++)
    {
    for(int i = 0;i < bLineBytes ;i++)
    {
    // 指向源图像倒数第j行,第i个象素的指针   
    lpSrc = (char *)blueImage->imageData + bLineBytes * j + i;
    
    pixel = (unsigned char)*lpSrc;
    
    fftSrc[(2*bLineBytes)*j + 2*i + 1] = (double)pixel;
    fftSrc[(2*bLineBytes)*j + 2*i + 2] = 0.0;
    laplacianKernel[(2*bLineBytes)*j + 2*i + 1] = 0.0;
    laplacianKernel[(2*bLineBytes)*j + 2*i + 2] = 0.0;
    if(i < h_col && j < h_row)
    {
    float h_value = CV_MAT_ELEM(*h_last,float,j,i);
    fftKernel[(2*bLineBytes)*j + 2*i + 1] = double(h_value);
    }
    else
    {
    fftKernel[(2*bLineBytes)*j + 2*i + 1] = 0.0;
    }
    fftKernel[(2*bLineBytes)*j + 2*i + 2] = 0.0;
    }
    }
    laplacianKernel[(2*bLineBytes)*0+2*1+1] = 1.0;  //设置拉普拉斯滤波器
    laplacianKernel[(2*bLineBytes)*1+2*0+1] = 1.0;
    laplacianKernel[(2*bLineBytes)*1+2*1+1] = -4.0;
    laplacianKernel[(2*bLineBytes)*0+2*2+1] = 1.0;
    laplacianKernel[(2*bLineBytes)*2+2*1+1] = 1.0;
    
    //对源图像进行FFT
    fourn(fftSrc,nn,2,1);
    //对卷积核图像进行FFT
    fourn(fftKernel,nn,2,1);
    //对过滤器进行FFT;
    fourn(laplacianKernel,nn,2,1);
    double a,b,c,d,e,f,norm1,norm2,temp;
    double gama = 0.05;
    for (int i = 1;i <bHeight*bLineBytes*2;i+=2)
    {
    a = fftSrc[i];
    b = fftSrc[i+1];
    c = fftKernel[i];
    d = fftKernel[i+1];
    e = laplacianKernel[i];
    f = laplacianKernel[i+1];
    //计算|H(u,v)|*|H(u,v)|+r|C(u,v)*C(u,v)|;
    norm1 = c*c + d*d;
    norm2 = e*e + f*f;
    temp = norm1 + norm2*gama;
    if (c*c + d*d > 1e-3)
    {
    fftSrc[i] = ( a*c + b*d ) /temp;
    fftSrc[i+1] = ( b*c - a*d )/temp; 
    }
    }
    
    //对结果图像进行反FFT
    fourn(fftSrc,nn,2,-1);
    //确定归一化因子  
    //图像归一化因子
    double MaxNum;
    MaxNum = 0.0;
    for (int j = 0;j < bHeight ;j++)
    {
    for(int i = 0;i < bLineBytes ;i++)
    {
    fftSrc[(2*bLineBytes)*j + 2*i + 1] = 
    sqrt(fftSrc[(2*bLineBytes)*j + 2*i + 1] * fftSrc[(2*bLineBytes)*j + 2*i + 1]/
    +fftSrc[(2*bLineBytes)*j + 2*i + 2] * fftSrc[(2*bLineBytes)*j + 2*i + 2]);
    if( MaxNum < fftSrc[(2*bLineBytes)*j + 2*i + 1])
    MaxNum = fftSrc[(2*bLineBytes)*j + 2*i + 1];
    }
    }
    //转换为图像
    for (int j = 0;j < bHeight ;j++)
    {
    for(int i = 0;i < bLineBytes ;i++)
    {
    // 指向源图像倒数第j行,第i个象素的指针   
    lpSrc = (char *)blueImage->imageData + bLineBytes * j + i;
    
    *lpSrc = (unsigned char) (fftSrc[(2*bLineBytes)*j + 2*i + 1]*255.0/MaxNum);
    }
    }
    //cvNamedWindow("blueImageDeblur");
    //cvShowImage("blueImageDeblur",blueImage);
    
    //处理绿色通道
    bLineBytes = greenImage->widthStep;
    bw = 1;
    bh = 1;
    //保证离散傅里叶变换的宽度和高度为2的整数幂
    while(bw*2 <= bLineBytes)
    {
    bw = bw*2;
    }
    while(bh*2 <= bHeight)
    {
    bh = bh*2;
    }
    //输入退化图像的长和宽必须为2的整数倍;
    if(bw != (int)bLineBytes)
    {
    return;
    }
    if(bh != (int)bHeight)
    {
    return;
    }
    
    //用于做FFT的数组
    // 指向源图像倒数第j行,第i个象素的指针   
    fftSrc = new double [bHeight*bLineBytes*2+1];
    fftKernel = new double [bHeight*bLineBytes*2+1];
    laplacianKernel = new double [bHeight*bLineBytes*2+1];
    CvMat *h_last2;
    CY_special(len,theta,h_last2);
    h_row = h_last2->height;
    h_col = h_last2->width;
    for (int j = 0;j < bHeight ;j++)
    {
    for(int i = 0;i < bLineBytes ;i++)
    {
    // 指向源图像倒数第j行,第i个象素的指针   
    lpSrc = (char *)greenImage->imageData + bLineBytes * j + i;
    
    pixel = (unsigned char)*lpSrc;
    
    fftSrc[(2*bLineBytes)*j + 2*i + 1] = (double)pixel;
    fftSrc[(2*bLineBytes)*j + 2*i + 2] = 0.0;
    laplacianKernel[(2*bLineBytes)*j + 2*i + 1] = 0.0;
    laplacianKernel[(2*bLineBytes)*j + 2*i + 2] = 0.0;
    if(i < h_col && j < h_row)
    {
    float h_value = CV_MAT_ELEM(*h_last2,float,j,i);
    fftKernel[(2*bLineBytes)*j + 2*i + 1] = double(h_value);
    }
    else
    {
    fftKernel[(2*bLineBytes)*j + 2*i + 1] = 0.0;
    }
    fftKernel[(2*bLineBytes)*j + 2*i + 2] = 0.0;
    }
    }
    laplacianKernel[(2*bLineBytes)*0+2*1+1] = 1.0;  //设置拉普拉斯滤波器
    laplacianKernel[(2*bLineBytes)*1+2*0+1] = 1.0;
    laplacianKernel[(2*bLineBytes)*1+2*1+1] = -4.0;
    laplacianKernel[(2*bLineBytes)*0+2*2+1] = 1.0;
    laplacianKernel[(2*bLineBytes)*2+2*1+1] = 1.0;
    
    //对源图像进行FFT
    fourn(fftSrc,nn,2,1);
    //对卷积核图像进行FFT
    fourn(fftKernel,nn,2,1);
    //对过滤器进行FFT;
    fourn(laplacianKernel,nn,2,1);
    for (int i = 1;i <bHeight*bLineBytes*2;i+=2)
    {
    a = fftSrc[i];
    b = fftSrc[i+1];
    c = fftKernel[i];
    d = fftKernel[i+1];
    e = laplacianKernel[i];
    f = laplacianKernel[i+1];
    //计算|H(u,v)|*|H(u,v)|+r|C(u,v)*C(u,v)|;
    norm1 = c*c + d*d;
    norm2 = e*e + f*f;
    temp = norm1 + norm2*gama;
    if (c*c + d*d > 1e-3)
    {
    fftSrc[i] = ( a*c + b*d ) /temp;
    fftSrc[i+1] = ( b*c - a*d )/temp; 
    }
    }
    
    //对结果图像进行反FFT
    fourn(fftSrc,nn,2,-1);
    //确定归一化因子  
    //图像归一化因子
    MaxNum=0;
    for (int j = 0;j < bHeight ;j++)
    {
    for(int i = 0;i < bLineBytes ;i++)
    {
    fftSrc[(2*bLineBytes)*j + 2*i + 1] = 
    sqrt(fftSrc[(2*bLineBytes)*j + 2*i + 1] * fftSrc[(2*bLineBytes)*j + 2*i + 1]/
    +fftSrc[(2*bLineBytes)*j + 2*i + 2] * fftSrc[(2*bLineBytes)*j + 2*i + 2]);
    if( MaxNum < fftSrc[(2*bLineBytes)*j + 2*i + 1])
    MaxNum = fftSrc[(2*bLineBytes)*j + 2*i + 1];
    }
    }
    //转换为图像
    for (int j = 0;j < bHeight ;j++)
    {
    for(int i = 0;i < bLineBytes ;i++)
    {
    // 指向源图像倒数第j行,第i个象素的指针   
    lpSrc = (char *)greenImage->imageData + bLineBytes * j + i;
    
    *lpSrc = (unsigned char) (fftSrc[(2*bLineBytes)*j + 2*i + 1]*255.0/MaxNum);
    }
    }
    //cvNamedWindow("greenImageDeblur");
    //cvShowImage("greenImageDeblur",greenImage);
    
    //处理绿色通道
    bLineBytes = redImage->widthStep;
    bw = 1;
    bh = 1;
    //保证离散傅里叶变换的宽度和高度为2的整数幂
    while(bw*2 <= bLineBytes)
    {
    bw = bw*2;
    }
    while(bh*2 <= bHeight)
    {
    bh = bh*2;
    }
    //输入退化图像的长和宽必须为2的整数倍;
    if(bw != (int)bLineBytes)
    {
    return;
    }
    if(bh != (int)bHeight)
    {
    return;
    }
    
    //用于做FFT的数组
    // 指向源图像倒数第j行,第i个象素的指针   
    fftSrc = new double [bHeight*bLineBytes*2+1];
    fftKernel = new double [bHeight*bLineBytes*2+1];
    laplacianKernel = new double [bHeight*bLineBytes*2+1];
    CvMat *h_last3;
    CY_special(len,theta,h_last3);
    h_row = h_last3->height;
    h_col = h_last3->width;
    for (int j = 0;j < bHeight ;j++)
    {
    for(int i = 0;i < bLineBytes ;i++)
    {
    // 指向源图像倒数第j行,第i个象素的指针   
    lpSrc = (char *)redImage->imageData + bLineBytes * j + i;
    
    pixel = (unsigned char)*lpSrc;
    
    fftSrc[(2*bLineBytes)*j + 2*i + 1] = (double)pixel;
    fftSrc[(2*bLineBytes)*j + 2*i + 2] = 0.0;
    laplacianKernel[(2*bLineBytes)*j + 2*i + 1] = 0.0;
    laplacianKernel[(2*bLineBytes)*j + 2*i + 2] = 0.0;
    if(i < h_col && j < h_row)
    {
    float h_value = CV_MAT_ELEM(*h_last3,float,j,i);
    fftKernel[(2*bLineBytes)*j + 2*i + 1] = double(h_value);
    }
    else
    {
    fftKernel[(2*bLineBytes)*j + 2*i + 1] = 0.0;
    }
    fftKernel[(2*bLineBytes)*j + 2*i + 2] = 0.0;
    }
    }
    laplacianKernel[(2*bLineBytes)*0+2*1+1] = 1.0;  //设置拉普拉斯滤波器
    laplacianKernel[(2*bLineBytes)*1+2*0+1] = 1.0;
    laplacianKernel[(2*bLineBytes)*1+2*1+1] = -4.0;
    laplacianKernel[(2*bLineBytes)*0+2*2+1] = 1.0;
    laplacianKernel[(2*bLineBytes)*2+2*1+1] = 1.0;
    
    //对源图像进行FFT
    fourn(fftSrc,nn,2,1);
    //对卷积核图像进行FFT
    fourn(fftKernel,nn,2,1);
    //对过滤器进行FFT;
    fourn(laplacianKernel,nn,2,1);
    for (int i = 1;i <bHeight*bLineBytes*2;i+=2)
    {
    a = fftSrc[i];
    b = fftSrc[i+1];
    c = fftKernel[i];
    d = fftKernel[i+1];
    e = laplacianKernel[i];
    f = laplacianKernel[i+1];
    //计算|H(u,v)|*|H(u,v)|+r|C(u,v)*C(u,v)|;
    norm1 = c*c + d*d;
    norm2 = e*e + f*f;
    temp = norm1 + norm2*gama;
    if (c*c + d*d > 1e-3)
    {
    fftSrc[i] = ( a*c + b*d ) /temp;
    fftSrc[i+1] = ( b*c - a*d )/temp; 
    }
    }
    
    //对结果图像进行反FFT
    fourn(fftSrc,nn,2,-1);
    //确定归一化因子  
    //图像归一化因子
    MaxNum=0;
    for (int j = 0;j < bHeight ;j++)
    {
    for(int i = 0;i < bLineBytes ;i++)
    {
    fftSrc[(2*bLineBytes)*j + 2*i + 1] = 
    sqrt(fftSrc[(2*bLineBytes)*j + 2*i + 1] * fftSrc[(2*bLineBytes)*j + 2*i + 1]/
    +fftSrc[(2*bLineBytes)*j + 2*i + 2] * fftSrc[(2*bLineBytes)*j + 2*i + 2]);
    if( MaxNum < fftSrc[(2*bLineBytes)*j + 2*i + 1])
    MaxNum = fftSrc[(2*bLineBytes)*j + 2*i + 1];
    }
    }
    //转换为图像
    for (int j = 0;j < bHeight ;j++)
    {
    for(int i = 0;i < bLineBytes ;i++)
    {
    // 指向源图像倒数第j行,第i个象素的指针   
    lpSrc = (char *)redImage->imageData + bLineBytes * j + i;
    
    *lpSrc = (unsigned char) (fftSrc[(2*bLineBytes)*j + 2*i + 1]*255.0/MaxNum);
    }
    }
    //cvNamedWindow("redImageDeblur");
    //cvShowImage("redImageDeblur",redImage);
    
    IplImage* MergedImage=cvCreateImage(cvGetSize(RGB),IPL_DEPTH_8U,3);  //将分割后的三个通道进行合并
    cvMerge(blueImage,greenImage,redImage,0,MergedImage);  
    
    double durationtime = (double)getTickCount() - startime; 
    printf("  detection time = %g ms\n", durationtime*1000./cv::getTickFrequency()); //calculate the running time
    cvNamedWindow("Merged Image");
    cvShowImage("Merged Image",MergedImage);
    cvWaitKey();
    }
    
    BOOL fourn(double * data/*psrc*/, unsigned long nn[]/*w*/, int ndim/*2*/, int isign)
    {
    int idim;
    unsigned long i1,i2,i3,i2rev,i3rev,ip1,ip2,ip3,ifp1,ifp2;
    unsigned long ibit,k1,k2,n,nprev,nrem,ntot;
    double tempi,tempr;
    double theta,wi,wpi,wpr,wr,wtemp;
    
    for (ntot=1,idim=1;idim<=ndim;idim++)
    ntot *= nn[idim];
    nprev=1;
    for (idim=ndim;idim>=1;idim--) {
    n=nn[idim];
    nrem=ntot/(n*nprev);
    ip1=nprev << 1;
    ip2=ip1*n;
    ip3=ip2*nrem;
    i2rev=1;
    for (i2=1;i2<=ip2;i2+=ip1) {
    if (i2  < i2rev) {
    for (i1=i2;i1<=i2+ip1-2;i1+=2) {
    for (i3=i1;i3<=ip3;i3+=ip2) {
    i3rev=i2rev+i3-i2;
    SWAP(data[i3],data[i3rev]);
    SWAP(data[i3+1],data[i3rev+1]);
    }
    }
    }
    ibit=ip2 >> 1;
    while (ibit >= ip1 && i2rev > ibit) {
    i2rev -= ibit;
    ibit >>= 1;
    }
    i2rev += ibit;
    }
    ifp1=ip1;
    while (ifp1 < ip2) {
    ifp2=ifp1 << 1;
    theta=isign*6.28318530717959/(ifp2/ip1);
    wtemp=sin(0.5*theta);
    wpr = -2.0*wtemp*wtemp;
    wpi=sin(theta);
    wr=1.0;
    wi=0.0;
    for (i3=1;i3<=ifp1;i3+=ip1) {
    for (i1=i3;i1<=i3+ip1-2;i1+=2) {
    for (i2=i1;i2<=ip3;i2+=ifp2) {
    k1=i2;
    k2=k1+ifp1;
    tempr=wr*data[k2]-wi*data[k2+1];
    tempi=wr*data[k2+1]+wi*data[k2];
    data[k2]=data[k1]-tempr;
    data[k2+1]=data[k1+1]-tempi;
    data[k1] += tempr;
    data[k1+1] += tempi;
    }
    }
    wr=(wtemp=wr)*wpr-wi*wpi+wr;
    wi=wi*wpr+wtemp*wpi+wi;
    }
    ifp1=ifp2;
    }
    nprev *= n;
    }
    return true;
    }
    void CY_special(double len,double theta,CvMat *&h_last)
    {
    len = double(max(len,1.0));
    double half = (len - 1)/2;
    double phi = theta/180.0*pi;
    double cosphi = cos(phi);
    double sinphi = sin(phi);
    double xsign = CY_sign(cosphi);
    double linewdt = 1.0;
    double sx = half*cosphi + linewdt*xsign - len*eps;
    sx = cvFloor(sx);
    double sy = half*sinphi +linewdt - len*eps;
    sy = cvFloor(sy);
    CvMat *X,*Y;
    CYmeshgrid(0,int(sy),0,int(sx),X,Y);
    int row = X->height;
    int col = X->width;
    CvMat *dist2line = cvCreateMat(row,col,CV_32FC1);
    CvMat *rad = cvCreateMat(row,col,CV_32FC1);
    CvMat *h = cvCreateMat(row,col,CV_32FC1);
    cvZero(dist2line);
    cvAddWeighted(Y,cosphi,X,-sinphi,0,dist2line);
    cvCartToPolar(X,Y,rad,NULL,0);
    for(int i = 0;i<row;i++)
    {
    for(int j = 0;j<col;j++)
    {
    float temp1 = CV_MAT_ELEM(*rad,float,i,j);
    float temp2 = CV_MAT_ELEM(*dist2line,float,i,j);
    temp2 = abs(temp2);
    if(temp1 >= half && temp2 <= linewdt)
    {
    float x_value = CV_MAT_ELEM(*X,float,i,j);
    float dist_value = CV_MAT_ELEM(*dist2line,float,i,j);
    float dist_value1 = (x_value + dist_value*float(sinphi))/float(cosphi);
    float x2lastpix_cy1 =  float(half) - abs(dist_value1);
    float cy = dist_value*dist_value + x2lastpix_cy1*x2lastpix_cy1;
    float cy1 = cvSqrt(cy);
    cvmSet(dist2line,i,j,cy1);
    }
    }
    }
    for(int i = 0;i<row;i++)
    {
    for(int j = 0;j<col;j++)
    {
    float cy2 = CV_MAT_ELEM(*dist2line,float,i,j);
    cy2 = float(linewdt) + float(0.00000000001) - abs(cy2);
    cvmSet(dist2line,i,j,cy2);
    if(cy2<0)
    {
    cvmSet(dist2line,i,j,0.0);
    }
    }
    }
    cvFlip(dist2line,h,1);
    cvFlip(h,NULL,0);
    int row_h = row + row - 1;
    int col_h = col + col - 1;
    //CvMat *h_last = cvCreateMat(row_h,col_h,CV_32FC1);
    h_last = cvCreateMat(row_h,col_h,CV_32FC1);
    cvZero(h_last);
    for(int i = 0;i<row;i++)
    {
    for(int j = 0;j<col;j++)
    {
    float h_value = CV_MAT_ELEM(*h,float,i,j);
    cvmSet(h_last,i,j,h_value);
    }
    }
    //将dist2line中的值赋给扩大后的h矩阵中的相应位置
    int p =0;
    for(int i = row-1;i<row_h;i++)
    {
    int q =0;
    for(int j = col-1;j<col_h;j++)
    {
    float h_temp = CV_MAT_ELEM(*dist2line,float,p,q);
    cvmSet(h_last,i,j,h_temp);
    q++;
    }
    p++;
    }
    double yao_value = len*len*eps;
    CvScalar sum = cvSum(h_last);
    double yao_sum = sum.val[0];
    double yaoyao = 1/(yao_value + yao_sum);
    cvConvertScale(h_last,h_last,yaoyao,0);
    if(cosphi > 0)
    {
    cvFlip(h_last,NULL,0);
    }
    }
    
    double CY_sign(double cosphi)
    {
    double dst_value = 0;
    if(cosphi>0)
    {
    dst_value = 1;
    }
    else
    {
    dst_value = -1;
    }
    return dst_value;
    }
    
    void CYmeshgrid(int xm,int xn,int ym,int yn,CvMat* &X,CvMat* &Y)
    {
    int m=xn-xm+1;
    int n=yn-ym+1;
    X=cvCreateMat(m,n,CV_32FC1);
    Y=cvCreateMat(m,n,CV_32FC1);
    float cy2=float(xm);
    for(int i=0;i<m;i++)
    {
    float cy1=float(xm);
    for(int j=0;j<n;j++)
    {
    cvmSet(X,i,j,cy1);
    cvmSet(Y,i,j,cy2);
    cy1=cy1+1;
    }
    cy2=cy2+1;
    }
    }

    原模糊图像
    维纳滤波结果

    展开全文
  • 有段时间需要做图像复原的研究,就用了平时用的比较多的MATLAB平台。利用的是MATLAB的工具箱,但各个参数的设置我都研究了一段时间,也参考了萨冈雷斯的关于图像处理的著作。程序前半部分不含噪声用了四种滤波法,后...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 147
精华内容 58
关键字:

运动模糊图像复原