├── BeamForming_PACK_python ├── BeamFormingPyProject │ ├── env │ │ ├── Ei_amplitude.csv │ │ ├── Ei_phase.csv │ │ └── phi_mask.csv │ ├── img │ │ ├── baboon.tif │ │ └── peppers.tif │ └── source │ │ ├── __main__.py │ │ ├── __pycache__ │ │ └── aux_tools.cpython-37.pyc │ │ └── aux_tools.py ├── LICENSE ├── PKG-INFO ├── README.md └── setup.py ├── LICENSE.md ├── README.md ├── env ├── B.mat └── tau.mat ├── img ├── amplitude_Et.tif ├── amplitude_T.tif ├── baboon.tif ├── peppers.tif ├── phase_Et.tif └── phase_T.tif └── source ├── FFT2.m ├── PR.m ├── define_T.m ├── format_subplot.m ├── iFFT2.m ├── main.m ├── speckle_gen.m └── ssim_index.m /BeamForming_PACK_python/BeamFormingPyProject/img/baboon.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grupolatof/phase-retrieval-algorithm/8fc8bd2331238340a0aa1e5b957cf86f6128a32f/BeamForming_PACK_python/BeamFormingPyProject/img/baboon.tif -------------------------------------------------------------------------------- /BeamForming_PACK_python/BeamFormingPyProject/img/peppers.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grupolatof/phase-retrieval-algorithm/8fc8bd2331238340a0aa1e5b957cf86f6128a32f/BeamForming_PACK_python/BeamFormingPyProject/img/peppers.tif -------------------------------------------------------------------------------- /BeamForming_PACK_python/BeamFormingPyProject/source/__main__.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from aux_tools import PR, define_T, FFT2, mat2level 3 | import matplotlib 4 | import matplotlib.pyplot as plt 5 | import matplotlib.gridspec as gridspec 6 | import matplotlib.figure as Figure 7 | from pathlib import Path 8 | from SSIM_PIL import compare_ssim 9 | from PIL import Image 10 | import csv 11 | 12 | # Initialization 13 | [Ei,Et,t,b,thresh,Nx,Ny,NLx,NLy,OffsetX,OffsetY,steps] = define_T() 14 | 15 | # Iterative algorithm for phase retrieval PR 16 | [tau,rms_angle,rms_fourier,steps] = PR(Ei,Et,thresh,b,t,NLx,NLy,steps) 17 | 18 | 19 | # Results ##################################################################################### 20 | 21 | # E is the final field projected by using the obtained phase mask tau, and the incidente field Ei. 22 | phi_mask=np.arctan2(np.imag(tau),np.real(tau)) 23 | 24 | E=FFT2(Ei*np.power(np.e,1j*phi_mask)) 25 | des_y = int(Ny/2-NLy/2+OffsetY) 26 | has_y = int(Ny/2+NLy/2+OffsetY) 27 | des_x = int(Nx/2-NLx/2+OffsetX) 28 | has_x = int(Nx/2+NLx/2+OffsetX) 29 | E_final=E[des_y:has_y,des_x:has_x] 30 | 31 | cm = 'jet' 32 | fig = plt.figure(constrained_layout=True) 33 | gs0 = gridspec.GridSpec(2, 1, figure=fig) # 1 fila, 2 columnas 34 | gs1 = gridspec.GridSpecFromSubplotSpec(1, 4, subplot_spec=gs0[0,0]) 35 | 36 | ax = fig.add_subplot(gs1[0]) 37 | plt.title('Recovered Amplitude') 38 | L=np.abs(E_final) 39 | pcm = ax.pcolormesh(np.flipud(L), cmap=cm) 40 | fig.colorbar(pcm, ax=ax) 41 | plt.axis('off') 42 | 43 | ax = fig.add_subplot(gs1[1]) 44 | plt.title('Target Amplitude') 45 | Lt=np.abs(Et[des_y:has_y,des_x:has_x]) 46 | pcm = ax.pcolormesh(np.flipud(Lt), cmap=cm) 47 | fig.colorbar(pcm, ax=ax) 48 | plt.axis('off') 49 | 50 | ax = fig.add_subplot(gs1[2]) 51 | plt.title('Recovered Phase') 52 | Lr=np.arctan2(np.imag(E_final),np.real(E_final)) 53 | pcm = ax.pcolormesh(np.flipud(Lr), cmap=cm) 54 | fig.colorbar(pcm, ax=ax) 55 | plt.axis('off') 56 | 57 | ax = fig.add_subplot(gs1[3]) 58 | plt.title('Target Phase') 59 | Lp=np.arctan2(np.imag(Et[des_y:has_y,des_x:has_x]),np.real(Et[des_y:has_y,des_x:has_x])) 60 | pcm = ax.pcolormesh(np.flipud(Lp), cmap=cm) 61 | fig.colorbar(pcm, ax=ax) 62 | plt.axis('off') 63 | 64 | # Convergence analysis 65 | Iteration = np.linspace(0, steps, steps) 66 | 67 | gs2 = gridspec.GridSpecFromSubplotSpec(1, 2, subplot_spec=gs0[1,0]) 68 | 69 | fig.add_subplot(gs2[0]) # In phase 70 | plt.title('Phase Convergence') 71 | plt.plot(Iteration, rms_angle) 72 | plt.xlabel('Iteration Number') 73 | plt.ylabel('RMS_phase(dB)') 74 | 75 | fig.add_subplot(gs2[1]) # In amplitude 76 | plt.title('Amplitude Convergence') 77 | plt.plot(Iteration, rms_fourier) 78 | plt.xlabel('Iteration Number') 79 | plt.ylabel('RMS_amplitude(dB)') 80 | 81 | plt.show() 82 | 83 | # Comparison of two images using the structural similarity algorithm (SSIM). 84 | # https://pypi.org/project/SSIM-PIL/ 85 | 86 | # Amplitude comparison using SSIM: 87 | image_target = Image.fromarray((mat2level(Lt)*255).astype(int), 'L') 88 | image_recovered = Image.fromarray((mat2level(np.abs(E_final))*255).astype(int), 'L') 89 | value = compare_ssim(image_target, image_recovered) 90 | print('\n',"The SSIM index value for amplitude calculation is Q = ",'{:f}'.format(value)) 91 | 92 | # Phase comparison using SSIM: 93 | image_target = Image.fromarray((mat2level(Lp)*255).astype(int), 'L') 94 | image_recovered = Image.fromarray((mat2level(Lr)*255).astype(int), 'L') 95 | value = compare_ssim(image_target, image_recovered) 96 | print('\n',"The SSIM index value for phase calculation is Q = ",'{:f}'.format(value),'\n') 97 | 98 | # Save results in cvs files ################################################################################################################## 99 | input = str(input("Save values of the obtained phase-mask and the input field Ei? Y/[N] = ")) 100 | if input=='Y': 101 | 102 | out_file_phi_mask = Path.cwd() / "env" / "phi_mask.csv" 103 | out_file_Ei_amplitude = Path.cwd() / "env" / "Ei_amplitude.csv" 104 | out_file_Ei_phase = Path.cwd() / "env" / "Ei_phase.csv" 105 | 106 | # Save the recovered phase mask 107 | with open(out_file_phi_mask, 'w', newline='') as f: 108 | writer = csv.writer(f) 109 | writer.writerows(phi_mask) 110 | 111 | # Save the input amplitude field Ei 112 | with open(out_file_Ei_amplitude, 'w', newline='') as f: 113 | writer = csv.writer(f) 114 | writer.writerows(np.abs(Ei)) 115 | 116 | # Save the input phase field Ei 117 | with open(out_file_Ei_phase, 'w', newline='') as f: 118 | writer = csv.writer(f) 119 | writer.writerows(np.arctan2(np.imag(Ei),np.real(Ei))) 120 | -------------------------------------------------------------------------------- /BeamForming_PACK_python/BeamFormingPyProject/source/__pycache__/aux_tools.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grupolatof/phase-retrieval-algorithm/8fc8bd2331238340a0aa1e5b957cf86f6128a32f/BeamForming_PACK_python/BeamFormingPyProject/source/__pycache__/aux_tools.cpython-37.pyc -------------------------------------------------------------------------------- /BeamForming_PACK_python/BeamFormingPyProject/source/aux_tools.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from scipy.fftpack import fftshift, ifftshift 3 | from tqdm import tqdm 4 | from PIL import Image # Python Imaging Library 5 | from pathlib import Path 6 | 7 | 8 | # Faster Fourier transform functions from the pyfftw module if 9 | # available 10 | try: 11 | from pyfftw.interfaces.scipy_fftpack import fft2, ifft2 12 | # Otherwise use the normal scipy fftpack 13 | except ImportError: 14 | import warnings 15 | warnings.warn(""" 16 | Module 'pyfftw' could not be imported. Try 17 | 'pip install pyfftw' from the Terminal. Default used, 18 | 'fftpack' module for 2D Fourier transforms.""") 19 | from scipy.fftpack import fft2, ifft2 20 | 21 | # Balanced Fast Fourier Transform. 22 | def FFT2(I): 23 | [Ny,Nx]=np.shape(I) 24 | FT=fftshift(fft2(ifftshift(I)))/np.sqrt(Ny)/np.sqrt(Nx) 25 | return FT 26 | 27 | # Balanced Inverse Fast Fourier Transform. 28 | def iFFT2(FT): 29 | [Ny,Nx]=np.shape(FT) 30 | I=fftshift(ifft2(ifftshift(FT)))*np.sqrt(Ny)*np.sqrt(Nx) 31 | return I 32 | 33 | # Converts the matrix I to the intensity array F with values in the range [0,1]. 34 | def mat2level(I): 35 | I=np.array(I) 36 | I_Max = np.amax(I) 37 | I_Min = np.amin(I) 38 | Dim=np.shape(I) 39 | Ones = np.ones(Dim,dtype=np.float64) 40 | F = (I-Ones*I_Min)/(I_Max-I_Min) 41 | return(F) 42 | 43 | # Generate SF 44 | def speckle_gen(fsp,Ny,Nx): 45 | '''Function to generate an speckle field 46 | input = {fsp, Ny, Nx}. 47 | fsp: is the pixels-radius of the frequency filter. 48 | output = speckle field U 49 | Date: 06/10/2019 50 | Authors: A. Federico - M. Yommi 51 | ''' 52 | 53 | # Arbitrary randon phases 54 | np.random.seed(22) 55 | fi = np.random.uniform(-np.pi,np.pi,(Ny,Nx)) 56 | U = np.power(np.e,1j*fi) 57 | IF0 = FFT2(U) 58 | ny=np.array(np.linspace(-Ny/2,Ny/2,Ny)) 59 | nx=np.array(np.linspace(-Nx/2,Nx/2,Nx)) 60 | [x,y] = np.meshgrid(nx,ny) 61 | a=np.sqrt(np.multiply(y,y)+np.multiply(x,x)) 62 | b=np.where(a>fsp,0,a) # lowpass filter 63 | U = iFFT2(np.multiply(IF0,b)) # generated speckle field 64 | return(U) 65 | 66 | # Iterative algorithm for the Phase Retrieval procedure (Algorithm 1, see Letter for description) 67 | def PR(Ei,Et,thresh,b,t,NLx,NLy,steps): 68 | ''' Iterative phase retrieval algorithm based on alternating projections. Algorithm 1. 69 | Find tau for input arguments: Ei,Et,thresh,gamma,t,NLx,NLy 70 | input = Ei,Et,thresh,gamma,t,NLx,NLy 71 | outputs = tau (phase mask), RMS values: rms_angle (phase),rms_fourier(intensity) 72 | Date: 10/30/2019 73 | Authors: A. Federico - M. Yommi''' 74 | 75 | # Progress bar implementation 76 | loop=tqdm(total=steps,position=0) 77 | 78 | T = iFFT2(Et) 79 | Dim=np.shape(T) 80 | 81 | rms_fourier=[] 82 | rms_angle=[] 83 | np.random.seed(33) 84 | phi = np.random.uniform(-np.pi,np.pi,Dim) 85 | Ai = np.abs(Ei) 86 | 87 | for k in range(0,steps,1): 88 | loop.set_description("Processing ...",format(k)) 89 | loop.update(1) 90 | 91 | c = T*np.power(np.e,-1j*phi)+np.conj(T)*np.power(np.e,1j*phi) 92 | B0 = (-c+np.sqrt(np.multiply(c,c)-4*(np.multiply(np.abs(T),np.abs(T))-np.multiply(Ai,Ai))))/2 # positive solution 93 | B = iFFT2(FFT2(T+B0*np.power(np.e,1j*phi))*b) 94 | phi=np.arctan2(np.imag(B),np.real(B)) 95 | tau = (T+B0*np.power(np.e,1j*phi))*np.power(Ei,-1) 96 | S = FFT2(tau*Ei) 97 | 98 | df=np.abs(Et)-np.abs(S) 99 | df=np.multiply(df,df)*t 100 | rms_f=np.log10(df.sum()/NLy/NLx) 101 | 102 | da=np.arctan2(np.imag(S),np.real(S))-np.arctan2(np.imag(Et),np.real(Et)) 103 | da=np.multiply(da,da)*t 104 | rms_a=np.log10(da.sum()/NLy/NLx) 105 | 106 | rms_fourier.append(rms_f) 107 | rms_angle.append(rms_a) 108 | 109 | if np.abs(rms_a) > thresh: 110 | steps=k+1 111 | break 112 | 113 | loop.close() 114 | return(tau,rms_angle,rms_fourier,steps) 115 | 116 | # Define T function 117 | def define_T(): 118 | ''' [T,Et,circ_in,circ_outside,domain] = define_T() 119 | Function to define T = IFFT[Et*t] (see Letter) 120 | input = none 121 | outputs: 122 | Ei, incidente complex input random field 123 | Et, target field 124 | t, target domain where Et is active 125 | b, exterior set of t 126 | thresh, value to stop the phase retrieval process 127 | Nx,Ny, dimension of the calculated mask 128 | NLx,NLy, dimension of the target field 129 | OffsetX,OffsetY, displacement of the origin for order zero problem 130 | steps, maximum number of iterations 131 | Date: 05/30/2019 132 | Authors: A. Federico - M. Yommi ''' 133 | 134 | # Input conditions 135 | # Maximum mplitude of the Incident field 136 | Amp_Ei = 16 # alpha value relationship 137 | 138 | # Size of the target field Er 139 | NLy = 128 140 | NLx = NLy 141 | 142 | # Size of the phase-only mask tau 143 | Nx = 270 144 | Ny = 320 145 | 146 | # Target field 147 | OffsetX = 0 # 72; % zero order compensation 148 | OffsetY = 0 # 97; 149 | 150 | # Threshold settings 151 | thresh = 20 # phase retrieval comparison 152 | 153 | # Maximum iteration number 154 | steps = 1000 155 | 156 | # Incident random field generation (speckle field) 157 | np.random.seed(17) 158 | phi_u=np.random.uniform(-np.pi,np.pi,[Ny,Nx]) 159 | U = speckle_gen(135,Ny,Nx) 160 | AS = np.amax(np.abs(U)) 161 | U = np.abs(U)/AS 162 | Ei = Amp_Ei*U*np.power(np.e,1j*phi_u) 163 | 164 | # Domains and field target definitions 165 | uno = np.ones((Ny,Nx),dtype=np.float64) 166 | t = np.zeros((Ny,Nx),dtype=np.float64) 167 | des_y = int(Ny/2-NLy/2+OffsetY) 168 | has_y = int(Ny/2+NLy/2+OffsetY) 169 | des_x = int(Nx/2-NLx/2+OffsetX) 170 | has_x = int(Nx/2+NLx/2+OffsetX) 171 | 172 | t[des_y:has_y,des_x:has_x] = np.ones((NLy,NLx),dtype=np.float64) 173 | b = uno-t 174 | 175 | # Use BeamFormingPyProject as the default folder 176 | in_file_peppers = Path.cwd() / "img" / "peppers.tif" 177 | in_file_baboon = Path.cwd() / "img" / "baboon.tif" 178 | 179 | A_t = np.zeros((Ny,Nx),dtype=np.float64) 180 | L = Image.open(in_file_peppers) 181 | L1 = L.convert('F') # 'F': 32-bit floating point scale mode 182 | peppers = mat2level(L1) 183 | 184 | Phi_t = np.zeros((Ny,Nx),dtype=np.float64) 185 | L = Image.open(in_file_baboon) 186 | L2 = L.convert('F') # 'F': 32-bit floating point scale mode 187 | baboon = mat2level(L2)*2*np.pi-np.pi 188 | 189 | # Target field Et 190 | YY = peppers*np.power(np.e,1j*baboon) 191 | 192 | A_t[des_y:has_y,des_x:has_x] = np.abs(YY) 193 | Phi_t[des_y:has_y,des_x:has_x] = np.arctan2(np.imag(YY),np.real(YY)) 194 | 195 | Et = A_t*np.power(np.e,1j*Phi_t) # Target beam embedded in Ny by Nx pixels 196 | 197 | return(Ei,Et,t,b,thresh,Nx,Ny,NLx,NLy,OffsetX,OffsetY,steps) 198 | 199 | -------------------------------------------------------------------------------- /BeamForming_PACK_python/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | 3 | Phase-only mask computation using a phase retrieval algorithm, Version 1.0 Copyright(c) 2019 M. Yommi, A. Bianchetti*, P. Etchepareborda*, and A. Federico 4 | 5 | All Rights Reserved. 6 | 7 | The authors are with Instituto Nacional de Tecnología Industrial, and CONICET(*). 8 | 9 | --- 10 | ### You are free to 11 | Share — copy and redistribute the material in any medium or format 12 | Adapt — remix, transform, and build upon the material 13 | for any purpose, even commercially. 14 | This license is acceptable for Free Cultural Works. 15 | 16 | The licensor cannot revoke these freedoms as long as you follow the license terms. 17 | 18 | ### Under the following terms 19 | * Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 20 | 21 | * ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. 22 | 23 | * No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 24 | 25 | ### Notices 26 | 27 | You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation. 28 | No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. 29 | --- 30 | 31 | This is an implementation of the phase retrieval algorithm for calculating the 32 | phase-only mask in beam shaping problems. Please refer 33 | to the following paper: 34 | 35 | M. Yommi, A. Bianchetti, P. Etchepareborda, and A. Federico, "Determining high-accuracy random phase-only masks for complex local modulation of light fields," 2019. 36 | 37 | Kindly report any suggestions or corrections to grupolatof@gmail.com 38 | 39 | -------------------------------------------------------------------------------- /BeamForming_PACK_python/PKG-INFO: -------------------------------------------------------------------------------- 1 | Metadata-Version: 1.0 2 | Name: BeamShapingPyProject 3 | Version: 0.0.1 4 | Summary: Beam Shaping Algorithm using phase-only random masks 5 | Home-page: https: 6 | Author: A. Federico 7 | Author-email: federico@inti.gov.ar 8 | 9 | -------------------------------------------------------------------------------- /BeamForming_PACK_python/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Beam shaping using random phase-only mask for Python. 3 | 4 | The replication of these presented results also were carried out by the open source scripts in MATLAB code, available in 5 | https://github.com/grupolatof/phase-retrieval-algorithm. [offered July 2022] 6 | 7 | 8 | * **Authors**: [M. Yommi](https://github.com/maxiyommi), [A. Bianchetti](https://github.com/abianchetti), [P. Etchepareborda](https://github.com/PablitoE) and [A. Federico](https://github.com/alefederico). 9 | * **Email**: federico@inti.gov.ar 10 | * **Homepage**: http://www.inti.gov.ar 11 | 12 | See licensing terms for details. 13 | 14 | ## Contents of the BeamFormingPyProject package 15 | | Script | Description | 16 | |---|---| 17 | | [main](/source/main.py) | Main script. | 18 | | [aux_tools](/source/aux_tools.py) | auxiliar tools script with the functions: | 19 | | [define_T] | Initial conditions settings. | 20 | | [FFT2] | Fast Fourier Transform balanced. | 21 | | [iFFT2] | Inverse Fast Fourier Transform balanced. | 22 | | [PR] | Phase retrieval algorithm. | 23 | | [speckle_gen] | Speckle field generator. | 24 | | [mat2level] | Converts the matrix I to the intensity array F with values in the range [0,1]. | 25 | | [Ei_amplitude.csv] | Intensity Data of the Input field | 26 | | [Ei_phase.csv] | Phase Data of the Input field | 27 | | [phi_mask.csv] | Calculated random phase-only mask | 28 | | [baboon.tif] | Phase field. Target | 29 | | [peppers.tif] | Amplitude field. Target| 30 | 31 | 32 | For a detailed description of arguments and outputs consult the docstring in the files. 33 | 34 | If you have suggestions, bugs or feature requests or want to contribute code, please email us. 35 | 36 | ## Disclaimer 37 | All functions in this toolbox were implemented with care and tested on the examples presented in *Determining high-accuracy random phase-only masks for local complex modulation of light fields.* were possible. 38 | Nevertheless, they may contain errors or bugs, which may affect the outcome of your analysis. 39 | We do not take responsibility for any harm coming from using this toolbox, neither if it is caused by errors in the software nor if it is caused by its improper application. Please email us any bugs you find. 40 | 41 | > Distributed under Open Source Script. 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /BeamForming_PACK_python/setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | with open("README.md", "r") as fh: 4 | long_description = fh.read() 5 | 6 | setuptools.setup( 7 | name="BeamFormingPyProject", 8 | version="0.0.1", 9 | author="M Yommi", 10 | author_email="myommi@inti.gob.ar", 11 | description="Beam forming algorithm using phase-only random masks", 12 | long_description="Here is presented an iterative algorithm that locally resolves the beam shaping problem through determining high-accuracy random phase-only masks. The algorithm is based on the discrimination of the target field spatial frequencies and a relation between the intensities of the incident and target fields, which is determined from a simple physical model.", 13 | url="https://www.researchgate.net/publication/337211653_Determining_high-accuracy_random_phase-only_masks_for_complex_local_modulation_of_arbitrary_light_fields", 14 | packages=['BeamFormingPyProject'], 15 | python_requires='>=3.8', 16 | ) 17 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | Phase-only mask computation using a phase retrieval algorithm, Version 1.0 Copyright(c) 2019 M. Yommi, A. Bianchetti*, P. Etchepareborda*, and A. Federico 4 | 5 | All Rights Reserved. 6 | 7 | The authors are with Instituto Nacional de Tecnología Industrial, and CONICET(*). 8 | 9 | --- 10 | ### You are free to 11 | Share — copy and redistribute the material in any medium or format 12 | Adapt — remix, transform, and build upon the material 13 | for any purpose, even commercially. 14 | This license is acceptable for Free Cultural Works. 15 | 16 | The licensor cannot revoke these freedoms as long as you follow the license terms. 17 | 18 | ### Under the following terms 19 | * Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 20 | 21 | * ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. 22 | 23 | * No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 24 | 25 | ### Notices 26 | 27 | You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation. 28 | No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. 29 | --- 30 | 31 | This is an implementation of the phase retrieval algorithm for calculating the 32 | phase-only mask in beam shaping problems. Please refer 33 | to the following paper: 34 | 35 | M. Yommi, A. Bianchetti, P. Etchepareborda, and A. Federico, "Determining high-accuracy random phase-only masks for complex local modulation of light fields," 2019. 36 | 37 | Kindly report any suggestions or corrections to grupolatof@gmail.com 38 | 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Beam shaping using random phase-only mask for MATLAB® 3 | 4 | * **Authors**: [M. Yommi](https://github.com/maxiyommi), [A. Bianchetti](https://github.com/abianchetti), [P. Etchepareborda](https://github.com/PablitoE) and [A. Federico](https://github.com/alefederico). 5 | * **Email**: federico@inti.gov.ar 6 | * **Homepage**: http://www.inti.gov.ar 7 | 8 | * **Manuscript**: http://dx.doi.org/10.7149/OPA.56.2.51117 9 | 10 | See licensing terms for details. 11 | 12 | ## Contents 13 | | Script | Description | 14 | |---|---| 15 | | [main.m](/source/main.m) | Main script. | 16 | | [define_T.m](/source/define_T.m) | Initial conditions settings. | 17 | | [FFT2.m](/source/FFT.m) | Fast Fourier Transform balanced. | 18 | | [iFFT2](/source/iFFT2.m) | Inverse Fast Fourier Transform balanced. | 19 | | [PR.m](/source/PR.m) | Phase retrieval algorithm. | 20 | | [speckle_gen.m](/source/speckle_gen.m) | Speckle field generator. | 21 | | [ssim_index.m](/source/ssim_index.m) | Structural SIMilarity (SSIM) index. | 22 | | [format_subplot.m](/source/format_subplot.m) | Subplot function. | 23 | 24 | 25 | 26 | For a detailed description of arguments and outputs consult the docstring in the files. 27 | 28 | If you have suggestions, bugs or feature requests or want to contribute code, please email us. 29 | 30 | ## Disclaimer 31 | All functions in this toolbox were implemented with care and tested. Nevertheless, they may contain errors or bugs, which may affect the outcome of your analysis. 32 | We do not take responsibility for any harm coming from using this toolbox, neither if it is caused by errors in the software nor if it is caused by its improper application. Please email us any bugs you find. 33 | 34 | > Distributed under Open Source Script. 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /env/B.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grupolatof/phase-retrieval-algorithm/8fc8bd2331238340a0aa1e5b957cf86f6128a32f/env/B.mat -------------------------------------------------------------------------------- /env/tau.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grupolatof/phase-retrieval-algorithm/8fc8bd2331238340a0aa1e5b957cf86f6128a32f/env/tau.mat -------------------------------------------------------------------------------- /img/amplitude_Et.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grupolatof/phase-retrieval-algorithm/8fc8bd2331238340a0aa1e5b957cf86f6128a32f/img/amplitude_Et.tif -------------------------------------------------------------------------------- /img/amplitude_T.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grupolatof/phase-retrieval-algorithm/8fc8bd2331238340a0aa1e5b957cf86f6128a32f/img/amplitude_T.tif -------------------------------------------------------------------------------- /img/baboon.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grupolatof/phase-retrieval-algorithm/8fc8bd2331238340a0aa1e5b957cf86f6128a32f/img/baboon.tif -------------------------------------------------------------------------------- /img/peppers.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grupolatof/phase-retrieval-algorithm/8fc8bd2331238340a0aa1e5b957cf86f6128a32f/img/peppers.tif -------------------------------------------------------------------------------- /img/phase_Et.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grupolatof/phase-retrieval-algorithm/8fc8bd2331238340a0aa1e5b957cf86f6128a32f/img/phase_Et.tif -------------------------------------------------------------------------------- /img/phase_T.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grupolatof/phase-retrieval-algorithm/8fc8bd2331238340a0aa1e5b957cf86f6128a32f/img/phase_T.tif -------------------------------------------------------------------------------- /source/FFT2.m: -------------------------------------------------------------------------------- 1 | function E = FFT2(E0) 2 | % E = iFFT2(E0) 3 | % Calculate the Fast Fourier Transform balanced 4 | % 5 | % input = E0 6 | % 7 | % output = E 8 | % 9 | % Date: 05/30/2019 10 | % Authors: A. Federico - M. Yommi 11 | 12 | 13 | [Ny,Nx] = size(E0); 14 | E = fftshift(fft2(ifftshift(E0)))/sqrt(Ny)/sqrt(Nx); 15 | end 16 | -------------------------------------------------------------------------------- /source/PR.m: -------------------------------------------------------------------------------- 1 | function [tau,rms_angle,rms_fourier] = PR(Ei,Et,thresh,b,t,NLx,NLy,steps) 2 | % 3 | % Find tau for input arguments: Ei,Et,thresh,gamma,t,NLx,NLy 4 | % 5 | % input = Ei,Et,thresh,gamma,t,NLx,NLy 6 | % 7 | % outputs = tau (phase mask), RMS values: rms_angle (phase),rms_fourier(intensity) 8 | % 9 | % 10 | % Date: 10/30/2019 11 | % Authors: A. Federico - M. Yommi 12 | 13 | T = iFFT2(Et); 14 | rng(22); phi = rand(size(T))*2*pi-pi; 15 | rms_angle(1) = 1; 16 | k = 0; 17 | Ai = abs(Ei); 18 | 19 | h = waitbar(0,'Please wait...'); 20 | while rms_angle > thresh 21 | k=k+1; % number of iterations 22 | if k == steps 23 | break 24 | end 25 | 26 | waitbar(k / steps); 27 | 28 | c = T.*exp(-1i*phi)+conj(T).*exp(1i*phi); 29 | B0 = (-c+sqrt(c.^2-4*(abs(T).^2-Ai.^2)))/2; % positive solution 30 | 31 | B = iFFT2(FFT2(T+B0.*exp(1i*phi)).*b); 32 | phi = angle(B); 33 | tau = (T+B0.*exp(1i*phi))./Ei; 34 | 35 | FTt = FFT2(tau.*Ei); 36 | S = FTt.*t; 37 | rms_fourier(k) = sum((abs(Et(:))-abs(S(:))).^2)/NLy/NLx; 38 | rms_angle(k) = sum((angle(S(:))-angle(Et(:))).^2)/NLy/NLx; 39 | end 40 | 41 | close(h) 42 | 43 | save('../env/B.mat', 'B'); 44 | save('../env/tau.mat', 'tau'); 45 | end 46 | -------------------------------------------------------------------------------- /source/define_T.m: -------------------------------------------------------------------------------- 1 | function [Ei,Et,t,b,thresh,Nx,Ny,NLx,NLy,OffsetX,OffsetY,steps] = define_T() 2 | % [T,Et,circ_in,circ_outside,domain] = define_T() 3 | % Function to define T = IFFT[Et*t] 4 | % 5 | % input = none 6 | % 7 | % Outputs: 8 | % Ei, incidente complex input field 9 | % Et, target field 10 | % t, target domain where Et is active 11 | % b, exterior set of t 12 | % thresh, value to stop the phase retrieval process 13 | % Nx,Ny, dimension of the calculated mask 14 | % NLx,NLy, dimension of the target field 15 | % OffsetX,OffsetY, displacement of the origin for order zero problem 16 | % steps, maximum number of iteration 17 | % 18 | % Date: 05/30/2019 19 | % Authors: A. Federico - M. Yommi 20 | 21 | 22 | %% Input conditions 23 | % Maximum mplitude of the Incident field 24 | Amp_Ei = 13; % alpha value relationship 25 | 26 | % Size of the target field Er 27 | NLy = 128; 28 | NLx = NLy; 29 | 30 | % Size of the phase-only mask tau 31 | Nx = 270; 32 | Ny = 320; 33 | 34 | % Target field 35 | OffsetX = 0; % 72; % zero order compensation 36 | OffsetY = 0; % 97; 37 | 38 | % Incident random field generation (speckle field) 39 | rng(33); % set seed 40 | phi_u=rand(Ny,Nx)*2*pi-pi; 41 | U = speckle_gen(135,Ny,Nx); 42 | as = max(abs(U(:))); 43 | U = abs(U)/as; 44 | Ei = Amp_Ei.*U.*exp(1i*phi_u); 45 | 46 | % Domains and field target definitions 47 | uno = ones(Ny,Nx); 48 | t=zeros(Ny,Nx); 49 | t(Ny/2-NLy/2+OffsetY:Ny/2+NLy/2-1+OffsetY,Nx/2-NLx/2+OffsetX:Nx/2+NLx/2-1+OffsetX) = 1; 50 | b = uno-t; 51 | 52 | A_t = zeros(Ny,Nx); 53 | L = imread('../img/peppers.tif','tif'); 54 | L = imresize(L,[NLy NLx]); % [numrows numcols] 55 | peppers = mat2gray(double(L)); 56 | 57 | Phi_t = zeros(Ny,Nx); 58 | L = imread('../img/baboon.tif','tif'); 59 | L = imresize(L,[NLy NLx]); % [numrows numcols]) 60 | baboon = mat2gray(double(L))*2*pi-pi; 61 | 62 | % Target field 63 | YY = peppers.*exp(1i*baboon); 64 | 65 | A_t(Ny/2-NLy/2+OffsetY:Ny/2+NLy/2-1+OffsetY,Nx/2-NLx/2+OffsetX:Nx/2+NLx/2-1+OffsetX) = abs(YY); 66 | Phi_t(Ny/2-NLy/2+OffsetY:Ny/2+NLy/2-1+OffsetY,Nx/2-NLx/2+OffsetX:Nx/2+NLx/2-1+OffsetX) = angle(YY); 67 | 68 | Et = A_t.*exp(1i*Phi_t); % Target beam embedded in Ny by Nx pixels 69 | 70 | % Threshold settings 71 | thresh = 1e-20; % phase retrieval comparison 72 | 73 | % Maximum iteration number 74 | steps=1000; 75 | 76 | return 77 | -------------------------------------------------------------------------------- /source/format_subplot.m: -------------------------------------------------------------------------------- 1 | function format_subplot(s) 2 | set(s,'FontName','Times','FontSize',12,'Layer','top',... 3 | 'TickLabelInterpreter','latex','TitleFontWeight','normal'); 4 | end -------------------------------------------------------------------------------- /source/iFFT2.m: -------------------------------------------------------------------------------- 1 | function E = iFFT2(E0) 2 | % E = iFFT2(E0) 3 | % Calculate the inverse Fast Fourier Transform balanced 4 | % 5 | % input = E0 6 | % 7 | % output = E 8 | % 9 | % Date: 05/30/2019 10 | % Authors: A. Federico - M. Yommi 11 | 12 | 13 | [Ny,Nx] = size(E0); 14 | E = fftshift(ifft2(ifftshift(E0)))*sqrt(Ny)*sqrt(Nx); 15 | end 16 | -------------------------------------------------------------------------------- /source/main.m: -------------------------------------------------------------------------------- 1 | function main () 2 | %% Initialization 3 | 4 | close all 5 | 6 | [Ei,Et,t,b,thresh,Nx,Ny,NLx,NLy,OffsetX,OffsetY,steps] = define_T(); 7 | 8 | %% Iterative algorithm for phase retrieval PR 9 | [tau,rms_angle,rms_fourier] = PR(Ei,Et,thresh,b,t,NLx,NLy,steps); 10 | 11 | %% Figures of the incidente field 12 | figure('Color',[1 1 1],'units','normalized','outerposition',[0 0 1 1]) 13 | s1 = subplot(1,2,1); 14 | imagesc(abs(Ei)) 15 | axis square 16 | colorbar() 17 | format_subplot(s1) 18 | title('Amplitude of the incident light field Ei') 19 | s2 = subplot(1,2,2); 20 | imagesc(angle(Ei)); 21 | title('Phase of the incident light field Ei') 22 | axis square 23 | colorbar() 24 | format_subplot(s2) 25 | 26 | %% Results 8 bits discretization and comparison 27 | % Discretization of the mask T 28 | alfa = 8; % Bits resolution of the computed mask 29 | fase_T_dis = double(uint8((2^alfa-1)/2/pi*angle(tau)+(2^alfa-1)/2))/(2^alfa-1); 30 | Er_d = FFT2(Ei.*exp(1i*(fase_T_dis*2*pi-pi))); % field for the discretized mask 31 | Er = FFT2(Ei.*tau); % recovered field 32 | 33 | figure('Color',[1 1 1],'units','normalized','outerposition',[0 0 1 1]) 34 | s3 = subplot(1,2,1); 35 | imagesc(abs(Er),[0 1]); 36 | title('Amplitude of the recovered field Er') 37 | axis square 38 | colorbar() 39 | format_subplot(s3) 40 | s4 = subplot(1,2,2); 41 | imagesc(abs(Et)); 42 | title('Amplitude of the target beam Et') 43 | axis square 44 | colorbar() 45 | format_subplot(s4) 46 | 47 | figure('Color',[1 1 1],'units','normalized','outerposition',[0 0 1 1]) 48 | s5 = subplot(1,2,1); 49 | imagesc(angle(Er)); 50 | title('Phase of the recovered field Er') 51 | axis square 52 | colorbar() 53 | format_subplot(s5) 54 | s6 = subplot(1,2,2); 55 | imagesc(angle(Et)); 56 | title('Phase of the target beam Et') 57 | axis square 58 | colorbar() 59 | format_subplot(s6) 60 | 61 | %% Figures of the determinated mask 62 | figure('Color',[1 1 1],'units','normalized','outerposition',[0 0 1 1]) 63 | s7 = subplot(1,2,1); 64 | imagesc(angle(tau)); 65 | title('Phase of the phase mask Tau') 66 | axis square 67 | colorbar() 68 | format_subplot(s7) 69 | s8 = subplot(1,2,2); 70 | imagesc(abs(tau)); 71 | title('Amplitude of the phase mask Tau') 72 | axis square 73 | colorbar() 74 | format_subplot(s8) 75 | 76 | %% Convergence analysis 77 | figure('Color',[1 1 1],'units','normalized','outerposition',[0 0 1 1]) 78 | s9 = subplot(1,2,1); 79 | plot(log10(rms_fourier)) 80 | title('Evolution of the RMS values for the recovered amplitude') 81 | ylabel('rms_a') 82 | xlabel('Iteration number') 83 | format_subplot(s9) 84 | s10 = subplot(1,2,2); 85 | plot(log10(rms_angle)) 86 | title('Evolution of the RMS values for the recovered phase') 87 | ylabel('rms_p') 88 | xlabel('Iteration number') 89 | format_subplot(s10) 90 | 91 | %% Quality index determination 92 | 93 | alfa = 12; % CCD 12 bits discretization 94 | Intensity = round(mat2gray(abs(Et(Ny/2-NLy/2+OffsetY:Ny/2+NLy/2-1+OffsetY,Nx/2-NLx/2+OffsetX:Nx/2+NLx/2-1+OffsetX)))*(2^alfa-1)); 95 | Phase = round(mat2gray(angle(Et(Ny/2-NLy/2+OffsetY:Ny/2+NLy/2-1+OffsetY,Nx/2-NLx/2+OffsetX:Nx/2+NLx/2-1+OffsetX)))*(2^alfa-1)); 96 | Intensity_recovered = round(mat2gray(abs(Er(Ny/2-NLy/2+OffsetY:Ny/2+NLy/2-1+OffsetY,Nx/2-NLx/2+OffsetX:Nx/2+NLx/2-1+OffsetX)))*(2^alfa-1)); 97 | Phase_recovered = round(mat2gray(angle(Er(Ny/2-NLy/2+OffsetY:Ny/2+NLy/2-1+OffsetY,Nx/2-NLx/2+OffsetX:Nx/2+NLx/2-1+OffsetX)))*(2^alfa-1)); 98 | 99 | fprintf('Discretization in CCD\n') 100 | 101 | [mssim,~] = ssim_index(Intensity , Intensity_recovered,[0.05 0.05],ones(5),2^alfa-1); 102 | fprintf('Quality_Intensity=%f8\n',mssim) 103 | [mssim,~] = ssim_index(Phase , Phase_recovered,[0.05 0.05],ones(5),2^alfa-1); 104 | fprintf('Quality_Phase=%f8\n',mssim) 105 | 106 | Intensity_recovered = round(mat2gray(abs(Er_d(Ny/2-NLy/2+OffsetY:Ny/2+NLy/2-1+OffsetY,Nx/2-NLx/2+OffsetX:Nx/2+NLx/2-1+OffsetX)))*(2^alfa-1)); 107 | Phase_recovered = round(mat2gray(angle(Er_d(Ny/2-NLy/2+OffsetY:Ny/2+NLy/2-1+OffsetY,Nx/2-NLx/2+OffsetX:Nx/2+NLx/2-1+OffsetX)))*(2^alfa-1)); 108 | 109 | fprintf('\n') 110 | fprintf('Discretization in the phase mask and CCD \n') 111 | 112 | [mssim,~] = ssim_index(Intensity , Intensity_recovered,[0.05 0.05],ones(5),2^alfa-1); 113 | fprintf('Quality_Intensity_for_phase_mask_8bits=%f8\n',mssim) 114 | [mssim,~] = ssim_index(Phase , Phase_recovered,[0.05 0.05],ones(5),2^alfa-1); 115 | fprintf('Quality_Phase_for_phase_mask_8bits=%f8\n',mssim) 116 | end 117 | 118 | -------------------------------------------------------------------------------- /source/speckle_gen.m: -------------------------------------------------------------------------------- 1 | function U = speckle_gen(fsp,Ny,Nx) 2 | % 3 | % Function to generate an speckle field 4 | % 5 | % input = fsp, Ny, Nx. fsp is the radius of the frequency filter. 6 | % 7 | % output = random field U 8 | % 9 | % Date: 06/10/2019 10 | % Authors: A. Federico - M. Yommi 11 | 12 | 13 | fi = rand(Ny,Nx)*2*pi-pi; 14 | U = exp(1i*fi); 15 | IF = fftshift(fft2(U)); 16 | [FU,FV] = freqspace(size(IF),'meshgrid'); 17 | FU = FU*Nx/2; 18 | FV = FV*Ny/2; 19 | IF(sqrt(FU.^2+FV.^2)>fsp) = 0; % lowpass 20 | U = ifft2(ifftshift(IF)); % speckle field 21 | end 22 | -------------------------------------------------------------------------------- /source/ssim_index.m: -------------------------------------------------------------------------------- 1 | function [mssim, ssim_map] = ssim_index(img1, img2, K, window, L) 2 | %======================================================================== 3 | %SSIM Index, Version 1.0 4 | %Copyright(c) 2003 Zhou Wang 5 | %All Rights Reserved. 6 | % 7 | %The author is with Howard Hughes Medical Institute, and Laboratory 8 | %for Computational Vision at Center for Neural Science and Courant 9 | %Institute of Mathematical Sciences, New York University. 10 | % 11 | %---------------------------------------------------------------------- 12 | %Permission to use, copy, or modify this software and its documentation 13 | %for educational and research purposes only and without fee is hereby 14 | %granted, provided that this copyright notice and the original authors' 15 | %names appear on all copies and supporting documentation. This program 16 | %shall not be used, rewritten, or adapted as the basis of a commercial 17 | %software or hardware product without first obtaining permission of the 18 | %authors. The authors make no representations about the suitability of 19 | %this software for any purpose. It is provided "as is" without express 20 | %or implied warranty. 21 | %---------------------------------------------------------------------- 22 | % 23 | %This is an implementation of the algorithm for calculating the 24 | %Structural SIMilarity (SSIM) index between two images. Please refer 25 | %to the following paper: 26 | % 27 | %Z. Wang, A. C. Bovik, H. R. Sheikh, and E. P. Simoncelli, "Image 28 | %quality assessment: From error measurement to structural similarity" 29 | %IEEE Transactios on Image Processing, vol. 13, no. 1, Jan. 2004. 30 | % 31 | %Kindly report any suggestions or corrections to zhouwang@ieee.org 32 | % 33 | %---------------------------------------------------------------------- 34 | % 35 | %Input : (1) img1: the first image being compared 36 | % (2) img2: the second image being compared 37 | % (3) K: constants in the SSIM index formula (see the above 38 | % reference). defualt value: K = [0.01 0.03] 39 | % (4) window: local window for statistics (see the above 40 | % reference). default widnow is Gaussian given by 41 | % window = fspecial('gaussian', 11, 1.5); 42 | % (5) L: dynamic range of the images. default: L = 255 43 | % 44 | %Output: (1) mssim: the mean SSIM index value between 2 images. 45 | % If one of the images being compared is regarded as 46 | % perfect quality, then mssim can be considered as the 47 | % quality measure of the other image. 48 | % If img1 = img2, then mssim = 1. 49 | % (2) ssim_map: the SSIM index map of the test image. The map 50 | % has a smaller size than the input images. The actual size: 51 | % size(img1) - size(window) + 1. 52 | % 53 | %Default Usage: 54 | % Given 2 test images img1 and img2, whose dynamic range is 0-255 55 | % 56 | % [mssim ssim_map] = ssim_index(img1, img2); 57 | % 58 | %Advanced Usage: 59 | % User defined parameters. For example 60 | % 61 | % K = [0.05 0.05]; 62 | % window = ones(8); 63 | % L = 100; 64 | % [mssim ssim_map] = ssim_index(img1, img2, K, window, L); 65 | % 66 | %See the results: 67 | % 68 | % mssim %Gives the mssim value 69 | % imshow(max(0, ssim_map).^4) %Shows the SSIM index map 70 | % 71 | %======================================================================== 72 | 73 | if (nargin < 2 || nargin > 5) 74 | ssim_index = -Inf; 75 | ssim_map = -Inf; 76 | return; 77 | end 78 | 79 | if (size(img1) ~= size(img2)) 80 | ssim_index = -Inf; 81 | ssim_map = -Inf; 82 | return; 83 | end 84 | 85 | [M N] = size(img1); 86 | 87 | if (nargin == 2) 88 | if ((M < 11) || (N < 11)) 89 | ssim_index = -Inf; 90 | ssim_map = -Inf; 91 | return 92 | end 93 | window = fspecial('gaussian', 11, 1.5); % 94 | K(1) = 0.01; % default settings 95 | K(2) = 0.03; % 96 | L = 255; % 97 | end 98 | 99 | if (nargin == 3) 100 | if ((M < 11) || (N < 11)) 101 | ssim_index = -Inf; 102 | ssim_map = -Inf; 103 | return 104 | end 105 | window = fspecial('gaussian', 11, 1.5); 106 | L = 255; 107 | if (length(K) == 2) 108 | if (K(1) < 0 || K(2) < 0) 109 | ssim_index = -Inf; 110 | ssim_map = -Inf; 111 | return; 112 | end 113 | else 114 | ssim_index = -Inf; 115 | ssim_map = -Inf; 116 | return; 117 | end 118 | end 119 | 120 | if (nargin == 4) 121 | [H W] = size(window); 122 | if ((H*W) < 4 || (H > M) || (W > N)) 123 | ssim_index = -Inf; 124 | ssim_map = -Inf; 125 | return 126 | end 127 | L = 255; 128 | if (length(K) == 2) 129 | if (K(1) < 0 || K(2) < 0) 130 | ssim_index = -Inf; 131 | ssim_map = -Inf; 132 | return; 133 | end 134 | else 135 | ssim_index = -Inf; 136 | ssim_map = -Inf; 137 | return; 138 | end 139 | end 140 | 141 | if (nargin == 5) 142 | [H W] = size(window); 143 | if ((H*W) < 4 || (H > M) || (W > N)) 144 | ssim_index = -Inf; 145 | ssim_map = -Inf; 146 | return 147 | end 148 | if (length(K) == 2) 149 | if (K(1) < 0 || K(2) < 0) 150 | ssim_index = -Inf; 151 | ssim_map = -Inf; 152 | return; 153 | end 154 | else 155 | ssim_index = -Inf; 156 | ssim_map = -Inf; 157 | return; 158 | end 159 | end 160 | 161 | C1 = (K(1)*L)^2; 162 | C2 = (K(2)*L)^2; 163 | window = window/sum(sum(window)); 164 | img1 = double(img1); 165 | img2 = double(img2); 166 | 167 | mu1 = filter2(window, img1, 'valid'); 168 | mu2 = filter2(window, img2, 'valid'); 169 | mu1_sq = mu1.*mu1; 170 | mu2_sq = mu2.*mu2; 171 | mu1_mu2 = mu1.*mu2; 172 | sigma1_sq = filter2(window, img1.*img1, 'valid') - mu1_sq; 173 | sigma2_sq = filter2(window, img2.*img2, 'valid') - mu2_sq; 174 | sigma12 = filter2(window, img1.*img2, 'valid') - mu1_mu2; 175 | 176 | if (C1 > 0 & C2 > 0) 177 | ssim_map = ((2*mu1_mu2 + C1).*(2*sigma12 + C2))./((mu1_sq + mu2_sq + C1).*(sigma1_sq + sigma2_sq + C2)); 178 | else 179 | numerator1 = 2*mu1_mu2 + C1; 180 | numerator2 = 2*sigma12 + C2; 181 | denominator1 = mu1_sq + mu2_sq + C1; 182 | denominator2 = sigma1_sq + sigma2_sq + C2; 183 | ssim_map = ones(size(mu1)); 184 | index = (denominator1.*denominator2 > 0); 185 | ssim_map(index) = (numerator1(index).*numerator2(index))./(denominator1(index).*denominator2(index)); 186 | index = (denominator1 ~= 0) & (denominator2 == 0); 187 | ssim_map(index) = numerator1(index)./denominator1(index); 188 | end 189 | 190 | mssim = mean2(ssim_map); 191 | 192 | return --------------------------------------------------------------------------------