<p dir="auto">Hello,</p>
<p dir="auto">The example in the tutorial use radius = 53 and SNR = 5200.  I downloaded<br>
the code and used the sample image as in the tutorial. However results are<br>
way off .Did anyone try the example? Has something changed?</p>
<p dir="auto">Thanks</p>
<h5 dir="auto">System information (version)</h5>
<ul dir="auto">
<li>OpenCV =&gt; 4.3</li>
<li>Operating System / Platform =&gt; MacOS (10.14 Mojave)</li>
<li>Compiler =&gt; Xcode (Clang/LLVM?)</li>
</ul>
<h5 dir="auto">Detailed description</h5>
<p dir="auto">I attempted to translate the C++ program featured in the <a href="https://docs.opencv.org/3.4/de/d3c/tutorial_out_of_focus_deblur_filter.html" rel="nofollow">Out-of-focus Deblur Filter</a> tutorial into Python for adding multi-language coverage. I have included that code below. However, I had trouble recreating the results of the article after translation:</p>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/33104112/82168232-480ee300-988c-11ea-9b3e-9ba26a374eab.jpg"><img src="https://user-images.githubusercontent.com/33104112/82168232-480ee300-988c-11ea-9b3e-9ba26a374eab.jpg" alt="result" style="max-width: 100%;"></a></p>
<p dir="auto">To try to isolate the problem, I compiled and ran the C++ program with the parameters mentioned in the tutorial, but did not receive the "advertised" results:</p>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/33104112/82167574-42180280-988a-11ea-86ca-a4e9828e6c8b.jpg"><img src="https://user-images.githubusercontent.com/33104112/82167574-42180280-988a-11ea-86ca-a4e9828e6c8b.jpg" alt="result" style="max-width: 100%;"></a></p>
<p dir="auto">Any help with debugging both versions would be greatly appreciated, as I would very much like to submit the translation for inclusion.</p>
<p dir="auto">Two notes:</p>
<ol dir="auto">
<li>This script uses NumPy <code class="notranslate">fft.fftshift()</code> instead of the custom fftshift function from the tutorial, but I got the same results with both.</li>
<li>I noticed that adding the cv.DFT_SCALE flag to the <code class="notranslate">cv.dft</code> and <code class="notranslate">cv.idft</code> functions improved the results, and I believed that flag should be included on all, but I have not included it here, in the interest of a direct translation.</li>
</ol>
<details>
<summary> Below is the translated Python script </summary>
<br>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import sys, argparse, copy
import numpy as np
import cv2 as cv

def main():
	# Parse arguments
	text = &quot;Recover an out-of-focus image by Wiener filter.&quot;
	parser = argparse.ArgumentParser(text)
	parser.add_argument(&quot;--image&quot;, type=str, required=True, 
		help=&quot;Specify the input image filename.&quot;)
	parser.add_argument(&quot;--R&quot;, type=int, required=True,
		help=&quot;Specify the point spread circle radius. Demo example: 53&quot;)
	parser.add_argument(&quot;--SNR&quot;, type=float, required=True,
		help=&quot;Specify the signal-to-noise ratio (SNR). Demo example: 5200&quot;)
	args = parser.parse_args()

	help()

	# Read in image and prepare empty output image
	img_in = cv.imread(args.image, cv.IMREAD_GRAYSCALE)
	if img_in is None:
		sys.exit(&quot;ERROR : Image cannot be loaded...!!&quot;)

	## [main]
	# it needs to process even image only
	roi = img_in[0:(img_in.shape[0] &amp; -2), 0:(img_in.shape[1] &amp; -2)]
	## Hw calculation (start)
	h = calcPSF(roi.shape, args.R)
	Hw = calcWnrFilter(h, 1.0 / float(args.SNR))
	## Hw calculation (stop)

	## filtering (start)
	imgOut = filter2DFreq(roi, Hw)
	## filtering (stop)
	## [main] 

	imgOut = imgOut.astype(np.float32)
	imgOut = cv.normalize(imgOut, imgOut, alpha=0, beta=255, 
		norm_type=cv.NORM_MINMAX)
	cv.imwrite(&quot;result.jpg&quot;, imgOut)

## [help]
def help():
	print(&quot;2018-07-12&quot;)
	print(&quot;DeBlur_v8&quot;)
	print(&quot;You will learn how to recover an out-of-focus image by Wiener\
		 filter&quot;)
## [help]

## [calcPSF]
def calcPSF(filterSize, R):
	h = np.zeros(filterSize, dtype=np.float32)
	point = (filterSize[1] // 2, filterSize[0] // 2)
	h = cv.circle(h, point, R, 255, -1, 8)
	summa = np.sum(h)
	return (h / summa) 
## [calcPSF]

## [filter2DFreq]
def filter2DFreq(inputImg, H):
	planes = [inputImg.copy().astype(np.float32), 
		np.zeros(inputImg.shape, dtype=np.float32)]
	complexI = cv.merge(planes)
	complexI = cv.dft(complexI, flags=cv.DFT_SCALE)

	planesH = [H.copy().astype(np.float32), 
		np.zeros(H.shape, dtype=np.float32)]
	complexH = cv.merge(planesH)
	complexIH = cv.mulSpectrums(complexI, complexH, 0)

	complexIH = cv.idft(complexIH)
	planes = cv.split(complexIH)
	return planes[0]
## [filter2DFreq]

## [calcWnrFilter]
def calcWnrFilter(input_h_PSF, nsr):
	h_PSF_shifted = np.fft.fftshift(input_h_PSF)
	planes = [h_PSF_shifted.copy().astype(np.float32), 
		np.zeros(h_PSF_shifted.shape, dtype=np.float32)]
	complexI = cv.merge(planes)
	complexI = cv.dft(complexI)
	planes = cv.split(complexI)
	denom = np.power(np.abs(planes[0]), 2)
	denom += nsr 
	return cv.divide(planes[0], denom) 
## [calcWnrFilter]

if __name__ == &quot;__main__&quot;:
	main()
	cv.destroyAllWindows()
"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">sys</span>, <span class="pl-s1">argparse</span>, <span class="pl-s1">copy</span>
<span class="pl-k">import</span> <span class="pl-s1">numpy</span> <span class="pl-k">as</span> <span class="pl-s1">np</span>
<span class="pl-k">import</span> <span class="pl-s1">cv2</span> <span class="pl-k">as</span> <span class="pl-s1">cv</span>

<span class="pl-k">def</span> <span class="pl-en">main</span>():
	<span class="pl-c"># Parse arguments</span>
	<span class="pl-s1">text</span> <span class="pl-c1">=</span> <span class="pl-s">"Recover an out-of-focus image by Wiener filter."</span>
	<span class="pl-s1">parser</span> <span class="pl-c1">=</span> <span class="pl-s1">argparse</span>.<span class="pl-v">ArgumentParser</span>(<span class="pl-s1">text</span>)
	<span class="pl-s1">parser</span>.<span class="pl-en">add_argument</span>(<span class="pl-s">"--image"</span>, <span class="pl-s1">type</span><span class="pl-c1">=</span><span class="pl-s1">str</span>, <span class="pl-s1">required</span><span class="pl-c1">=</span><span class="pl-c1">True</span>, 
		<span class="pl-s1">help</span><span class="pl-c1">=</span><span class="pl-s">"Specify the input image filename."</span>)
	<span class="pl-s1">parser</span>.<span class="pl-en">add_argument</span>(<span class="pl-s">"--R"</span>, <span class="pl-s1">type</span><span class="pl-c1">=</span><span class="pl-s1">int</span>, <span class="pl-s1">required</span><span class="pl-c1">=</span><span class="pl-c1">True</span>,
		<span class="pl-s1">help</span><span class="pl-c1">=</span><span class="pl-s">"Specify the point spread circle radius. Demo example: 53"</span>)
	<span class="pl-s1">parser</span>.<span class="pl-en">add_argument</span>(<span class="pl-s">"--SNR"</span>, <span class="pl-s1">type</span><span class="pl-c1">=</span><span class="pl-s1">float</span>, <span class="pl-s1">required</span><span class="pl-c1">=</span><span class="pl-c1">True</span>,
		<span class="pl-s1">help</span><span class="pl-c1">=</span><span class="pl-s">"Specify the signal-to-noise ratio (SNR). Demo example: 5200"</span>)
	<span class="pl-s1">args</span> <span class="pl-c1">=</span> <span class="pl-s1">parser</span>.<span class="pl-en">parse_args</span>()

	<span class="pl-en">help</span>()

	<span class="pl-c"># Read in image and prepare empty output image</span>
	<span class="pl-s1">img_in</span> <span class="pl-c1">=</span> <span class="pl-s1">cv</span>.<span class="pl-en">imread</span>(<span class="pl-s1">args</span>.<span class="pl-s1">image</span>, <span class="pl-s1">cv</span>.<span class="pl-v">IMREAD_GRAYSCALE</span>)
	<span class="pl-k">if</span> <span class="pl-s1">img_in</span> <span class="pl-c1">is</span> <span class="pl-c1">None</span>:
		<span class="pl-s1">sys</span>.<span class="pl-en">exit</span>(<span class="pl-s">"ERROR : Image cannot be loaded...!!"</span>)

	<span class="pl-c">## [main]</span>
	<span class="pl-c"># it needs to process even image only</span>
	<span class="pl-s1">roi</span> <span class="pl-c1">=</span> <span class="pl-s1">img_in</span>[<span class="pl-c1">0</span>:(<span class="pl-s1">img_in</span>.<span class="pl-s1">shape</span>[<span class="pl-c1">0</span>] <span class="pl-c1">&amp;</span> <span class="pl-c1">-</span><span class="pl-c1">2</span>), <span class="pl-c1">0</span>:(<span class="pl-s1">img_in</span>.<span class="pl-s1">shape</span>[<span class="pl-c1">1</span>] <span class="pl-c1">&amp;</span> <span class="pl-c1">-</span><span class="pl-c1">2</span>)]
	<span class="pl-c">## Hw calculation (start)</span>
	<span class="pl-s1">h</span> <span class="pl-c1">=</span> <span class="pl-en">calcPSF</span>(<span class="pl-s1">roi</span>.<span class="pl-s1">shape</span>, <span class="pl-s1">args</span>.<span class="pl-v">R</span>)
	<span class="pl-v">Hw</span> <span class="pl-c1">=</span> <span class="pl-en">calcWnrFilter</span>(<span class="pl-s1">h</span>, <span class="pl-c1">1.0</span> <span class="pl-c1">/</span> <span class="pl-en">float</span>(<span class="pl-s1">args</span>.<span class="pl-v">SNR</span>))
	<span class="pl-c">## Hw calculation (stop)</span>

	<span class="pl-c">## filtering (start)</span>
	<span class="pl-s1">imgOut</span> <span class="pl-c1">=</span> <span class="pl-en">filter2DFreq</span>(<span class="pl-s1">roi</span>, <span class="pl-v">Hw</span>)
	<span class="pl-c">## filtering (stop)</span>
	<span class="pl-c">## [main] </span>

	<span class="pl-s1">imgOut</span> <span class="pl-c1">=</span> <span class="pl-s1">imgOut</span>.<span class="pl-en">astype</span>(<span class="pl-s1">np</span>.<span class="pl-s1">float32</span>)
	<span class="pl-s1">imgOut</span> <span class="pl-c1">=</span> <span class="pl-s1">cv</span>.<span class="pl-en">normalize</span>(<span class="pl-s1">imgOut</span>, <span class="pl-s1">imgOut</span>, <span class="pl-s1">alpha</span><span class="pl-c1">=</span><span class="pl-c1">0</span>, <span class="pl-s1">beta</span><span class="pl-c1">=</span><span class="pl-c1">255</span>, 
		<span class="pl-s1">norm_type</span><span class="pl-c1">=</span><span class="pl-s1">cv</span>.<span class="pl-v">NORM_MINMAX</span>)
	<span class="pl-s1">cv</span>.<span class="pl-en">imwrite</span>(<span class="pl-s">"result.jpg"</span>, <span class="pl-s1">imgOut</span>)

<span class="pl-c">## [help]</span>
<span class="pl-k">def</span> <span class="pl-en">help</span>():
	<span class="pl-en">print</span>(<span class="pl-s">"2018-07-12"</span>)
	<span class="pl-en">print</span>(<span class="pl-s">"DeBlur_v8"</span>)
	<span class="pl-en">print</span>(<span class="pl-s">"You will learn how to recover an out-of-focus image by Wiener<span class="pl-cce">\</span></span>
<span class="pl-s"><span class="pl-cce"></span>		 filter"</span>)
<span class="pl-c">## [help]</span>

<span class="pl-c">## [calcPSF]</span>
<span class="pl-k">def</span> <span class="pl-en">calcPSF</span>(<span class="pl-s1">filterSize</span>, <span class="pl-v">R</span>):
	<span class="pl-s1">h</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-en">zeros</span>(<span class="pl-s1">filterSize</span>, <span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">np</span>.<span class="pl-s1">float32</span>)
	<span class="pl-s1">point</span> <span class="pl-c1">=</span> (<span class="pl-s1">filterSize</span>[<span class="pl-c1">1</span>] <span class="pl-c1">//</span> <span class="pl-c1">2</span>, <span class="pl-s1">filterSize</span>[<span class="pl-c1">0</span>] <span class="pl-c1">//</span> <span class="pl-c1">2</span>)
	<span class="pl-s1">h</span> <span class="pl-c1">=</span> <span class="pl-s1">cv</span>.<span class="pl-en">circle</span>(<span class="pl-s1">h</span>, <span class="pl-s1">point</span>, <span class="pl-v">R</span>, <span class="pl-c1">255</span>, <span class="pl-c1">-</span><span class="pl-c1">1</span>, <span class="pl-c1">8</span>)
	<span class="pl-s1">summa</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-en">sum</span>(<span class="pl-s1">h</span>)
	<span class="pl-k">return</span> (<span class="pl-s1">h</span> <span class="pl-c1">/</span> <span class="pl-s1">summa</span>) 
<span class="pl-c">## [calcPSF]</span>

<span class="pl-c">## [filter2DFreq]</span>
<span class="pl-k">def</span> <span class="pl-en">filter2DFreq</span>(<span class="pl-s1">inputImg</span>, <span class="pl-v">H</span>):
	<span class="pl-s1">planes</span> <span class="pl-c1">=</span> [<span class="pl-s1">inputImg</span>.<span class="pl-en">copy</span>().<span class="pl-en">astype</span>(<span class="pl-s1">np</span>.<span class="pl-s1">float32</span>), 
		<span class="pl-s1">np</span>.<span class="pl-en">zeros</span>(<span class="pl-s1">inputImg</span>.<span class="pl-s1">shape</span>, <span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">np</span>.<span class="pl-s1">float32</span>)]
	<span class="pl-s1">complexI</span> <span class="pl-c1">=</span> <span class="pl-s1">cv</span>.<span class="pl-en">merge</span>(<span class="pl-s1">planes</span>)
	<span class="pl-s1">complexI</span> <span class="pl-c1">=</span> <span class="pl-s1">cv</span>.<span class="pl-en">dft</span>(<span class="pl-s1">complexI</span>, <span class="pl-s1">flags</span><span class="pl-c1">=</span><span class="pl-s1">cv</span>.<span class="pl-v">DFT_SCALE</span>)

	<span class="pl-s1">planesH</span> <span class="pl-c1">=</span> [<span class="pl-v">H</span>.<span class="pl-en">copy</span>().<span class="pl-en">astype</span>(<span class="pl-s1">np</span>.<span class="pl-s1">float32</span>), 
		<span class="pl-s1">np</span>.<span class="pl-en">zeros</span>(<span class="pl-v">H</span>.<span class="pl-s1">shape</span>, <span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">np</span>.<span class="pl-s1">float32</span>)]
	<span class="pl-s1">complexH</span> <span class="pl-c1">=</span> <span class="pl-s1">cv</span>.<span class="pl-en">merge</span>(<span class="pl-s1">planesH</span>)
	<span class="pl-s1">complexIH</span> <span class="pl-c1">=</span> <span class="pl-s1">cv</span>.<span class="pl-en">mulSpectrums</span>(<span class="pl-s1">complexI</span>, <span class="pl-s1">complexH</span>, <span class="pl-c1">0</span>)

	<span class="pl-s1">complexIH</span> <span class="pl-c1">=</span> <span class="pl-s1">cv</span>.<span class="pl-en">idft</span>(<span class="pl-s1">complexIH</span>)
	<span class="pl-s1">planes</span> <span class="pl-c1">=</span> <span class="pl-s1">cv</span>.<span class="pl-en">split</span>(<span class="pl-s1">complexIH</span>)
	<span class="pl-k">return</span> <span class="pl-s1">planes</span>[<span class="pl-c1">0</span>]
<span class="pl-c">## [filter2DFreq]</span>

<span class="pl-c">## [calcWnrFilter]</span>
<span class="pl-k">def</span> <span class="pl-en">calcWnrFilter</span>(<span class="pl-s1">input_h_PSF</span>, <span class="pl-s1">nsr</span>):
	<span class="pl-s1">h_PSF_shifted</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-s1">fft</span>.<span class="pl-en">fftshift</span>(<span class="pl-s1">input_h_PSF</span>)
	<span class="pl-s1">planes</span> <span class="pl-c1">=</span> [<span class="pl-s1">h_PSF_shifted</span>.<span class="pl-en">copy</span>().<span class="pl-en">astype</span>(<span class="pl-s1">np</span>.<span class="pl-s1">float32</span>), 
		<span class="pl-s1">np</span>.<span class="pl-en">zeros</span>(<span class="pl-s1">h_PSF_shifted</span>.<span class="pl-s1">shape</span>, <span class="pl-s1">dtype</span><span class="pl-c1">=</span><span class="pl-s1">np</span>.<span class="pl-s1">float32</span>)]
	<span class="pl-s1">complexI</span> <span class="pl-c1">=</span> <span class="pl-s1">cv</span>.<span class="pl-en">merge</span>(<span class="pl-s1">planes</span>)
	<span class="pl-s1">complexI</span> <span class="pl-c1">=</span> <span class="pl-s1">cv</span>.<span class="pl-en">dft</span>(<span class="pl-s1">complexI</span>)
	<span class="pl-s1">planes</span> <span class="pl-c1">=</span> <span class="pl-s1">cv</span>.<span class="pl-en">split</span>(<span class="pl-s1">complexI</span>)
	<span class="pl-s1">denom</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-en">power</span>(<span class="pl-s1">np</span>.<span class="pl-en">abs</span>(<span class="pl-s1">planes</span>[<span class="pl-c1">0</span>]), <span class="pl-c1">2</span>)
	<span class="pl-s1">denom</span> <span class="pl-c1">+=</span> <span class="pl-s1">nsr</span> 
	<span class="pl-k">return</span> <span class="pl-s1">cv</span>.<span class="pl-en">divide</span>(<span class="pl-s1">planes</span>[<span class="pl-c1">0</span>], <span class="pl-s1">denom</span>) 
<span class="pl-c">## [calcWnrFilter]</span>

<span class="pl-k">if</span> <span class="pl-s1">__name__</span> <span class="pl-c1">==</span> <span class="pl-s">"__main__"</span>:
	<span class="pl-en">main</span>()
	<span class="pl-s1">cv</span>.<span class="pl-en">destroyAllWindows</span>()</pre></div>
</details>
<h5 dir="auto">Steps to reproduce</h5>
<p dir="auto">Build OpenCV from source with samples and run the example_tutorial_out_of_focus_deblur_filter executable with the parameters mentioned in the tutorial.</p>