点扩散函数

  • PSF是point spread function的简称,即点扩散函数,用该指标来衡量重建后的图像的分辨率。
  • 在线性系统中,对于任意成像目标I1和其对应的像I2可以表示成I2=I1*h,h是系统函数。这个卷积系数h就是PSF,因为当I1为冲击函数时,I2=h。I2的质量取决于h。当h越偏离冲击函数,I2就越模糊,其模糊程度可以用h的宽度来衡量,h越宽,I2越模糊。
  • 空间分辨率定义为,能够区分两个不同点的最小间隔。PSF的宽度决定了重建图像的空间分辨率。对于从傅里叶域采样重建的图像,其分辨率取决于傅里叶域的分辨率,无论在重建后图像域中采样何种差值或补零方案,都不能提高图像的空间分辨率。

psf2otf函数解释

  • psf2otf()函数,可以将小尺寸的点扩散函数进行尺寸扩大,并作二维傅里叶变换。
  • 把一个空间点扩散函数转换为频谱面的光学传递函数。
  • OTF = psf2otf(PSF):利用快速傅立叶变换(FFT)实现将点扩散函数(PSF)矩阵转换为光学传输函数矩阵OTF,不受PSF偏心的影响。默认情况下,OTF阵列的大小与PSF阵列的大小相同。
  • OTF = psf2otf(PSF,OUTSIZE):将PSF矩阵转换为OTF矩阵,其中OUTSIZE指定OTF阵列的大小。 OUTSIZE不可以
    小于任何尺寸的PSF阵列尺寸。
  • 请注意,当操作涉及FFT时,此功能用于图像卷积/反卷积。

psf2otf函数与fft2函数的不同

  • 首先我们生成PSF函数(其实就是空间卷积),即生成一个拉普拉斯模板
  • 对l进行傅里叶变换,这里选择m,n都是3
  • 使用psf2otf函数,其操作效果如下

如何消除差异

为确保因PSF偏心而不改变OTF,psf2otf将PSF阵列(向下或向右)后缀为0匹配OUTSIZE中指定的尺寸,然后循环移动
PSF阵列的值向上(或向左)直到中心像素到达(1,1)位置。

  • 将l的中心元素移动到矩阵的左上角
  • 进行fft变换

源码

(1)c++实现源码

//实现FFT变换
Mat psf2otf(Mat psf, Size size)
{//定义生成的目标矩阵Mat otf = Mat::zeros(size.height, size.width, psf.type());//定义点扩散函数的大小Size dftSize;//计算DFT变换的大小dftSize.width = getOptimalDFTSize(size.width);dftSize.height = getOptimalDFTSize(size.height);//定义一个临时缓存Mat temp = Mat::zeros(dftSize, psf.type());//将psf拷贝到temp矩阵的左上角Mat psfROI(temp, Rect(0, 0, psf.cols, psf.rows));psf.copyTo(psfROI);//循环平移otf,为了使psf中心点移动到矩阵(0, 0)的位置Mat psf2 = temp.clone();//计算水平移动位置int cx = psf.cols / 2;//计算垂直移动位置int cy = psf.rows / 2;//Create Left-Top ROIMat p0(temp, Rect(0, 0, cx, cy));//Create Right-TOP ROIMat p1(temp, Rect(cx, 0, psf2.cols - cx, cy));//Create Left-Bottom ROIMat p2(temp, Rect(0, cy, cx, psf2.rows - cy));//Create Right-Bottom ROIMat p3(temp, Rect(cx, cy, psf2.cols - cx, psf2.rows - cy));//Create Left-Top ROIMat q0(psf2, Rect(0, 0, psf2.cols - cx, psf2.rows - cy));//Create Right-TOP ROIMat q1(psf2, Rect(psf2.cols - cx, 0, cx, psf2.rows - cy));//Create Left-Bottom ROIMat q2(psf2, Rect(0, psf2.rows - cy, psf2.cols - cx, cy));//Create Right-Bottom ROIMat q3(psf2, Rect(psf2.cols - cx, psf2.rows - cy, cx, cy));//swap quadrants (Top-Left with Bottom-Right)p0.copyTo(q3);p3.copyTo(q0);//swap quadrant (Top-Right with Bottom-Left)p1.copyTo(q2);p2.copyTo(q1);//Computer the OTFMat planes[] = { Mat_<float>(psf2), Mat::zeros(psf2.size(), CV_32F) };Mat complexI;//建立DFT所需要的参数merge(planes, 2, complexI);//进行DFT计算dft(complexI, complexI);//获取计算结果otf = complexI;//返回用户定义的结果return otf(Range(0, size.height), Range(0, size.width));
}

(2)matlb实现源码

[psf, psfSize, outSize] = ParseInputs(varargin{:});if  ~all(psf(:)==0),% Pad the PSF to outSizepadSize = outSize - psfSize;psf     = padarray(psf, padSize, 'post');% Circularly shift otf so that the "center" of the PSF is at the% (1,1) element of the array.psf    = circshift(psf,-floor(psfSize/2));% Compute the OTFotf = fftn(psf);% Estimate the rough number of operations involved in the % computation of the FFT.nElem = prod(psfSize);nOps  = 0;for k=1:ndims(psf)nffts = nElem/psfSize(k);nOps  = nOps + psfSize(k)*log2(psfSize(k))*nffts; end% Discard the imaginary part of the psf if it's within roundoff error.if max(abs(imag(otf(:))))/max(abs(otf(:))) <= nOps*epsotf = real(otf);end
elseotf = zeros(outSize);
end

注意

OpenCV中傅里叶变换输出有两种格式 全复数输出(full-complex output,占用两个矩阵大小)和复数共轭对称压缩输出(Complex Conjugate Symmetric (CCS) packed output,一个矩阵大小) 。

参考网址

https://blog.csdn.net/bluecol/article/details/48288739

https://blog.csdn.net/huang1024rui/article/details/50318647

http://prog3.com/sbdm/blog/bluecol/article/details/49046219

https://blog.csdn.net/bluecol/article/details/49046219

基于C++的psf2otf实现相关推荐

  1. 基于Golang的简单web服务程序开发——CloudGo

    基于Golang的简单web服务程序开发--CloudGo[阅读时间:约10分钟] 一.概述 二.系统环境&项目介绍 1.系统环境 2.项目的任务要求 (1)基本要求 (2)扩展要求 三.具体 ...

  2. 【ReactiveX】基于Golang pmlpml/RxGo程序包的二次开发

    基于Golang pmlpml/RxGo程序包的二次开发[阅读时间:约20分钟] 一.ReactiveX & RxGo介绍 1.ReactiveX 2.RxGo 二.系统环境&项目介绍 ...

  3. 基于Golang的对象序列化的程序包开发——myJsonMarshal

    基于Golang的对象序列化的程序包开发--myJsonMarshal[阅读时间:约10分钟] 一.对象序列化概述 二.系统环境&项目介绍 1.系统环境 2.项目的任务要求 三.具体程序设计及 ...

  4. 基于Golang的监听读取配置文件的程序包开发——simpleConfig_v1

    基于Golang的监听&读取配置文件的程序包开发--simpleConfig_v1 [阅读时间:约10分钟] 一.配置文件概述 二.系统环境&项目介绍 1.系统环境 2.项目的任务要求 ...

  5. 基于Golang的CLI 命令行程序开发

    基于Golang的CLI 命令行程序开发 [阅读时间:约15分钟] 一. CLI 命令行程序概述 二. 系统环境&项目介绍&开发准备 1.系统环境 2.项目介绍 3.开发准备 三.具体 ...

  6. etcd 笔记(08)— 基于 etcd 实现分布式锁

    1. 为什么需要分布式锁? 在分布式环境下,数据一致性问题一直是个难点.分布式与单机环境最大的不同在于它不是多线程而是多进程.由于多线程可以共享堆内存,因此可以简单地采取内存作为标记存储位置.而多进程 ...

  7. OpenCV 笔记(08)— 二维点、三维点、基于 Mat 的 std::vector 等常用数据结构的定义和输出

    1. 定义和输出二维点 Point2f p2(3, 4);cout << "[二维点] is "<< endl << p2 << e ...

  8. python中的新式类与旧式类的一些基于descriptor的概念(下)

    3. Descriptor介绍 3.1 Descriptor代码示例 3.2 定义 3.3 Descriptor Protocol(协议) 3.4 Descriptor调用方法 4. 基于Descri ...

  9. python中的新式类与旧式类的一些基于descriptor的概念(上)

    python中基于descriptor的一些概念(上) 1. 前言 2. 新式类与经典类 2.1 内置的object对象 2.2 类的方法 2.2.1 静态方法 2.2.2 类方法 2.3 新式类(n ...

  10. 【Spring】spring基于注解的声明式事务控制

    结构 domin package com.itheima.domain;import java.io.Serializable;public class Account implements Seri ...

最新文章

  1. oracle crm版本,ORACLE CRM ON DEMAND 19 版
  2. linux打补丁前如何备份,关于Linux下给文件打补丁
  3. 1.IDA-基本操作(改变Image Base地址、打开、保存IDA的不同方式)
  4. How to ignore files and directories in subversion?
  5. 提升业务价值 APM应用与整合分享
  6. phpMyAdmin ‘tbl_gis_visualization.php’多个跨站脚本漏洞
  7. A Style-Based Generator Architecture for Generative Adversarial Networks---阅读笔记
  8. WPF管理系统自定义分页控件 - WPF特工队内部资料
  9. java 文件编码_Java获取文件编码
  10. android浏览器病毒,2018安卓手机杀毒软件排行榜
  11. Vbs脚本编程简明教程之十五
  12. 数据库基础学习(思维导图)
  13. Doc2Vec模型介绍及使用
  14. linux安装vscode(中标麒麟+龙芯CPU)
  15. 知道注册电子邮件的方法么?今天就告诉你邮箱申请免费注册的方法!
  16. 线代:1.7矩阵对角化二次型
  17. spider_study 1
  18. 绪论--《可以量化的经济学》
  19. 【电商】电商后台设计—购物车
  20. 场效应三极管及其放大电路(1)MOSFET详解

热门文章

  1. 房租,社会教给年轻人的第一课
  2. 七夕节程序员应有的表白方式
  3. 【抽象代数】环、子环、理想、商环、环的同态
  4. 【学懂数据结构】二叉树之舞之二叉树
  5. 万字吐血好文,一线分析师的4大总结。
  6. z5s+android+4.4,中兴NX403a(Nubia Z5S Mini Android 4.4)刷Recovery教程
  7. Android 报错:Entry name 'AndroidManifest.xml' collided
  8. 2019第十二届全国大学生信息安全竞赛部分WriteUp
  9. html火焰字效果,火焰字,通过PS的自带滤镜制作火焰效果文字
  10. 揭开均线系统的神秘面纱_揭开极限编程的神秘面纱,重新探讨“ XP蒸馏”,第3部分...