Digital blurring is usually Gaussian, or something close. Cameras defocus differently.
Photographic blur comes from two phenomena:
This page is about focus blur.
Light from a point of the object doesn't hit a single point on the sensor. Instead, it is spread across an area. The size of the area depends on how out-of-focus the camare is, and the size of the lens aperture. The shape of the area depends on the shape of the lens aperture.
Here is a photo of a Noct-Nikkor 58mm f/1.2 lens, stopped down to f/2.8 and f/8 and f/1.2. A Nikkor 105mm set to f/2.8 and f/8.
It's irrelevant, but they were photographed with a Nikkor 50/2 on a D800 at f/4, about 1/30s, ISO 200, handheld. The background is a laptop screen.
set CRAD=3 %IMG7%magick ^ -size 100x200 ^ xc:#000 ^ xc:#fff ^ xc:#888 ^ -fill #fff -draw "translate 50,40 circle 0,0 0,%CRAD%" ^ -fill #f00 -draw "translate 50,80 circle 0,0 0,%CRAD%" ^ -fill #0f0 -draw "translate 50,120 circle 0,0 0,%CRAD%" ^ -fill #00f -draw "translate 50,160 circle 0,0 0,%CRAD%" ^ +append +repage ^ +depth ^ cb_samp.png |
Digital blur is commonly Gaussian. This is not how cameras blur images.
set /A RAD=15 set /A DIAM=%RAD%+%RAD%+1 %IMG7%magick ^ xc:White ^ -bordercolor Black -border %RAD% ^ -gaussian-blur 0x5 ^ +depth cb_g1.png |
The script polyPath.bat, given a centre, radius and number of points, builds a path string representing a regular polygon, in the form Mx,y,Lx,y,...Lx,yZ. The result can be used in a "-draw" command to create the polygon.
set /A RAD=15 set /A DIAM=%RAD%+%RAD%+1 call %PICTBAT%polyPath %RAD% %RAD% %RAD% 2 %IMG7%magick ^ -size %DIAM%x%DIAM% xc:#000 -fill #fff -draw "path '%ppPATH%'" ^ +depth cb_poly2.png |
|
call %PICTBAT%polyPath %RAD% %RAD% %RAD% 3 %IMG7%magick ^ -size %DIAM%x%DIAM% xc:#000 -fill #fff -draw "path '%ppPATH%'" ^ +depth cb_poly3.png |
|
call %PICTBAT%polyPath %RAD% %RAD% %RAD% 4 %IMG7%magick ^ -size %DIAM%x%DIAM% xc:#000 -fill #fff -draw "path '%ppPATH%'" ^ +depth cb_poly4.png |
|
call %PICTBAT%polyPath %RAD% %RAD% %RAD% 5 %IMG7%magick ^ -size %DIAM%x%DIAM% xc:#000 -fill #fff -draw "path '%ppPATH%'" ^ +depth cb_poly5.png |
|
call %PICTBAT%polyPath %RAD% %RAD% %RAD% 6 %IMG7%magick ^ -size %DIAM%x%DIAM% xc:#000 -fill #fff -draw "path '%ppPATH%'" ^ +depth cb_poly6.png |
|
call %PICTBAT%polyPath %RAD% %RAD% %RAD% 7 %IMG7%magick ^ -size %DIAM%x%DIAM% xc:#000 -fill #fff -draw "path '%ppPATH%'" ^ +depth cb_poly7.png |
We can convert any of these into a finite Gaussian kernel. First, we make a linear gradient using "-morphology Distance". Then we clut it with the result of a process module (see Process modules: mkgauss), but "-sigmoidal-contrast" would give a close approximation instead.
%IM7DEV%magick ^ cb_poly5.png ^ -morphology Distance "Euclidean:7" ^ -auto-level ^ -write cb_p5d.png ^ -process "mkgauss zeroize cumul norm" ^ -clut ^ cb_p5g.png |
|
%IM7DEV%magick ^ cb_poly5.png ^ -morphology Distance "Euclidean:7" ^ -auto-level ^ -sigmoidal-contrast 7,50%% ^ cb_p5sg.png |
Read into a kernel (see Process modules: img2knl):
for /F "usebackq" %%L in (`%IM7DEV%magick ^ cb_poly5.png -process img2knl NULL:`) do set KNL=%%L
Blur with this kernel:
%IMG7%magick ^ cb_samp.png ^ -define convolve:scale="^!" ^ -morphology convolve %KNL% ^ cb_conv1.png |
|
Blur in linear colorspace: %IM7DEV%magick ^ cb_samp.png ^ -colorspace RGB ^ -define convolve:scale="^!" ^ -morphology convolve %KNL% ^ -colorspace sRGB ^ cb_conv2.png |
|
Blur in sub-linear colorspace: %IM7DEV%magick ^ cb_samp.png ^ -evaluate Pow 5 ^ -define convolve:scale="^!" ^ -morphology convolve %KNL% ^ -evaluate Pow 0.2 ^ cb_conv3.png |
Doughnut kernel, aka bad bokeh (see Wikipedia: Bokeh):
blah: %IMG7%magick ^ cb_poly5.png ^ cb_p5g.png ^ -compose Mathematics -define compose:args=0,-0.5,1,0 -composite ^ cb_k_dn1.png |
Read into a kernel:
for /F "usebackq" %%L in (`%IM7DEV%magick ^ cb_k_dn1.png -process img2knl NULL:`) do set KNLD=%%L echo KNLD=%KNLD%
Blur with this kernel:
%IMG7%magick ^ cb_samp.png ^ -define morphology:showkernel=1 ^ -define convolve:scale="^!" ^ -morphology convolve %KNLD% ^ cb_conv1d.png |
|
Blur in linear colorspace: %IMG7%magick ^ cb_samp.png ^ -colorspace RGB ^ -define convolve:scale="^!" ^ -morphology convolve %KNLD% ^ -colorspace sRGB ^ cb_conv2d.png |
|
Blur in sub-linear colorspace: %IMG7%magick ^ cb_samp.png ^ -evaluate Pow 5 ^ -define convolve:scale="^!" ^ -morphology convolve %KNLD% ^ -evaluate Pow 0.2 ^ cb_conv3d.png |
Each kernel is a point spread function (PSF, see Wikipedia Point spread function). It defines how a point of light is spread. We can demonstrate this by convolving a point source with one of the kernels.
Create a point source: %IMG7%magick ^ xc:White ^ -bordercolor Black ^ -border 30 ^ cb_pnt.png |
|
Convolve the point source: %IMG7%magick ^ cb_pnt.png ^ -define convolve:scale="^!" ^ -morphology convolve %KNLD% ^ -auto-level ^ +depth ^ cb_convpnt1.png |
The result, cropped to the size of the kernel, is (more or less) identical to the kernel.
%IMG7%magick ^ cb_convpnt1.png ^ -gravity Center -crop %DIAM%x%DIAM%+0+0 +repage ^ cb_k_dn1.png ^ -metric RMSE -compare ^ -format %%[distortion] ^ info:
0.00675413
blah
blah
Deblurring a photograph needs two steps:
If the kernel is known, deblurring is a process of deconvolution. When the kernel is not known the process is called "blind deconvolution".
The PSF (kernel) for camera-shake might be approximately constant across the image for rotation of the camera about a horzontal or vertical axis. It will not be constant for out-of-focus areas; these need different sizes of PSFs, and PSF rotation depending on whether the object is in front of or behind the plane of focus.
If the PSF is not correct, the result will suffer from ringing.
A interesting reference for camera-shake is Removing Camera Shake from a Single Photograph, Fergus et al, which chiefly addresses the difficult problem of finding the PSF.
The Fergus paper uses Richarson-Lucy deconvolution, which doesn't seem difficult. See Wikipedia: Richardson-Lucy deconvolution.
For convenience, .bat scripts are also available in a single zip file. See Zipped BAT files.
rem From: rem %1,%2 coords of centre rem %3 radius from centre to each apex rem %4 number of sides rem %5 optional rotation rem returns ppPATH set to M...Z path, no spaces. @if "%4"=="" findstr /B "rem @rem" %~f0 & exit /B 1 @setlocal enabledelayedexpansion @call echoOffSave set sPath=M set /A Nm1=%4-1 echo %Nm1% set ROT=%5 if "%ROT%"=="" set ROT=0 for /L %%i in (0,1,%Nm1%) do ( for /F "usebackq" %%F in (`%IM%identify -ping -precision 15 ^ -format "ANG=%%[fx:(%%i*360/%4+%ROT%)*pi/180]" ^ xc:`) do set %%F echo ANG=!ANG! for /F "usebackq" %%F in (`%IM%identify -ping -precision 15 ^ -format "DX=%%[fx:sin(!ANG!)*%3+%1]\nDY=%%[fx:cos(!ANG!)*%3+%2]" ^ xc:`) do set %%F echo !DX!,!DY! if not %%i==0 set sPath=!sPath!L set sPath=!sPath!!DX!,!DY! ) call echoRestore set sPath=!sPath!Z echo sPath=%sPath% @endlocal & set ppPATH=%sPath%
All images on this page were created by the commands shown, using:
%IMG7%magick -version
Version: ImageMagick 7.1.0-42 Q16-HDRI x64 396d87c:20220709 https://imagemagick.org Copyright: (C) 1999 ImageMagick Studio LLC License: https://imagemagick.org/script/license.php Features: Cipher DPC HDRI OpenCL Delegates (built-in): bzlib cairo freetype gslib heic jng jp2 jpeg jxl lcms lqr lzma openexr pangocairo png ps raqm raw rsvg tiff webp xml zip zlib Compiler: Visual Studio 2022 (193231332)
To improve internet download speeds, some images may have been automatically converted (by ImageMagick, of course) from PNG or TIFF or MIFF to JPG.
Source file for this web page is camblur.h1. To re-create this web page, run "procH1 camblur".
This page, including the images, is my copyright. Anyone is permitted to use or adapt any of the code, scripts or images for any purpose, including commercial use.
Anyone is permitted to re-publish this page, but only for non-commercial use.
Anyone is permitted to link to this page, including for commercial use.
Page version v1.0 9-November-2014.
Page created 22-Aug-2022 20:22:22.
Copyright © 2022 Alan Gibson.