diff --git a/samples/python2/data/licenseplate_motion.jpg b/samples/python2/data/licenseplate_motion.jpg
new file mode 100644
index 0000000000..9723ea148b
Binary files /dev/null and b/samples/python2/data/licenseplate_motion.jpg differ
diff --git a/samples/python2/data/text_defocus.jpg b/samples/python2/data/text_defocus.jpg
new file mode 100644
index 0000000000..42c37e058f
Binary files /dev/null and b/samples/python2/data/text_defocus.jpg differ
diff --git a/samples/python2/data/text_motion.jpg b/samples/python2/data/text_motion.jpg
new file mode 100644
index 0000000000..781f095c2d
Binary files /dev/null and b/samples/python2/data/text_motion.jpg differ
diff --git a/samples/python2/deconvolution.py b/samples/python2/deconvolution.py
new file mode 100644
index 0000000000..cbce8a2c50
--- /dev/null
+++ b/samples/python2/deconvolution.py
@@ -0,0 +1,118 @@
+'''
+Wiener deconvolution.
+
+Sample shows how DFT can be used to perform Weiner deconvolution [1]
+of an image with user-defined point spread function (PSF)
+
+Usage:
+  deconvolution.py  [--circle] 
+      [--angle <degrees>] 
+      [--d <diameter>] 
+      [--snr <signal/noise ratio in db>]
+      [<input image>]
+
+  Use sliders to adjust PSF paramitiers.
+  Keys:
+    SPACE - switch btw linear/cirular PSF
+    ESC   - exit
+
+Examples:
+  deconvolution.py --angle 135 --d 22  data/licenseplate_motion.jpg
+    (image source: http://www.topazlabs.com/infocus/_images/licenseplate_compare.jpg)
+  
+  deconvolution.py --angle 86 --d 31  data/text_motion.jpg
+  deconvolution.py --circle --d 19  data/text_defocus.jpg
+    (image source: compact digital photo camera, no artificial distortion)
+  
+
+[1] http://en.wikipedia.org/wiki/Wiener_deconvolution
+'''
+
+import numpy as np
+import cv2
+from common import nothing
+
+
+def blur_edge(img, d=31):
+    h, w  = img.shape[:2]
+    img_pad = cv2.copyMakeBorder(img, d, d, d, d, cv2.BORDER_WRAP)
+    img_blur = cv2.GaussianBlur(img_pad, (2*d+1, 2*d+1), -1)[d:-d,d:-d]
+    y, x = np.indices((h, w))
+    dist = np.dstack([x, w-x-1, y, h-y-1]).min(-1)
+    w = np.minimum(np.float32(dist)/d, 1.0)
+    return img*w + img_blur*(1-w)
+
+def motion_kernel(angle, d, sz=65):
+    kern = np.ones((1, d), np.float32)
+    c, s = np.cos(angle), np.sin(angle)
+    A = np.float32([[c, -s, 0], [s, c, 0]])
+    sz2 = sz // 2
+    A[:,2] = (sz2, sz2) - np.dot(A[:,:2], ((d-1)*0.5, 0))
+    kern = cv2.warpAffine(kern, A, (sz, sz), flags=cv2.INTER_CUBIC)
+    return kern
+
+def defocus_kernel(d, sz=65):
+    kern = np.zeros((sz, sz), np.uint8)
+    cv2.circle(kern, (sz, sz), d, 255, -1, cv2.CV_AA, shift=1)
+    kern = np.float32(kern) / 255.0
+    return kern
+    
+
+if __name__ == '__main__':
+    print __doc__
+    import sys, getopt
+    opts, args = getopt.getopt(sys.argv[1:], '', ['circle', 'angle=', 'd=', 'snr='])
+    opts = dict(opts)
+    try: fn = args[0]
+    except: fn = 'data/licenseplate_motion.jpg'
+
+    win = 'deconvolution'
+    
+    img = cv2.imread(fn, 0)
+    img = np.float32(img)/255.0
+    cv2.imshow('input', img)
+
+    img = blur_edge(img)
+    IMG = cv2.dft(img, flags=cv2.DFT_COMPLEX_OUTPUT)
+
+    defocus = '--circle' in opts
+
+    def update(_):
+        ang = np.deg2rad( cv2.getTrackbarPos('angle', win) )
+        d = cv2.getTrackbarPos('d', win)
+        noise = 10**(-0.1*cv2.getTrackbarPos('SNR (db)', win))
+
+        if defocus:
+            psf = defocus_kernel(d)
+        else:
+            psf = motion_kernel(ang, d)
+        cv2.imshow('psf', psf)
+
+        psf /= psf.sum()
+        psf_pad = np.zeros_like(img)
+        kh, kw = psf.shape
+        psf_pad[:kh, :kw] = psf
+        PSF = cv2.dft(psf_pad, flags=cv2.DFT_COMPLEX_OUTPUT, nonzeroRows = kh)
+        PSF2 = (PSF**2).sum(-1)
+        iPSF = PSF / (PSF2 + noise)[...,np.newaxis]
+        RES = cv2.mulSpectrums(IMG, iPSF, 0)
+        res = cv2.idft(RES, flags=cv2.DFT_SCALE | cv2.DFT_REAL_OUTPUT )
+        res = np.roll(res, -kh//2, 0)
+        res = np.roll(res, -kw//2, 1)
+        cv2.imshow(win, res)
+
+    cv2.namedWindow(win)
+    cv2.namedWindow('psf', 0)
+    cv2.createTrackbar('angle', win, int(opts.get('--angle', 135)), 180, update)
+    cv2.createTrackbar('d', win, int(opts.get('--d', 22)), 50, update)
+    cv2.createTrackbar('SNR (db)', win, int(opts.get('--snr', 25)), 50, update)
+    update(None)
+
+    while True:
+        ch = cv2.waitKey()
+        if ch == 27:
+            break
+        if ch == ord(' '):
+            defocus = not defocus
+            update(None)
+