基于C++的psf2otf实现
点扩散函数
- 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实现相关推荐
- 基于Golang的简单web服务程序开发——CloudGo
基于Golang的简单web服务程序开发--CloudGo[阅读时间:约10分钟] 一.概述 二.系统环境&项目介绍 1.系统环境 2.项目的任务要求 (1)基本要求 (2)扩展要求 三.具体 ...
- 【ReactiveX】基于Golang pmlpml/RxGo程序包的二次开发
基于Golang pmlpml/RxGo程序包的二次开发[阅读时间:约20分钟] 一.ReactiveX & RxGo介绍 1.ReactiveX 2.RxGo 二.系统环境&项目介绍 ...
- 基于Golang的对象序列化的程序包开发——myJsonMarshal
基于Golang的对象序列化的程序包开发--myJsonMarshal[阅读时间:约10分钟] 一.对象序列化概述 二.系统环境&项目介绍 1.系统环境 2.项目的任务要求 三.具体程序设计及 ...
- 基于Golang的监听读取配置文件的程序包开发——simpleConfig_v1
基于Golang的监听&读取配置文件的程序包开发--simpleConfig_v1 [阅读时间:约10分钟] 一.配置文件概述 二.系统环境&项目介绍 1.系统环境 2.项目的任务要求 ...
- 基于Golang的CLI 命令行程序开发
基于Golang的CLI 命令行程序开发 [阅读时间:约15分钟] 一. CLI 命令行程序概述 二. 系统环境&项目介绍&开发准备 1.系统环境 2.项目介绍 3.开发准备 三.具体 ...
- etcd 笔记(08)— 基于 etcd 实现分布式锁
1. 为什么需要分布式锁? 在分布式环境下,数据一致性问题一直是个难点.分布式与单机环境最大的不同在于它不是多线程而是多进程.由于多线程可以共享堆内存,因此可以简单地采取内存作为标记存储位置.而多进程 ...
- OpenCV 笔记(08)— 二维点、三维点、基于 Mat 的 std::vector 等常用数据结构的定义和输出
1. 定义和输出二维点 Point2f p2(3, 4);cout << "[二维点] is "<< endl << p2 << e ...
- python中的新式类与旧式类的一些基于descriptor的概念(下)
3. Descriptor介绍 3.1 Descriptor代码示例 3.2 定义 3.3 Descriptor Protocol(协议) 3.4 Descriptor调用方法 4. 基于Descri ...
- python中的新式类与旧式类的一些基于descriptor的概念(上)
python中基于descriptor的一些概念(上) 1. 前言 2. 新式类与经典类 2.1 内置的object对象 2.2 类的方法 2.2.1 静态方法 2.2.2 类方法 2.3 新式类(n ...
- 【Spring】spring基于注解的声明式事务控制
结构 domin package com.itheima.domain;import java.io.Serializable;public class Account implements Seri ...
最新文章
- oracle crm版本,ORACLE CRM ON DEMAND 19 版
- linux打补丁前如何备份,关于Linux下给文件打补丁
- 1.IDA-基本操作(改变Image Base地址、打开、保存IDA的不同方式)
- How to ignore files and directories in subversion?
- 提升业务价值 APM应用与整合分享
- phpMyAdmin ‘tbl_gis_visualization.php’多个跨站脚本漏洞
- A Style-Based Generator Architecture for Generative Adversarial Networks---阅读笔记
- WPF管理系统自定义分页控件 - WPF特工队内部资料
- java 文件编码_Java获取文件编码
- android浏览器病毒,2018安卓手机杀毒软件排行榜
- Vbs脚本编程简明教程之十五
- 数据库基础学习(思维导图)
- Doc2Vec模型介绍及使用
- linux安装vscode(中标麒麟+龙芯CPU)
- 知道注册电子邮件的方法么?今天就告诉你邮箱申请免费注册的方法!
- 线代:1.7矩阵对角化二次型
- spider_study 1
- 绪论--《可以量化的经济学》
- 【电商】电商后台设计—购物车
- 场效应三极管及其放大电路(1)MOSFET详解
热门文章
- 房租,社会教给年轻人的第一课
- 七夕节程序员应有的表白方式
- 【抽象代数】环、子环、理想、商环、环的同态
- 【学懂数据结构】二叉树之舞之二叉树
- 万字吐血好文,一线分析师的4大总结。
- z5s+android+4.4,中兴NX403a(Nubia Z5S Mini Android 4.4)刷Recovery教程
- Android 报错:Entry name 'AndroidManifest.xml' collided
- 2019第十二届全国大学生信息安全竞赛部分WriteUp
- html火焰字效果,火焰字,通过PS的自带滤镜制作火焰效果文字
- 揭开均线系统的神秘面纱_揭开极限编程的神秘面纱,重新探讨“ XP蒸馏”,第3部分...