[opencv] 36/98: Backport of new python tests from master branch(PR https://github.com/Itseez/opencv/pull/6025). At the moment tests requre samples/data copied to source location from master branch.

Mattia Rizzolo mattia at debian.org
Tue Oct 4 17:51:22 UTC 2016


This is an automated email from the git hooks/post-receive script.

mattia pushed a commit to annotated tag 2.4.13
in repository opencv.

commit e0f426f78bbf0fd6e161de4a778800b2fb4e7288
Author: Vitaly Tuzov <vitaly.tuzov at itseez.com>
Date:   Wed Feb 24 14:18:51 2016 +0300

    Backport of new python tests from master branch(PR https://github.com/Itseez/opencv/pull/6025).
    At the moment tests requre samples/data copied to source location from master branch.
---
 modules/python/test/test.py                    |  48 +++---
 modules/python/test/test_calibration.py        |  71 +++++++++
 modules/python/test/test_camshift.py           |  92 ++++++++++++
 modules/python/test/test_dft.py                |  46 ++++++
 modules/python/test/test_digits.py             | 197 +++++++++++++++++++++++++
 modules/python/test/test_facedetect.py         |  90 +++++++++++
 modules/python/test/test_feature_homography.py | 160 ++++++++++++++++++++
 modules/python/test/test_fitline.py            |  66 +++++++++
 modules/python/test/test_gaussian_mix.py       |  58 ++++++++
 modules/python/test/test_grabcut.py            |  67 +++++++++
 modules/python/test/test_houghcircles.py       |  81 ++++++++++
 modules/python/test/test_houghlines.py         |  65 ++++++++
 modules/python/test/test_kmeans.py             |  70 +++++++++
 modules/python/test/test_letter_recog.py       | 161 ++++++++++++++++++++
 modules/python/test/test_lk_homography.py      |  96 ++++++++++++
 modules/python/test/test_lk_track.py           | 111 ++++++++++++++
 modules/python/test/test_morphology.py         |  51 +++++++
 modules/python/test/test_mser.py               |  65 ++++++++
 modules/python/test/test_peopledetect.py       |  62 ++++++++
 modules/python/test/test_squares.py            |  96 ++++++++++++
 modules/python/test/test_texture_flow.py       |  51 +++++++
 modules/python/test/test_watershed.py          |  33 +++++
 modules/python/test/tests_common.py            |  79 ++++++++++
 modules/python/test/tst_scene_render.py        | 119 +++++++++++++++
 24 files changed, 2005 insertions(+), 30 deletions(-)

diff --git a/modules/python/test/test.py b/modules/python/test/test.py
index a4a3d75..e9f1a13 100755
--- a/modules/python/test/test.py
+++ b/modules/python/test/test.py
@@ -122,6 +122,15 @@ class OpenCVTests(unittest.TestCase):
         """ Compute a hash for an image, useful for image comparisons """
         return hashlib.md5(im.tostring()).digest()
 
+#import new OpenCV tests(do we really need old ones in this case)
+from tests_common import NewOpenCVTests
+
+basedir = os.path.abspath(os.path.dirname(__file__))
+
+def load_tests(loader, tests, pattern):
+    tests.addTests(loader.discover(basedir, pattern='test_*.py'))
+    return tests
+
 # Tests to run first; check the handful of basic operations that the later tests rely on
 
 class PreliminaryTests(OpenCVTests):
@@ -2239,36 +2248,15 @@ if __name__ == '__main__':
     print "Local repo path:", args.repo
     print "Local data path:", args.data
     OpenCVTests.repoPath = args.repo
-    OpenCVTests.dataPath = args.data
+    NewOpenCVTests.repoPath = args.repo
+    try:
+        OpenCVTests.dataPath = os.environ['OPENCV_TEST_DATA_PATH']
+        NewOpenCVTests.extraTestDataPath = OpenCVTests.dataPath
+    except KeyError:
+        OpenCVTests.dataPath = args.data
+        NewOpenCVTests.extraTestDataPath = args.data
+        if args.data is None:
+            print('Missing opencv extra repository. Some of tests may fail.')
     random.seed(0)
     unit_argv = [sys.argv[0]] + other;
     unittest.main(argv=unit_argv)
-#    optlist, args = getopt.getopt(sys.argv[1:], 'l:rd')
-#    loops = 1
-#    shuffle = 0
-#    doc_frags = False
-#    for o,a in optlist:
-#        if o == '-l':
-#            loops = int(a)
-#        if o == '-r':
-#            shuffle = 1
-#        if o == '-d':
-#            doc_frags = True
-#
-#    cases = [PreliminaryTests, FunctionTests, AreaTests]
-#    if doc_frags:
-#        cases += [DocumentFragmentTests]
-#    everything = [(tc, t) for tc in cases for t in unittest.TestLoader().getTestCaseNames(tc) ]
-#    if len(args) == 0:
-#        # cases = [NewTests]
-#        args = everything
-#    else:
-#        args = [(tc, t) for (tc, t) in everything if t in args]
-#
-#    suite = unittest.TestSuite()
-#    for l in range(loops):
-#        if shuffle:
-#            random.shuffle(args)
-#        for tc,t in args:
-#            suite.addTest(tc(t))
-#	    unittest.TextTestRunner(verbosity=2).run(suite)
diff --git a/modules/python/test/test_calibration.py b/modules/python/test/test_calibration.py
new file mode 100644
index 0000000..6655218
--- /dev/null
+++ b/modules/python/test/test_calibration.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+
+'''
+camera calibration for distorted images with chess board samples
+reads distorted images, calculates the calibration and write undistorted images
+'''
+
+# Python 2/3 compatibility
+from __future__ import print_function
+
+import numpy as np
+import cv2
+
+from tests_common import NewOpenCVTests
+
+class calibration_test(NewOpenCVTests):
+
+    def test_calibration(self):
+
+        from glob import glob
+        img_names = []
+        for i in range(1, 15):
+            if i < 10:
+                img_names.append('samples/data/left0{}.jpg'.format(str(i)))
+            elif i != 10:
+                img_names.append('samples/data/left{}.jpg'.format(str(i)))
+
+        square_size = 1.0
+        pattern_size = (9, 6)
+        pattern_points = np.zeros((np.prod(pattern_size), 3), np.float32)
+        pattern_points[:, :2] = np.indices(pattern_size).T.reshape(-1, 2)
+        pattern_points *= square_size
+
+        obj_points = []
+        img_points = []
+        h, w = 0, 0
+        img_names_undistort = []
+        for fn in img_names:
+            img = self.get_sample(fn, 0)
+            if img is None:
+                continue
+
+            h, w = img.shape[:2]
+            found, corners = cv2.findChessboardCorners(img, pattern_size)
+            if found:
+                term = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_COUNT, 30, 0.1)
+                cv2.cornerSubPix(img, corners, (5, 5), (-1, -1), term)
+
+            if not found:
+                continue
+
+            img_points.append(corners.reshape(-1, 2))
+            obj_points.append(pattern_points)
+
+        # calculate camera distortion
+        rms, camera_matrix, dist_coefs, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, (w, h), None, None, flags = 0)
+
+        eps = 0.01
+        normCamEps = 10.0
+        normDistEps = 0.001
+
+        cameraMatrixTest = [[ 532.80992189,    0.,          342.4952186 ],
+         [   0.,         532.93346422,  233.8879292 ],
+         [   0.,            0.,            1.        ]]
+
+        distCoeffsTest = [ -2.81325576e-01,   2.91130406e-02,
+           1.21234330e-03,  -1.40825372e-04, 1.54865844e-01]
+
+        self.assertLess(abs(rms - 0.196334638034), eps)
+        self.assertLess(cv2.norm(camera_matrix - cameraMatrixTest, cv2.NORM_L1), normCamEps)
+        self.assertLess(cv2.norm(dist_coefs - distCoeffsTest, cv2.NORM_L1), normDistEps)
\ No newline at end of file
diff --git a/modules/python/test/test_camshift.py b/modules/python/test/test_camshift.py
new file mode 100644
index 0000000..a824320
--- /dev/null
+++ b/modules/python/test/test_camshift.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+
+'''
+Camshift tracker
+================
+
+This is a demo that shows mean-shift based tracking
+You select a color objects such as your face and it tracks it.
+This reads from video camera (0 by default, or the camera number the user enters)
+
+http://www.robinhewitt.com/research/track/camshift.html
+
+'''
+
+# Python 2/3 compatibility
+from __future__ import print_function
+import sys
+PY3 = sys.version_info[0] == 3
+
+if PY3:
+    xrange = range
+
+import numpy as np
+import cv2
+from tst_scene_render import TestSceneRender
+
+from tests_common import NewOpenCVTests, intersectionRate
+
+class camshift_test(NewOpenCVTests):
+
+    framesNum = 300
+    frame = None
+    selection = None
+    drag_start = None
+    show_backproj = False
+    track_window = None
+    render = None
+    errors = 0
+
+    def prepareRender(self):
+
+        self.render = TestSceneRender(self.get_sample('samples/data/pca_test1.jpg'), deformation = True)
+
+    def runTracker(self):
+
+        framesCounter = 0
+        self.selection = True
+
+        xmin, ymin, xmax, ymax = self.render.getCurrentRect()
+
+        self.track_window = (xmin, ymin, xmax - xmin, ymax - ymin)
+
+        while True:
+            framesCounter += 1
+            self.frame = self.render.getNextFrame()
+            hsv = cv2.cvtColor(self.frame, cv2.COLOR_BGR2HSV)
+            mask = cv2.inRange(hsv, np.array((0., 60., 32.)), np.array((180., 255., 255.)))
+
+            if self.selection:
+                x0, y0, x1, y1 = self.render.getCurrentRect() + 50
+                x0 -= 100
+                y0 -= 100
+
+                hsv_roi = hsv[y0:y1, x0:x1]
+                mask_roi = mask[y0:y1, x0:x1]
+                hist = cv2.calcHist( [hsv_roi], [0], mask_roi, [16], [0, 180] )
+                cv2.normalize(hist, hist, 0, 255, cv2.NORM_MINMAX)
+                self.hist = hist.reshape(-1)
+                self.selection = False
+
+            if self.track_window and self.track_window[2] > 0 and self.track_window[3] > 0:
+                self.selection = None
+                prob = cv2.calcBackProject([hsv], [0], self.hist, [0, 180], 1)
+                prob &= mask
+                term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 )
+                track_box, self.track_window = cv2.CamShift(prob, self.track_window, term_crit)
+
+            trackingRect = np.array(self.track_window)
+            trackingRect[2] += trackingRect[0]
+            trackingRect[3] += trackingRect[1]
+
+            if intersectionRate(self.render.getCurrentRect(), trackingRect) < 0.4:
+                self.errors += 1
+
+            if framesCounter > self.framesNum:
+                break
+
+        self.assertLess(float(self.errors) / self.framesNum, 0.4)
+
+    def test_camshift(self):
+        self.prepareRender()
+        self.runTracker()
\ No newline at end of file
diff --git a/modules/python/test/test_dft.py b/modules/python/test/test_dft.py
new file mode 100644
index 0000000..f796939
--- /dev/null
+++ b/modules/python/test/test_dft.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+
+'''
+Test for disctrete fourier transform (dft)
+'''
+
+# Python 2/3 compatibility
+from __future__ import print_function
+
+import cv2
+import numpy as np
+import sys
+
+from tests_common import NewOpenCVTests
+
+class dft_test(NewOpenCVTests):
+    def test_dft(self):
+
+        img = self.get_sample('samples/data/rubberwhale1.png', 0)
+        eps = 0.001
+
+        #test direct transform
+        refDft = np.fft.fft2(img)
+        refDftShift = np.fft.fftshift(refDft)
+        refMagnitide = np.log(1.0 + np.abs(refDftShift))
+
+        testDft = cv2.dft(np.float32(img),flags = cv2.DFT_COMPLEX_OUTPUT)
+        testDftShift = np.fft.fftshift(testDft)
+        testMagnitude = np.log(1.0 + cv2.magnitude(testDftShift[:,:,0], testDftShift[:,:,1]))
+
+        refMagnitide = cv2.normalize(refMagnitide, 0.0, 1.0, cv2.NORM_MINMAX)
+        testMagnitude = cv2.normalize(testMagnitude, 0.0, 1.0, cv2.NORM_MINMAX)
+
+        self.assertLess(cv2.norm(refMagnitide - testMagnitude), eps)
+
+        #test inverse transform
+        img_back = np.fft.ifft2(refDft)
+        img_back = np.abs(img_back)
+
+        img_backTest = cv2.idft(testDft)
+        img_backTest = cv2.magnitude(img_backTest[:,:,0], img_backTest[:,:,1])
+
+        img_backTest = cv2.normalize(img_backTest, 0.0, 1.0, cv2.NORM_MINMAX)
+        img_back = cv2.normalize(img_back, 0.0, 1.0, cv2.NORM_MINMAX)
+
+        self.assertLess(cv2.norm(img_back - img_backTest), eps)
\ No newline at end of file
diff --git a/modules/python/test/test_digits.py b/modules/python/test/test_digits.py
new file mode 100644
index 0000000..587c355
--- /dev/null
+++ b/modules/python/test/test_digits.py
@@ -0,0 +1,197 @@
+#!/usr/bin/env python
+
+'''
+SVM and KNearest digit recognition.
+
+Sample loads a dataset of handwritten digits from '../data/digits.png'.
+Then it trains a SVM and KNearest classifiers on it and evaluates
+their accuracy.
+
+Following preprocessing is applied to the dataset:
+ - Moment-based image deskew (see deskew())
+ - Digit images are split into 4 10x10 cells and 16-bin
+   histogram of oriented gradients is computed for each
+   cell
+ - Transform histograms to space with Hellinger metric (see [1] (RootSIFT))
+
+
+[1] R. Arandjelovic, A. Zisserman
+    "Three things everyone should know to improve object retrieval"
+    http://www.robots.ox.ac.uk/~vgg/publications/2012/Arandjelovic12/arandjelovic12.pdf
+
+'''
+
+
+# Python 2/3 compatibility
+from __future__ import print_function
+
+# built-in modules
+from multiprocessing.pool import ThreadPool
+
+import cv2
+
+import numpy as np
+from numpy.linalg import norm
+
+
+SZ = 20 # size of each digit is SZ x SZ
+CLASS_N = 10
+DIGITS_FN = 'samples/data/digits.png'
+
+def split2d(img, cell_size, flatten=True):
+    h, w = img.shape[:2]
+    sx, sy = cell_size
+    cells = [np.hsplit(row, w//sx) for row in np.vsplit(img, h//sy)]
+    cells = np.array(cells)
+    if flatten:
+        cells = cells.reshape(-1, sy, sx)
+    return cells
+
+def deskew(img):
+    m = cv2.moments(img)
+    if abs(m['mu02']) < 1e-2:
+        return img.copy()
+    skew = m['mu11']/m['mu02']
+    M = np.float32([[1, skew, -0.5*SZ*skew], [0, 1, 0]])
+    img = cv2.warpAffine(img, M, (SZ, SZ), flags=cv2.WARP_INVERSE_MAP | cv2.INTER_LINEAR)
+    return img
+
+class StatModel(object):
+    def load(self, fn):
+        self.model.load(fn)  # Known bug: https://github.com/Itseez/opencv/issues/4969
+    def save(self, fn):
+        self.model.save(fn)
+
+class KNearest(StatModel):
+    def __init__(self, k = 3):
+        self.k = k
+        self.model = cv2.KNearest()
+
+    def train(self, samples, responses):
+        self.model.train(samples, responses)
+
+    def predict(self, samples):
+        retval, results, neigh_resp, dists = self.model.find_nearest(samples, self.k)
+        return results.ravel()
+
+class SVM(StatModel):
+    def __init__(self, C = 1, gamma = 0.5):
+        self.params = dict( kernel_type = cv2.SVM_RBF,
+                            svm_type = cv2.SVM_C_SVC,
+                            C = C,
+                            gamma = gamma )
+        self.model = cv2.SVM()
+
+    def train(self, samples, responses):
+        self.model.train(samples, responses, params = self.params)
+
+    def predict(self, samples):
+        return self.model.predict_all(samples).ravel()
+
+
+def evaluate_model(model, digits, samples, labels):
+    resp = model.predict(samples)
+    err = (labels != resp).mean()
+
+    confusion = np.zeros((10, 10), np.int32)
+    for i, j in zip(labels, resp):
+        confusion[int(i), int(j)] += 1
+
+    return err, confusion
+
+def preprocess_simple(digits):
+    return np.float32(digits).reshape(-1, SZ*SZ) / 255.0
+
+def preprocess_hog(digits):
+    samples = []
+    for img in digits:
+        gx = cv2.Sobel(img, cv2.CV_32F, 1, 0)
+        gy = cv2.Sobel(img, cv2.CV_32F, 0, 1)
+        mag, ang = cv2.cartToPolar(gx, gy)
+        bin_n = 16
+        bin = np.int32(bin_n*ang/(2*np.pi))
+        bin_cells = bin[:10,:10], bin[10:,:10], bin[:10,10:], bin[10:,10:]
+        mag_cells = mag[:10,:10], mag[10:,:10], mag[:10,10:], mag[10:,10:]
+        hists = [np.bincount(b.ravel(), m.ravel(), bin_n) for b, m in zip(bin_cells, mag_cells)]
+        hist = np.hstack(hists)
+
+        # transform to Hellinger kernel
+        eps = 1e-7
+        hist /= hist.sum() + eps
+        hist = np.sqrt(hist)
+        hist /= norm(hist) + eps
+
+        samples.append(hist)
+    return np.float32(samples)
+
+from tests_common import NewOpenCVTests
+
+class digits_test(NewOpenCVTests):
+
+    def load_digits(self, fn):
+        digits_img = self.get_sample(fn, 0)
+        digits = split2d(digits_img, (SZ, SZ))
+        labels = np.repeat(np.arange(CLASS_N), len(digits)/CLASS_N)
+        return digits, labels
+
+    def test_digits(self):
+
+        digits, labels = self.load_digits(DIGITS_FN)
+
+        # shuffle digits
+        rand = np.random.RandomState(321)
+        shuffle = rand.permutation(len(digits))
+        digits, labels = digits[shuffle], labels[shuffle]
+
+        digits2 = list(map(deskew, digits))
+        samples = preprocess_hog(digits2)
+
+        train_n = int(0.9*len(samples))
+        digits_train, digits_test = np.split(digits2, [train_n])
+        samples_train, samples_test = np.split(samples, [train_n])
+        labels_train, labels_test = np.split(labels, [train_n])
+        errors = list()
+        confusionMatrixes = list()
+
+        model = KNearest(k=4)
+        model.train(samples_train, labels_train)
+        error, confusion = evaluate_model(model, digits_test, samples_test, labels_test)
+        errors.append(error)
+        confusionMatrixes.append(confusion)
+
+        model = SVM(C=2.67, gamma=5.383)
+        model.train(samples_train, labels_train)
+        error, confusion = evaluate_model(model, digits_test, samples_test, labels_test)
+        errors.append(error)
+        confusionMatrixes.append(confusion)
+
+        eps = 0.001
+        normEps = len(samples_test) * 0.02
+
+        confusionKNN = [[45,  0,  0,  0,  0,  0,  0,  0,  0,  0],
+         [ 0, 57,  0,  0,  0,  0,  0,  0,  0,  0],
+         [ 0,  0, 59,  1,  0,  0,  0,  0,  1,  0],
+         [ 0,  0,  0, 43,  0,  0,  0,  1,  0,  0],
+         [ 0,  0,  0,  0, 38,  0,  2,  0,  0,  0],
+         [ 0,  0,  0,  2,  0, 48,  0,  0,  1,  0],
+         [ 0,  1,  0,  0,  0,  0, 51,  0,  0,  0],
+         [ 0,  0,  1,  0,  0,  0,  0, 54,  0,  0],
+         [ 0,  0,  0,  0,  0,  1,  0,  0, 46,  0],
+         [ 1,  1,  0,  1,  1,  0,  0,  0,  2, 42]]
+
+        confusionSVM = [[45,  0,  0,  0,  0,  0,  0,  0,  0,  0],
+          [ 0, 57,  0,  0,  0,  0,  0,  0,  0,  0],
+          [ 0,  0, 59,  2,  0,  0,  0,  0,  0,  0],
+          [ 0,  0,  0, 43,  0,  0,  0,  1,  0,  0],
+          [ 0,  0,  0,  0, 40,  0,  0,  0,  0,  0],
+          [ 0,  0,  0,  1,  0, 50,  0,  0,  0,  0],
+          [ 0,  0,  0,  0,  1,  0,  51, 0,  0,  0],
+          [ 0,  0,  1,  0,  0,  0,  0,  54, 0,  0],
+          [ 0,  0,  0,  0,  0,  0,  0,  0, 47,  0],
+          [ 0,  1,  0,  1,  0,  0,  0,  0,  1, 45]]
+
+        self.assertLess(cv2.norm(confusionMatrixes[0] - confusionKNN, cv2.NORM_L1), normEps)
+        self.assertLess(cv2.norm(confusionMatrixes[1] - confusionSVM, cv2.NORM_L1), normEps)
+
+        self.assertLess(errors[0] - 0.034, eps)
+        self.assertLess(errors[1] - 0.018, eps)
\ No newline at end of file
diff --git a/modules/python/test/test_facedetect.py b/modules/python/test/test_facedetect.py
new file mode 100644
index 0000000..8d64fde
--- /dev/null
+++ b/modules/python/test/test_facedetect.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+
+'''
+face detection using haar cascades
+'''
+
+# Python 2/3 compatibility
+from __future__ import print_function
+
+import numpy as np
+import cv2
+
+def detect(img, cascade):
+    rects = cascade.detectMultiScale(img, scaleFactor=1.3, minNeighbors=4, minSize=(30, 30),
+                                     flags=cv2.CASCADE_SCALE_IMAGE)
+    if len(rects) == 0:
+        return []
+    rects[:,2:] += rects[:,:2]
+    return rects
+
+from tests_common import NewOpenCVTests, intersectionRate
+
+class facedetect_test(NewOpenCVTests):
+
+    def test_facedetect(self):
+        import sys, getopt
+
+        cascade_fn = self.repoPath + '/data/haarcascades/haarcascade_frontalface_alt.xml'
+        nested_fn  = self.repoPath + '/data/haarcascades/haarcascade_eye.xml'
+
+        cascade = cv2.CascadeClassifier(cascade_fn)
+        nested = cv2.CascadeClassifier(nested_fn)
+
+        samples = ['samples/data/lena.jpg', 'cv/cascadeandhog/images/mona-lisa.png']
+
+        faces = []
+        eyes = []
+
+        testFaces = [
+        #lena
+        [[218, 200, 389, 371],
+        [ 244, 240, 294, 290],
+        [ 309, 246, 352, 289]],
+
+        #lisa
+        [[167, 119, 307, 259],
+        [188, 153, 229, 194],
+        [236, 153, 277, 194]]
+        ]
+
+        for sample in samples:
+
+            img = self.get_sample(  sample)
+            gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
+            gray = cv2.GaussianBlur(gray, (5, 5), 5.1)
+
+            rects = detect(gray, cascade)
+            faces.append(rects)
+
+            if not nested.empty():
+                for x1, y1, x2, y2 in rects:
+                    roi = gray[y1:y2, x1:x2]
+                    subrects = detect(roi.copy(), nested)
+
+                    for rect in subrects:
+                        rect[0] += x1
+                        rect[2] += x1
+                        rect[1] += y1
+                        rect[3] += y1
+
+                    eyes.append(subrects)
+
+        faces_matches = 0
+        eyes_matches = 0
+
+        eps = 0.8
+
+        for i in range(len(faces)):
+            for j in range(len(testFaces)):
+                if intersectionRate(faces[i][0], testFaces[j][0]) > eps:
+                    faces_matches += 1
+                    #check eyes
+                    if len(eyes[i]) == 2:
+                        if intersectionRate(eyes[i][0], testFaces[j][1]) > eps and intersectionRate(eyes[i][1] , testFaces[j][2]) > eps:
+                            eyes_matches += 1
+                        elif intersectionRate(eyes[i][1], testFaces[j][1]) > eps and intersectionRate(eyes[i][0], testFaces[j][2]) > eps:
+                            eyes_matches += 1
+
+        self.assertEqual(faces_matches, 2)
+        self.assertEqual(eyes_matches, 2)
\ No newline at end of file
diff --git a/modules/python/test/test_feature_homography.py b/modules/python/test/test_feature_homography.py
new file mode 100644
index 0000000..280945e
--- /dev/null
+++ b/modules/python/test/test_feature_homography.py
@@ -0,0 +1,160 @@
+#!/usr/bin/env python
+
+'''
+Feature homography
+==================
+
+Example of using features2d framework for interactive video homography matching.
+ORB features and FLANN matcher are used. The actual tracking is implemented by
+PlaneTracker class in plane_tracker.py
+'''
+
+# Python 2/3 compatibility
+from __future__ import print_function
+
+import numpy as np
+import cv2
+import sys
+PY3 = sys.version_info[0] == 3
+
+if PY3:
+    xrange = range
+
+# local modules
+from tst_scene_render import TestSceneRender
+
+def intersectionRate(s1, s2):
+
+    x1, y1, x2, y2 = s1
+    s1 = np.array([[x1, y1], [x2,y1], [x2, y2], [x1, y2]])
+
+    area, intersection = cv2.intersectConvexConvex(s1, np.array(s2))
+    return 2 * area / (cv2.contourArea(s1) + cv2.contourArea(np.array(s2)))
+
+from tests_common import NewOpenCVTests
+
+class feature_homography_test(NewOpenCVTests):
+
+    render = None
+    tracker = None
+    framesCounter = 0
+    frame = None
+
+    def test_feature_homography(self):
+
+        self.render = TestSceneRender(self.get_sample('samples/data/graf1.png'),
+            self.get_sample('samples/data/box.png'), noise = 0.5, speed = 0.5)
+        self.frame = self.render.getNextFrame()
+        self.tracker = PlaneTracker()
+        self.tracker.clear()
+        self.tracker.add_target(self.frame, self.render.getCurrentRect())
+
+        while self.framesCounter < 100:
+            self.framesCounter += 1
+            tracked = self.tracker.track(self.frame)
+            if len(tracked) > 0:
+                tracked = tracked[0]
+                self.assertGreater(intersectionRate(self.render.getCurrentRect(), np.int32(tracked.quad)), 0.6)
+            else:
+                self.assertEqual(0, 1, 'Tracking error')
+            self.frame = self.render.getNextFrame()
+
+
+# built-in modules
+from collections import namedtuple
+
+FLANN_INDEX_KDTREE = 1
+FLANN_INDEX_LSH    = 6
+flann_params= dict(algorithm = FLANN_INDEX_LSH,
+                   table_number = 6, # 12
+                   key_size = 12,     # 20
+                   multi_probe_level = 1) #2
+
+MIN_MATCH_COUNT = 10
+
+'''
+  image     - image to track
+  rect      - tracked rectangle (x1, y1, x2, y2)
+  keypoints - keypoints detected inside rect
+  descrs    - their descriptors
+  data      - some user-provided data
+'''
+PlanarTarget = namedtuple('PlaneTarget', 'image, rect, keypoints, descrs, data')
+
+'''
+  target - reference to PlanarTarget
+  p0     - matched points coords in target image
+  p1     - matched points coords in input frame
+  H      - homography matrix from p0 to p1
+  quad   - target bounary quad in input frame
+'''
+TrackedTarget = namedtuple('TrackedTarget', 'target, p0, p1, H, quad')
+
+class PlaneTracker:
+    def __init__(self):
+        self.detector = cv2.ORB( nfeatures = 1000 )
+        self.matcher = cv2.FlannBasedMatcher(flann_params, {})  # bug : need to pass empty dict (#1329)
+        self.targets = []
+        self.frame_points = []
+
+    def add_target(self, image, rect, data=None):
+        '''Add a new tracking target.'''
+        x0, y0, x1, y1 = rect
+        raw_points, raw_descrs = self.detect_features(image)
+        points, descs = [], []
+        for kp, desc in zip(raw_points, raw_descrs):
+            x, y = kp.pt
+            if x0 <= x <= x1 and y0 <= y <= y1:
+                points.append(kp)
+                descs.append(desc)
+        descs = np.uint8(descs)
+        self.matcher.add([descs])
+        target = PlanarTarget(image = image, rect=rect, keypoints = points, descrs=descs, data=data)
+        self.targets.append(target)
+
+    def clear(self):
+        '''Remove all targets'''
+        self.targets = []
+        self.matcher.clear()
+
+    def track(self, frame):
+        '''Returns a list of detected TrackedTarget objects'''
+        self.frame_points, frame_descrs = self.detect_features(frame)
+        if len(self.frame_points) < MIN_MATCH_COUNT:
+            return []
+        matches = self.matcher.knnMatch(frame_descrs, k = 2)
+        matches = [m[0] for m in matches if len(m) == 2 and m[0].distance < m[1].distance * 0.75]
+        if len(matches) < MIN_MATCH_COUNT:
+            return []
+        matches_by_id = [[] for _ in xrange(len(self.targets))]
+        for m in matches:
+            matches_by_id[m.imgIdx].append(m)
+        tracked = []
+        for imgIdx, matches in enumerate(matches_by_id):
+            if len(matches) < MIN_MATCH_COUNT:
+                continue
+            target = self.targets[imgIdx]
+            p0 = [target.keypoints[m.trainIdx].pt for m in matches]
+            p1 = [self.frame_points[m.queryIdx].pt for m in matches]
+            p0, p1 = np.float32((p0, p1))
+            H, status = cv2.findHomography(p0, p1, cv2.RANSAC, 3.0)
+            status = status.ravel() != 0
+            if status.sum() < MIN_MATCH_COUNT:
+                continue
+            p0, p1 = p0[status], p1[status]
+
+            x0, y0, x1, y1 = target.rect
+            quad = np.float32([[x0, y0], [x1, y0], [x1, y1], [x0, y1]])
+            quad = cv2.perspectiveTransform(quad.reshape(1, -1, 2), H).reshape(-1, 2)
+
+            track = TrackedTarget(target=target, p0=p0, p1=p1, H=H, quad=quad)
+            tracked.append(track)
+        tracked.sort(key = lambda t: len(t.p0), reverse=True)
+        return tracked
+
+    def detect_features(self, frame):
+        '''detect_features(self, frame) -> keypoints, descrs'''
+        keypoints, descrs = self.detector.detectAndCompute(frame, None)
+        if descrs is None:  # detectAndCompute returns descs=None if not keypoints found
+            descrs = []
+        return keypoints, descrs
\ No newline at end of file
diff --git a/modules/python/test/test_fitline.py b/modules/python/test/test_fitline.py
new file mode 100644
index 0000000..05719b7
--- /dev/null
+++ b/modules/python/test/test_fitline.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+
+'''
+Robust line fitting.
+==================
+
+Example of using cv2.fitLine function for fitting line
+to points in presence of outliers.
+
+Switch through different M-estimator functions and see,
+how well the robust functions fit the line even
+in case of ~50% of outliers.
+
+'''
+
+# Python 2/3 compatibility
+from __future__ import print_function
+import sys
+PY3 = sys.version_info[0] == 3
+
+import numpy as np
+import cv2
+
+from tests_common import NewOpenCVTests
+
+w, h = 512, 256
+
+def toint(p):
+    return tuple(map(int, p))
+
+def sample_line(p1, p2, n, noise=0.0):
+    np.random.seed(10)
+    p1 = np.float32(p1)
+    t = np.random.rand(n,1)
+    return p1 + (p2-p1)*t + np.random.normal(size=(n, 2))*noise
+
+dist_func_names = ['CV_DIST_L2', 'CV_DIST_L1', 'CV_DIST_L12', 'CV_DIST_FAIR', 'CV_DIST_WELSCH', 'CV_DIST_HUBER']
+
+class fitline_test(NewOpenCVTests):
+
+    def test_fitline(self):
+
+        noise = 5
+        n = 200
+        r = 5 / 100.0
+        outn = int(n*r)
+
+        p0, p1 = (90, 80), (w-90, h-80)
+        line_points = sample_line(p0, p1, n-outn, noise)
+        outliers = np.random.rand(outn, 2) * (w, h)
+        points = np.vstack([line_points, outliers])
+
+        lines = []
+
+        for name in dist_func_names:
+            func = getattr(cv2.cv, name)
+            vx, vy, cx, cy = cv2.fitLine(np.float32(points), func, 0, 0.01, 0.01)
+            line = [float(vx), float(vy), float(cx), float(cy)]
+            lines.append(line)
+
+        eps = 0.05
+
+        refVec =  (np.float32(p1) - p0) / cv2.norm(np.float32(p1) - p0)
+
+        for i in range(len(lines)):
+            self.assertLessEqual(cv2.norm(refVec - lines[i][0:2], cv2.NORM_L2), eps)
\ No newline at end of file
diff --git a/modules/python/test/test_gaussian_mix.py b/modules/python/test/test_gaussian_mix.py
new file mode 100644
index 0000000..498cf38
--- /dev/null
+++ b/modules/python/test/test_gaussian_mix.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+
+# Python 2/3 compatibility
+from __future__ import print_function
+import sys
+PY3 = sys.version_info[0] == 3
+
+if PY3:
+    xrange = range
+
+import numpy as np
+from numpy import random
+import cv2
+
+def make_gaussians(cluster_n, img_size):
+    points = []
+    ref_distrs = []
+    for i in xrange(cluster_n):
+        mean = (0.1 + 0.8*random.rand(2)) * img_size
+        a = (random.rand(2, 2)-0.5)*img_size*0.1
+        cov = np.dot(a.T, a) + img_size*0.05*np.eye(2)
+        n = 100 + random.randint(900)
+        pts = random.multivariate_normal(mean, cov, n)
+        points.append( pts )
+        ref_distrs.append( (mean, cov) )
+    points = np.float32( np.vstack(points) )
+    return points, ref_distrs
+
+from tests_common import NewOpenCVTests
+
+class gaussian_mix_test(NewOpenCVTests):
+
+    def test_gaussian_mix(self):
+
+        np.random.seed(10)
+        cluster_n = 5
+        img_size = 512
+
+        points, ref_distrs = make_gaussians(cluster_n, img_size)
+
+        em = cv2.EM(cluster_n,cv2.EM_COV_MAT_GENERIC)
+        em.train(points)
+        means = em.getMat("means")
+        covs = em.getMatVector("covs")  # Known bug: https://github.com/Itseez/opencv/pull/4232
+        found_distrs = zip(means, covs)
+
+        matches_count = 0
+
+        meanEps = 0.05
+        covEps = 0.1
+
+        for i in range(cluster_n):
+            for j in range(cluster_n):
+                if (cv2.norm(means[i] - ref_distrs[j][0], cv2.NORM_L2) / cv2.norm(ref_distrs[j][0], cv2.NORM_L2) < meanEps and
+                    cv2.norm(covs[i] - ref_distrs[j][1], cv2.NORM_L2) / cv2.norm(ref_distrs[j][1], cv2.NORM_L2) < covEps):
+                    matches_count += 1
+
+        self.assertEqual(matches_count, cluster_n)
\ No newline at end of file
diff --git a/modules/python/test/test_grabcut.py b/modules/python/test/test_grabcut.py
new file mode 100644
index 0000000..38211f7
--- /dev/null
+++ b/modules/python/test/test_grabcut.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+'''
+===============================================================================
+Interactive Image Segmentation using GrabCut algorithm.
+===============================================================================
+'''
+
+# Python 2/3 compatibility
+from __future__ import print_function
+
+import numpy as np
+import cv2
+import sys
+
+from tests_common import NewOpenCVTests
+
+class grabcut_test(NewOpenCVTests):
+
+    def verify(self, mask, exp):
+
+        maxDiffRatio = 0.02
+        expArea = np.count_nonzero(exp)
+        nonIntersectArea = np.count_nonzero(mask != exp)
+        curRatio = float(nonIntersectArea) / expArea
+        return curRatio < maxDiffRatio
+
+    def scaleMask(self, mask):
+
+        return np.where((mask==cv2.GC_FGD) + (mask==cv2.GC_PR_FGD),255,0).astype('uint8')
+
+    def test_grabcut(self):
+
+        img = self.get_sample('cv/shared/airplane.png')
+        mask_prob = self.get_sample("cv/grabcut/mask_probpy.png", 0)
+        exp_mask1 = self.get_sample("cv/grabcut/exp_mask1py.png", 0)
+        exp_mask2 = self.get_sample("cv/grabcut/exp_mask2py.png", 0)
+
+        if img is None:
+            self.assertTrue(False, 'Missing test data')
+
+        rect = (24, 126, 459, 168)
+        mask = np.zeros(img.shape[:2], dtype = np.uint8)
+        bgdModel = np.zeros((1,65),np.float64)
+        fgdModel = np.zeros((1,65),np.float64)
+        cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 0, cv2.GC_INIT_WITH_RECT)
+        cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 2, cv2.GC_EVAL)
+
+        if mask_prob is None:
+            mask_prob = mask.copy()
+            cv2.imwrite(self.extraTestDataPath + '/cv/grabcut/mask_probpy.png', mask_prob)
+        if exp_mask1 is None:
+            exp_mask1 = self.scaleMask(mask)
+            cv2.imwrite(self.extraTestDataPath + '/cv/grabcut/exp_mask1py.png', exp_mask1)
+
+        self.assertEqual(self.verify(self.scaleMask(mask), exp_mask1), True)
+
+        mask = mask_prob
+        bgdModel = np.zeros((1,65),np.float64)
+        fgdModel = np.zeros((1,65),np.float64)
+        cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 0, cv2.GC_INIT_WITH_MASK)
+        cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 1, cv2.GC_EVAL)
+
+        if exp_mask2 is None:
+            exp_mask2 = self.scaleMask(mask)
+            cv2.imwrite(self.extraTestDataPath + '/cv/grabcut/exp_mask2py.png', exp_mask2)
+
+        self.assertEqual(self.verify(self.scaleMask(mask), exp_mask2), True)
\ No newline at end of file
diff --git a/modules/python/test/test_houghcircles.py b/modules/python/test/test_houghcircles.py
new file mode 100644
index 0000000..6cf7d74
--- /dev/null
+++ b/modules/python/test/test_houghcircles.py
@@ -0,0 +1,81 @@
+#!/usr/bin/python
+
+'''
+This example illustrates how to use cv2.HoughCircles() function.
+'''
+
+# Python 2/3 compatibility
+from __future__ import print_function
+
+import cv2
+import numpy as np
+import sys
+from numpy import pi, sin, cos
+
+from tests_common import NewOpenCVTests
+
+def circleApproximation(circle):
+
+    nPoints = 30
+    phi = 0
+    dPhi = 2*pi / nPoints
+    contour = []
+    for i in range(nPoints):
+        contour.append(([circle[0] + circle[2]*cos(i*dPhi),
+            circle[1] + circle[2]*sin(i*dPhi)]))
+
+    return np.array(contour).astype(int)
+
+def convContoursIntersectiponRate(c1, c2):
+
+    s1 = cv2.contourArea(c1)
+    s2 = cv2.contourArea(c2)
+
+    s, _ = cv2.intersectConvexConvex(c1, c2)
+
+    return 2*s/(s1+s2)
+
+class houghcircles_test(NewOpenCVTests):
+
+    def test_houghcircles(self):
+
+        fn = "samples/data/board.jpg"
+
+        src = self.get_sample(fn, 1)
+        img = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
+        img = cv2.medianBlur(img, 5)
+
+        circles = cv2.HoughCircles(img, cv2.cv.CV_HOUGH_GRADIENT, 1, 10, np.array([]), 100, 30, 1, 30)[0]
+
+        testCircles = [[38, 181, 17.6],
+        [99.7, 166, 13.12],
+        [142.7, 160, 13.52],
+        [223.6, 110, 8.62],
+        [79.1, 206.7, 8.62],
+        [47.5, 351.6, 11.64],
+        [189.5, 354.4, 11.64],
+        [189.8, 298.9, 10.64],
+        [189.5, 252.4, 14.62],
+        [252.5, 393.4, 15.62],
+        [602.9, 467.5, 11.42],
+        [222, 210.4, 9.12],
+        [263.1, 216.7, 9.12],
+        [359.8, 222.6, 9.12],
+        [518.9, 120.9, 9.12],
+        [413.8, 113.4, 9.12],
+        [489, 127.2, 9.12],
+        [448.4, 121.3, 9.12],
+        [384.6, 128.9, 8.62]]
+
+        matches_counter = 0
+
+        for i in range(len(testCircles)):
+            for j in range(len(circles)):
+
+                tstCircle = circleApproximation(testCircles[i])
+                circle = circleApproximation(circles[j])
+                if convContoursIntersectiponRate(tstCircle, circle) > 0.6:
+                    matches_counter += 1
+
+        self.assertGreater(float(matches_counter) / len(testCircles), .5)
+        self.assertLess(float(len(circles) - matches_counter) / len(circles), .75)
\ No newline at end of file
diff --git a/modules/python/test/test_houghlines.py b/modules/python/test/test_houghlines.py
new file mode 100644
index 0000000..081c849
--- /dev/null
+++ b/modules/python/test/test_houghlines.py
@@ -0,0 +1,65 @@
+#!/usr/bin/python
+
+'''
+This example illustrates how to use Hough Transform to find lines
+'''
+
+# Python 2/3 compatibility
+from __future__ import print_function
+
+import cv2
+import numpy as np
+import sys
+import math
+
+from tests_common import NewOpenCVTests
+
+def linesDiff(line1, line2):
+
+    norm1 = cv2.norm(line1 - line2, cv2.NORM_L2)
+    line3 = line1[2:4] + line1[0:2]
+    norm2 = cv2.norm(line3 - line2, cv2.NORM_L2)
+
+    return min(norm1, norm2)
+
+class houghlines_test(NewOpenCVTests):
+
+    def test_houghlines(self):
+
+        fn = "/samples/data/pic1.png"
+
+        src = self.get_sample(fn)
+        dst = cv2.Canny(src, 50, 200)
+
+        lines = cv2.HoughLinesP(dst, 1, math.pi/180.0, 40, np.array([]), 50, 10)[0,:,:]
+
+        eps = 5
+        testLines = [
+            #rect1
+             [ 232,  25, 43, 25],
+             [ 43, 129, 232, 129],
+             [ 43, 129,  43,  25],
+             [232, 129, 232,  25],
+            #rect2
+             [251,  86, 314, 183],
+             [252,  86, 323,  40],
+             [315, 183, 386, 137],
+             [324,  40, 386, 136],
+            #triangle
+             [245, 205, 377, 205],
+             [244, 206, 305, 278],
+             [306, 279, 377, 205],
+            #rect3
+             [153, 177, 196, 177],
+             [153, 277, 153, 179],
+             [153, 277, 196, 277],
+             [196, 177, 196, 277]]
+
+        matches_counter = 0
+
+        for i in range(len(testLines)):
+            for j in range(len(lines)):
+                if linesDiff(testLines[i], lines[j]) < eps:
+                    matches_counter += 1
+
+        self.assertGreater(float(matches_counter) / len(testLines), .7)
\ No newline at end of file
diff --git a/modules/python/test/test_kmeans.py b/modules/python/test/test_kmeans.py
new file mode 100644
index 0000000..8cee11c
--- /dev/null
+++ b/modules/python/test/test_kmeans.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+
+'''
+K-means clusterization test
+'''
+
+# Python 2/3 compatibility
+from __future__ import print_function
+
+import numpy as np
+import cv2
+from numpy import random
+import sys
+PY3 = sys.version_info[0] == 3
+if PY3:
+    xrange = range
+
+from tests_common import NewOpenCVTests
+
+def make_gaussians(cluster_n, img_size):
+    points = []
+    ref_distrs = []
+    sizes = []
+    for i in xrange(cluster_n):
+        mean = (0.1 + 0.8*random.rand(2)) * img_size
+        a = (random.rand(2, 2)-0.5)*img_size*0.1
+        cov = np.dot(a.T, a) + img_size*0.05*np.eye(2)
+        n = 100 + random.randint(900)
+        pts = random.multivariate_normal(mean, cov, n)
+        points.append( pts )
+        ref_distrs.append( (mean, cov) )
+        sizes.append(n)
+    points = np.float32( np.vstack(points) )
+    return points, ref_distrs, sizes
+
+def getMainLabelConfidence(labels, nLabels):
+
+    n = len(labels)
+    labelsDict = dict.fromkeys(range(nLabels), 0)
+    labelsConfDict = dict.fromkeys(range(nLabels))
+
+    for i in range(n):
+        labelsDict[labels[i][0]] += 1
+
+    for i in range(nLabels):
+        labelsConfDict[i] = float(labelsDict[i]) / n
+
+    return max(labelsConfDict.values())
+
+class kmeans_test(NewOpenCVTests):
+
+    def test_kmeans(self):
+
+        np.random.seed(10)
+
+        cluster_n = 5
+        img_size = 512
+
+        points, _, clusterSizes = make_gaussians(cluster_n, img_size)
+
+        term_crit = (cv2.TERM_CRITERIA_EPS, 30, 0.1)
+        ret, labels, centers = cv2.kmeans(points, cluster_n, term_crit, 10, 0)
+
+        self.assertEqual(len(centers), cluster_n)
+
+        offset = 0
+        for i in range(cluster_n):
+            confidence = getMainLabelConfidence(labels[offset : (offset + clusterSizes[i])], cluster_n)
+            offset += clusterSizes[i]
+            self.assertGreater(confidence, 0.9)
\ No newline at end of file
diff --git a/modules/python/test/test_letter_recog.py b/modules/python/test/test_letter_recog.py
new file mode 100644
index 0000000..05f8799
--- /dev/null
+++ b/modules/python/test/test_letter_recog.py
@@ -0,0 +1,161 @@
+#!/usr/bin/env python
+
+'''
+The sample demonstrates how to train Random Trees classifier
+(or Boosting classifier, or MLP, or Knearest, or Support Vector Machines) using the provided dataset.
+
+We use the sample database letter-recognition.data
+from UCI Repository, here is the link:
+
+Newman, D.J. & Hettich, S. & Blake, C.L. & Merz, C.J. (1998).
+UCI Repository of machine learning databases
+[http://www.ics.uci.edu/~mlearn/MLRepository.html].
+Irvine, CA: University of California, Department of Information and Computer Science.
+
+The dataset consists of 20000 feature vectors along with the
+responses - capital latin letters A..Z.
+The first 10000 samples are used for training
+and the remaining 10000 - to test the classifier.
+======================================================
+  Models: RTrees, KNearest, Boost, SVM, MLP
+'''
+
+# Python 2/3 compatibility
+from __future__ import print_function
+
+import numpy as np
+import cv2
+
+def load_base(fn):
+    a = np.loadtxt(fn, np.float32, delimiter=',', converters={ 0 : lambda ch : ord(ch)-ord('A') })
+    samples, responses = a[:,1:], a[:,0]
+    return samples, responses
+
+class LetterStatModel(object):
+    class_n = 26
+    train_ratio = 0.5
+
+    def load(self, fn):
+        self.model.load(fn)
+    def save(self, fn):
+        self.model.save(fn)
+
+    def unroll_samples(self, samples):
+        sample_n, var_n = samples.shape
+        new_samples = np.zeros((sample_n * self.class_n, var_n+1), np.float32)
+        new_samples[:,:-1] = np.repeat(samples, self.class_n, axis=0)
+        new_samples[:,-1] = np.tile(np.arange(self.class_n), sample_n)
+        return new_samples
+
+    def unroll_responses(self, responses):
+        sample_n = len(responses)
+        new_responses = np.zeros(sample_n*self.class_n, np.int32)
+        resp_idx = np.int32( responses + np.arange(sample_n)*self.class_n )
+        new_responses[resp_idx] = 1
+        return new_responses
+
+class RTrees(LetterStatModel):
+    def __init__(self):
+        self.model = cv2.RTrees()
+
+    def train(self, samples, responses):
+        sample_n, var_n = samples.shape
+        params = dict(max_depth=20 )
+        self.model.train(samples, cv2.CV_ROW_SAMPLE, responses.astype(int), params = params)
+
+    def predict(self, samples):
+        return np.float32( [self.model.predict(s) for s in samples] )
+
+
+class KNearest(LetterStatModel):
+    def __init__(self):
+        self.model = cv2.KNearest()
+
+    def train(self, samples, responses):
+        self.model.train(samples, responses)
+
+    def predict(self, samples):
+        retval, results, neigh_resp, dists = self.model.find_nearest(samples, k = 10)
+        return results.ravel()
+
+
+class Boost(LetterStatModel):
+    def __init__(self):
+        self.model = cv2.Boost()
+
+    def train(self, samples, responses):
+        sample_n, var_n = samples.shape
+        new_samples = self.unroll_samples(samples)
+        new_responses = self.unroll_responses(responses)
+        var_types = np.array([cv2.CV_VAR_NUMERICAL] * var_n + [cv2.CV_VAR_CATEGORICAL, cv2.CV_VAR_CATEGORICAL], np.uint8)
+        params = dict(max_depth=10, weak_count=15)
+        self.model.train(new_samples, cv2.CV_ROW_SAMPLE, new_responses.astype(int), varType = var_types, params=params)
+
+    def predict(self, samples):
+        new_samples = self.unroll_samples(samples)
+        pred = np.array( [self.model.predict(s) for s in new_samples] )
+        pred = pred.reshape(-1, self.class_n).argmax(1)
+        return pred
+
+
+class SVM(LetterStatModel):
+    def __init__(self):
+        self.model = cv2.SVM()
+
+    def train(self, samples, responses):
+        params = dict( kernel_type = cv2.SVM_RBF,
+                       svm_type = cv2.SVM_C_SVC,
+                       C = 1,
+                       gamma = .1 )
+        self.model.train(samples, responses.astype(int), params = params)
+
+    def predict(self, samples):
+        return self.model.predict_all(samples).ravel()
+
+
+class MLP(LetterStatModel):
+    def __init__(self):
+        self.model = cv2.ANN_MLP()
+
+    def train(self, samples, responses):
+        sample_n, var_n = samples.shape
+        new_responses = self.unroll_responses(responses).reshape(-1, self.class_n)
+        layer_sizes = np.int32([var_n, 100, 100, self.class_n])
+
+        self.model.create(layer_sizes, cv2.ANN_MLP_SIGMOID_SYM, 2, 1)
+        params = dict( train_method = cv2.ANN_MLP_TRAIN_PARAMS_BACKPROP,
+                       bp_moment_scale = 0.0,
+                       bp_dw_scale = 0.001,
+                       term_crit = (cv2.TERM_CRITERIA_COUNT, 20, 0.01) )
+        self.model.train(samples, np.float32(new_responses), None, params = params)
+
+    def predict(self, samples):
+        ret, resp = self.model.predict(samples)
+        return resp.argmax(-1)
+
+from tests_common import NewOpenCVTests
+
+class letter_recog_test(NewOpenCVTests):
+
+    def test_letter_recog(self):
+
+        eps = 0.01
+
+        models = [RTrees, KNearest, Boost, SVM, MLP]
+        models = dict( [(cls.__name__.lower(), cls) for cls in models] )
+        testErrors = {RTrees: (98.930000, 92.390000), KNearest: (94.960000, 92.010000),
+         Boost: (85.970000, 74.920000), SVM: (99.780000, 95.680000), MLP: (90.060000, 87.410000)}
+
+        for model in models:
+            Model = models[model]
+            classifier = Model()
+
+            samples, responses = load_base(self.repoPath + '/samples/data/letter-recognition.data')
+            train_n = int(len(samples)*classifier.train_ratio)
+
+            classifier.train(samples[:train_n], responses[:train_n])
+            train_rate = np.mean(classifier.predict(samples[:train_n]) == responses[:train_n].astype(int))
+            test_rate  = np.mean(classifier.predict(samples[train_n:]) == responses[train_n:].astype(int))
+
+            self.assertLess(train_rate - testErrors[Model][0], eps)
+            self.assertLess(test_rate - testErrors[Model][1], eps)
\ No newline at end of file
diff --git a/modules/python/test/test_lk_homography.py b/modules/python/test/test_lk_homography.py
new file mode 100644
index 0000000..8e526d0
--- /dev/null
+++ b/modules/python/test/test_lk_homography.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+
+'''
+Lucas-Kanade homography tracker test
+===============================
+Uses goodFeaturesToTrack for track initialization and back-tracking for match verification
+between frames. Finds homography between reference and current views.
+'''
+
+# Python 2/3 compatibility
+from __future__ import print_function
+
+import numpy as np
+import cv2
+
+#local modules
+from tst_scene_render import TestSceneRender
+from tests_common import NewOpenCVTests, isPointInRect
+
+lk_params = dict( winSize  = (19, 19),
+                  maxLevel = 2,
+                  criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
+
+feature_params = dict( maxCorners = 1000,
+                       qualityLevel = 0.01,
+                       minDistance = 8,
+                       blockSize = 19 )
+
+def checkedTrace(img0, img1, p0, back_threshold = 1.0):
+    p1, st, err = cv2.calcOpticalFlowPyrLK(img0, img1, p0, None, **lk_params)
+    p0r, st, err = cv2.calcOpticalFlowPyrLK(img1, img0, p1, None, **lk_params)
+    d = abs(p0-p0r).reshape(-1, 2).max(-1)
+    status = d < back_threshold
+    return p1, status
+
+class lk_homography_test(NewOpenCVTests):
+
+    render = None
+    framesCounter = 0
+    frame = frame0 = None
+    p0 = None
+    p1 = None
+    gray0 = gray1 = None
+    numFeaturesInRectOnStart = 0
+
+    def test_lk_homography(self):
+        self.render = TestSceneRender(self.get_sample('samples/data/graf1.png'),
+            self.get_sample('samples/data/box.png'), noise = 0.1, speed = 1.0)
+
+        frame = self.render.getNextFrame()
+        frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
+        self.frame0 = frame.copy()
+        self.p0 = cv2.goodFeaturesToTrack(frame_gray, **feature_params)
+
+        isForegroundHomographyFound = False
+
+        if self.p0 is not None:
+            self.p1 = self.p0
+            self.gray0 = frame_gray
+            self.gray1 = frame_gray
+            currRect = self.render.getCurrentRect()
+            for (x,y) in self.p0[:,0]:
+                if isPointInRect((x,y), currRect):
+                    self.numFeaturesInRectOnStart += 1
+
+        while self.framesCounter < 200:
+            self.framesCounter += 1
+            frame = self.render.getNextFrame()
+            frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
+            if self.p0 is not None:
+                p2, trace_status = checkedTrace(self.gray1, frame_gray, self.p1)
+
+                self.p1 = p2[trace_status].copy()
+                self.p0 = self.p0[trace_status].copy()
+                self.gray1 = frame_gray
+
+                if len(self.p0) < 4:
+                    self.p0 = None
+                    continue
+                H, status = cv2.findHomography(self.p0, self.p1, cv2.RANSAC, 5.0)
+
+                goodPointsInRect = 0
+                goodPointsOutsideRect = 0
+                for (x0, y0), (x1, y1), good in zip(self.p0[:,0], self.p1[:,0], status[:,0]):
+                    if good:
+                        if isPointInRect((x1,y1), self.render.getCurrentRect()):
+                            goodPointsInRect += 1
+                        else: goodPointsOutsideRect += 1
+
+                if goodPointsOutsideRect < goodPointsInRect:
+                    isForegroundHomographyFound = True
+                    self.assertGreater(float(goodPointsInRect) / (self.numFeaturesInRectOnStart + 1), 0.6)
+            else:
+                p = cv2.goodFeaturesToTrack(frame_gray, **feature_params)
+
+        self.assertEqual(isForegroundHomographyFound, True)
\ No newline at end of file
diff --git a/modules/python/test/test_lk_track.py b/modules/python/test/test_lk_track.py
new file mode 100644
index 0000000..ccc67a5
--- /dev/null
+++ b/modules/python/test/test_lk_track.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python
+
+'''
+Lucas-Kanade tracker
+====================
+
+Lucas-Kanade sparse optical flow demo. Uses goodFeaturesToTrack
+for track initialization and back-tracking for match verification
+between frames.
+'''
+
+# Python 2/3 compatibility
+from __future__ import print_function
+
+import numpy as np
+import cv2
+
+#local modules
+from tst_scene_render import TestSceneRender
+from tests_common import NewOpenCVTests, intersectionRate, isPointInRect
+
+lk_params = dict( winSize  = (15, 15),
+                  maxLevel = 2,
+                  criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
+
+feature_params = dict( maxCorners = 500,
+                       qualityLevel = 0.3,
+                       minDistance = 7,
+                       blockSize = 7 )
+
+def getRectFromPoints(points):
+
+    distances = []
+    for point in points:
+        distances.append(cv2.norm(point, cv2.NORM_L2))
+
+    x0, y0 = points[np.argmin(distances)]
+    x1, y1 = points[np.argmax(distances)]
+
+    return np.array([x0, y0, x1, y1])
+
+
+class lk_track_test(NewOpenCVTests):
+
+    track_len = 10
+    detect_interval = 5
+    tracks = []
+    frame_idx = 0
+    render = None
+
+    def test_lk_track(self):
+
+        self.render = TestSceneRender(self.get_sample('samples/data/graf1.png'), self.get_sample('samples/data/box.png'))
+        self.runTracker()
+
+    def runTracker(self):
+        foregroundPointsNum = 0
+
+        while True:
+            frame = self.render.getNextFrame()
+            frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
+
+            if len(self.tracks) > 0:
+                img0, img1 = self.prev_gray, frame_gray
+                p0 = np.float32([tr[-1][0] for tr in self.tracks]).reshape(-1, 1, 2)
+                p1, st, err = cv2.calcOpticalFlowPyrLK(img0, img1, p0, None, **lk_params)
+                p0r, st, err = cv2.calcOpticalFlowPyrLK(img1, img0, p1, None, **lk_params)
+                d = abs(p0-p0r).reshape(-1, 2).max(-1)
+                good = d < 1
+                new_tracks = []
+                for tr, (x, y), good_flag in zip(self.tracks, p1.reshape(-1, 2), good):
+                    if not good_flag:
+                        continue
+                    tr.append([(x, y), self.frame_idx])
+                    if len(tr) > self.track_len:
+                        del tr[0]
+                    new_tracks.append(tr)
+                self.tracks = new_tracks
+
+            if self.frame_idx % self.detect_interval == 0:
+                goodTracksCount = 0
+                for tr in self.tracks:
+                    oldRect = self.render.getRectInTime(self.render.timeStep * tr[0][1])
+                    newRect = self.render.getRectInTime(self.render.timeStep * tr[-1][1])
+                    if isPointInRect(tr[0][0], oldRect) and isPointInRect(tr[-1][0], newRect):
+                        goodTracksCount += 1
+
+                if self.frame_idx == self.detect_interval:
+                    foregroundPointsNum = goodTracksCount
+
+                fgIndex = float(foregroundPointsNum) / (foregroundPointsNum + 1)
+                fgRate = float(goodTracksCount) / (len(self.tracks) + 1)
+
+                if self.frame_idx > 0:
+                    self.assertGreater(fgIndex, 0.9)
+                    self.assertGreater(fgRate, 0.2)
+
+                mask = np.zeros_like(frame_gray)
+                mask[:] = 255
+                for x, y in [np.int32(tr[-1][0]) for tr in self.tracks]:
+                    cv2.circle(mask, (x, y), 5, 0, -1)
+                p = cv2.goodFeaturesToTrack(frame_gray, mask = mask, **feature_params)
+                if p is not None:
+                    for x, y in np.float32(p).reshape(-1, 2):
+                        self.tracks.append([[(x, y), self.frame_idx]])
+
+            self.frame_idx += 1
+            self.prev_gray = frame_gray
+
+            if self.frame_idx > 300:
+                break
\ No newline at end of file
diff --git a/modules/python/test/test_morphology.py b/modules/python/test/test_morphology.py
new file mode 100644
index 0000000..309c80c
--- /dev/null
+++ b/modules/python/test/test_morphology.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+
+'''
+Morphology operations.
+'''
+
+# Python 2/3 compatibility
+from __future__ import print_function
+import sys
+PY3 = sys.version_info[0] == 3
+
+import numpy as np
+import cv2
+
+from tests_common import NewOpenCVTests
+
+class morphology_test(NewOpenCVTests):
+
+    def test_morphology(self):
+
+        fn = 'samples/data/rubberwhale1.png'
+        img = self.get_sample(fn)
+
+        modes = ['erode/dilate', 'open/close', 'blackhat/tophat', 'gradient']
+        str_modes = ['ellipse', 'rect', 'cross']
+
+        referenceHashes = { modes[0]: '071a526425b79e45b4d0d71ef51b0562', modes[1] : '071a526425b79e45b4d0d71ef51b0562',
+            modes[2] : '427e89f581b7df1b60a831b1ed4c8618', modes[3] : '0dd8ad251088a63d0dd022bcdc57361c'}
+
+        def update(cur_mode):
+            cur_str_mode = str_modes[0]
+            sz = 10
+            iters = 1
+            opers = cur_mode.split('/')
+            if len(opers) > 1:
+                sz = sz - 10
+                op = opers[sz > 0]
+                sz = abs(sz)
+            else:
+                op = opers[0]
+            sz = sz*2+1
+
+            str_name = 'MORPH_' + cur_str_mode.upper()
+            oper_name = 'MORPH_' + op.upper()
+
+            st = cv2.getStructuringElement(getattr(cv2, str_name), (sz, sz))
+            return cv2.morphologyEx(img, getattr(cv2, oper_name), st, iterations=iters)
+
+        for mode in modes:
+            res = update(mode)
+            self.assertEqual(self.hashimg(res), referenceHashes[mode])
\ No newline at end of file
diff --git a/modules/python/test/test_mser.py b/modules/python/test/test_mser.py
new file mode 100644
index 0000000..dfdb30a
--- /dev/null
+++ b/modules/python/test/test_mser.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+
+'''
+MSER detector test
+'''
+# Python 2/3 compatibility
+from __future__ import print_function
+
+import numpy as np
+import cv2
+
+from tests_common import NewOpenCVTests
+
+class mser_test(NewOpenCVTests):
+    def test_mser(self):
+
+        img = self.get_sample('cv/mser/puzzle.png', 0)
+        smallImg = [
+         [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
+         [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
+         [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
+         [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
+         [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
+         [255, 255, 255, 255, 255,   0,   0,   0,   0, 255, 255, 255, 255, 255, 255, 255, 255, 255,   0,   0,   0,   0, 255, 255, 255, 255],
+         [255, 255, 255, 255, 255,   0,   0,   0,   0,   0, 255, 255, 255, 255, 255, 255, 255, 255,   0,   0,   0,   0, 255, 255, 255, 255],
+         [255, 255, 255, 255, 255,   0,   0,   0,   0,   0, 255, 255, 255, 255, 255, 255, 255, 255,   0,   0,   0,   0, 255, 255, 255, 255],
+         [255, 255, 255, 255, 255,   0,   0,   0,   0, 255, 255, 255, 255, 255, 255, 255, 255, 255,   0,   0,   0,   0, 255, 255, 255, 255],
+         [255, 255, 255, 255, 255, 255,   0,   0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   0,   0, 255, 255, 255, 255, 255],
+         [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
+         [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
+         [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
+         [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]
+        ]
+        thresharr = [ 0, 70, 120, 180, 255 ]
+        kDelta = 5
+        np.random.seed(10)
+
+        for i in range(100):
+
+            use_big_image = int(np.random.rand(1,1)*7) != 0
+            invert = int(np.random.rand(1,1)*2) != 0
+            binarize = int(np.random.rand(1,1)*5) != 0 if use_big_image else False
+            blur = int(np.random.rand(1,1)*2) != 0
+            thresh = thresharr[int(np.random.rand(1,1)*5)]
+            src0 = img if use_big_image else np.array(smallImg).astype('uint8')
+            src = src0.copy()
+
+            kMinArea = 256 if use_big_image else 10
+            kMaxArea = int(src.shape[0]*src.shape[1]/4)
+
+            mserExtractor = cv2.MSER(kDelta, kMinArea, kMaxArea)
+            if invert:
+                cv2.bitwise_not(src, src)
+            if binarize:
+                _, src = cv2.threshold(src, thresh, 255, cv2.THRESH_BINARY)
+            if blur:
+                src = cv2.GaussianBlur(src, (5, 5), 1.5, 1.5)
+            minRegs = 7 if use_big_image else 2
+            maxRegs = 1000 if use_big_image else 15
+            if binarize and (thresh == 0 or thresh == 255):
+                minRegs = maxRegs = 0
+            msers = mserExtractor.detect(src)
+            nmsers = len(msers)
+            self.assertLessEqual(minRegs, nmsers)
+            self.assertGreaterEqual(maxRegs, nmsers)
\ No newline at end of file
diff --git a/modules/python/test/test_peopledetect.py b/modules/python/test/test_peopledetect.py
new file mode 100644
index 0000000..fb0a9e9
--- /dev/null
+++ b/modules/python/test/test_peopledetect.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+
+'''
+example to detect upright people in images using HOG features
+'''
+
+# Python 2/3 compatibility
+from __future__ import print_function
+
+import numpy as np
+import cv2
+
+
+def inside(r, q):
+    rx, ry, rw, rh = r
+    qx, qy, qw, qh = q
+    return rx > qx and ry > qy and rx + rw < qx + qw and ry + rh < qy + qh
+
+from tests_common import NewOpenCVTests, intersectionRate
+
+class peopledetect_test(NewOpenCVTests):
+    def test_peopledetect(self):
+
+        hog = cv2.HOGDescriptor()
+        hog.setSVMDetector( cv2.HOGDescriptor_getDefaultPeopleDetector() )
+
+        dirPath = 'samples/data/'
+        samples = ['basketball1.png', 'basketball2.png']
+
+        testPeople = [
+        [[23, 76, 164, 477], [440, 22, 637, 478]],
+        [[23, 76, 164, 477], [440, 22, 637, 478]]
+        ]
+
+        eps = 0.5
+
+        for sample in samples:
+
+            img = self.get_sample(dirPath + sample, 0)
+
+            found, w = hog.detectMultiScale(img, winStride=(8,8), padding=(32,32), scale=1.05)
+            found_filtered = []
+            for ri, r in enumerate(found):
+                for qi, q in enumerate(found):
+                    if ri != qi and inside(r, q):
+                        break
+                else:
+                    found_filtered.append(r)
+
+            matches = 0
+
+            for i in range(len(found_filtered)):
+                for j in range(len(testPeople)):
+
+                    found_rect = (found_filtered[i][0], found_filtered[i][1],
+                        found_filtered[i][0] + found_filtered[i][2],
+                        found_filtered[i][1] + found_filtered[i][3])
+
+                    if intersectionRate(found_rect, testPeople[j][0]) > eps or intersectionRate(found_rect, testPeople[j][1]) > eps:
+                        matches += 1
+
+            self.assertGreater(matches, 0)
\ No newline at end of file
diff --git a/modules/python/test/test_squares.py b/modules/python/test/test_squares.py
new file mode 100644
index 0000000..3b3fbb6
--- /dev/null
+++ b/modules/python/test/test_squares.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+
+'''
+Simple "Square Detector" program.
+
+Loads several images sequentially and tries to find squares in each image.
+'''
+
+# Python 2/3 compatibility
+import sys
+PY3 = sys.version_info[0] == 3
+
+if PY3:
+    xrange = range
+
+import numpy as np
+import cv2
+
+
+def angle_cos(p0, p1, p2):
+    d1, d2 = (p0-p1).astype('float'), (p2-p1).astype('float')
+    return abs( np.dot(d1, d2) / np.sqrt( np.dot(d1, d1)*np.dot(d2, d2) ) )
+
+def find_squares(img):
+    img = cv2.GaussianBlur(img, (5, 5), 0)
+    squares = []
+    for gray in cv2.split(img):
+        for thrs in xrange(0, 255, 26):
+            if thrs == 0:
+                bin = cv2.Canny(gray, 0, 50, apertureSize=5)
+                bin = cv2.dilate(bin, None)
+            else:
+                retval, bin = cv2.threshold(gray, thrs, 255, cv2.THRESH_BINARY)
+            contours, hierarchy = cv2.findContours(bin, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
+            for cnt in contours:
+                cnt_len = cv2.arcLength(cnt, True)
+                cnt = cv2.approxPolyDP(cnt, 0.02*cnt_len, True)
+                if len(cnt) == 4 and cv2.contourArea(cnt) > 1000 and cv2.isContourConvex(cnt):
+                    cnt = cnt.reshape(-1, 2)
+                    max_cos = np.max([angle_cos( cnt[i], cnt[(i+1) % 4], cnt[(i+2) % 4] ) for i in xrange(4)])
+                    if max_cos < 0.1 and filterSquares(squares, cnt):
+                        squares.append(cnt)
+
+    return squares
+
+def intersectionRate(s1, s2):
+    area, intersection = cv2.intersectConvexConvex(np.array(s1), np.array(s2))
+    return 2 * area / (cv2.contourArea(np.array(s1)) + cv2.contourArea(np.array(s2)))
+
+def filterSquares(squares, square):
+
+    for i in range(len(squares)):
+        if intersectionRate(squares[i], square) > 0.95:
+            return False
+
+    return True
+
+from tests_common import NewOpenCVTests
+
+class squares_test(NewOpenCVTests):
+
+    def test_squares(self):
+
+        img = self.get_sample('samples/data/pic1.png')
+        squares = find_squares(img)
+
+        testSquares = [
+        [[43, 25],
+        [43, 129],
+        [232, 129],
+        [232, 25]],
+
+        [[252, 87],
+        [324, 40],
+        [387, 137],
+        [315, 184]],
+
+        [[154, 178],
+        [196, 180],
+        [198, 278],
+        [154, 278]],
+
+        [[0, 0],
+        [400, 0],
+        [400, 300],
+        [0, 300]]
+        ]
+
+        matches_counter = 0
+        for i in range(len(squares)):
+            for j in range(len(testSquares)):
+                if intersectionRate(squares[i], testSquares[j]) > 0.9:
+                    matches_counter += 1
+
+        self.assertGreater(matches_counter / len(testSquares), 0.9)
+        self.assertLess( (len(squares) - matches_counter) / len(squares), 0.2)
\ No newline at end of file
diff --git a/modules/python/test/test_texture_flow.py b/modules/python/test/test_texture_flow.py
new file mode 100644
index 0000000..7dc3b07
--- /dev/null
+++ b/modules/python/test/test_texture_flow.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+
+'''
+Texture flow direction estimation.
+
+Sample shows how cv2.cornerEigenValsAndVecs function can be used
+to estimate image texture flow direction.
+'''
+
+# Python 2/3 compatibility
+from __future__ import print_function
+
+import numpy as np
+import cv2
+import sys
+
+from tests_common import NewOpenCVTests
+
+
+class texture_flow_test(NewOpenCVTests):
+
+    def test_texture_flow(self):
+
+        img = self.get_sample('samples/data/pic6.png')
+
+        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
+        h, w = img.shape[:2]
+
+        eigen = cv2.cornerEigenValsAndVecs(gray, 15, 3)
+        eigen = eigen.reshape(h, w, 3, 2)  # [[e1, e2], v1, v2]
+        flow = eigen[:,:,2]
+
+        vis = img.copy()
+        vis[:] = (192 + np.uint32(vis)) / 2
+        d = 80
+        points =  np.dstack( np.mgrid[d/2:w:d, d/2:h:d] ).reshape(-1, 2)
+
+        textureVectors = []
+
+        for x, y in np.int32(points):
+            textureVectors.append(np.int32(flow[y, x]*d))
+
+        eps = 0.05
+
+        testTextureVectors = [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0],
+        [-38, 70], [-79, 3], [0, 0], [0, 0], [-39, 69], [-79, -1],
+        [0, 0], [0, 0], [0, -79], [17, -78], [-48, -63], [65, -46],
+        [-69, -39], [-48, -63], [-45, 66]]
+
+        for i in range(len(textureVectors)):
+            self.assertLessEqual(cv2.norm(textureVectors[i] - testTextureVectors[i], cv2.NORM_L2), eps)
\ No newline at end of file
diff --git a/modules/python/test/test_watershed.py b/modules/python/test/test_watershed.py
new file mode 100644
index 0000000..0a1d222
--- /dev/null
+++ b/modules/python/test/test_watershed.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+
+'''
+Watershed segmentation test
+'''
+
+# Python 2/3 compatibility
+from __future__ import print_function
+
+import numpy as np
+import cv2
+
+from tests_common import NewOpenCVTests
+
+class watershed_test(NewOpenCVTests):
+    def test_watershed(self):
+
+        img = self.get_sample('cv/inpaint/orig.png')
+        markers = self.get_sample('cv/watershed/wshed_exp.png', 0)
+        refSegments = self.get_sample('cv/watershed/wshed_segments.png')
+
+        if img is None or markers is None:
+            self.assertEqual(0, 1, 'Missing test data')
+
+        colors = np.int32( list(np.ndindex(3, 3, 3)) ) * 122
+        cv2.watershed(img, np.int32(markers))
+        segments = colors[np.maximum(markers, 0)]
+
+        if refSegments is None:
+            refSegments = segments.copy()
+            cv2.imwrite(self.extraTestDataPath + '/cv/watershed/wshed_segments.png', refSegments)
+
+        self.assertLess(cv2.norm(segments - refSegments, cv2.NORM_L1) / 255.0, 50)
\ No newline at end of file
diff --git a/modules/python/test/tests_common.py b/modules/python/test/tests_common.py
new file mode 100644
index 0000000..3a636b2
--- /dev/null
+++ b/modules/python/test/tests_common.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+
+import unittest
+import sys
+import hashlib
+import os
+import numpy as np
+import cv2
+
+# Python 3 moved urlopen to urllib.requests
+try:
+    from urllib.request import urlopen
+except ImportError:
+    from urllib import urlopen
+
+class NewOpenCVTests(unittest.TestCase):
+
+    # path to local repository folder containing 'samples' folder
+    repoPath = None
+    extraTestDataPath = None
+    # github repository url
+    repoUrl = 'https://raw.github.com/Itseez/opencv/master'
+
+    def get_sample(self, filename, iscolor = cv2.IMREAD_COLOR):
+        if not filename in self.image_cache:
+            filedata = None
+            if NewOpenCVTests.repoPath is not None:
+                candidate = NewOpenCVTests.repoPath + '/' + filename
+                if os.path.isfile(candidate):
+                    with open(candidate, 'rb') as f:
+                        filedata = f.read()
+            if NewOpenCVTests.extraTestDataPath is not None:
+                candidate = NewOpenCVTests.extraTestDataPath + '/' + filename
+                if os.path.isfile(candidate):
+                    with open(candidate, 'rb') as f:
+                        filedata = f.read()
+            if filedata is None:
+                return None#filedata = urlopen(NewOpenCVTests.repoUrl + '/' + filename).read()
+            self.image_cache[filename] = cv2.imdecode(np.fromstring(filedata, dtype=np.uint8), iscolor)
+        return self.image_cache[filename]
+
+    def setUp(self):
+        self.image_cache = {}
+
+    def hashimg(self, im):
+        """ Compute a hash for an image, useful for image comparisons """
+        return hashlib.md5(im.tostring()).hexdigest()
+
+    if sys.version_info[:2] == (2, 6):
+        def assertLess(self, a, b, msg=None):
+            if not a < b:
+                self.fail('%s not less than %s' % (repr(a), repr(b)))
+
+        def assertLessEqual(self, a, b, msg=None):
+            if not a <= b:
+                self.fail('%s not less than or equal to %s' % (repr(a), repr(b)))
+
+        def assertGreater(self, a, b, msg=None):
+            if not a > b:
+                self.fail('%s not greater than %s' % (repr(a), repr(b)))
+
+def intersectionRate(s1, s2):
+
+    x1, y1, x2, y2 = s1
+    s1 = np.array([[x1, y1], [x2,y1], [x2, y2], [x1, y2]])
+
+    x1, y1, x2, y2 = s2
+    s2 = np.array([[x1, y1], [x2,y1], [x2, y2], [x1, y2]])
+
+    area, intersection = cv2.intersectConvexConvex(s1, s2)
+    return 2 * area / (cv2.contourArea(s1) + cv2.contourArea(s2))
+
+def isPointInRect(p, rect):
+    if rect[0] <= p[0] and rect[1] <=p[1] and p[0] <= rect[2] and p[1] <= rect[3]:
+        return True
+    else:
+        return False
\ No newline at end of file
diff --git a/modules/python/test/tst_scene_render.py b/modules/python/test/tst_scene_render.py
new file mode 100644
index 0000000..49cde80
--- /dev/null
+++ b/modules/python/test/tst_scene_render.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python
+
+
+# Python 2/3 compatibility
+from __future__ import print_function
+
+import numpy as np
+from numpy import pi, sin, cos
+
+import cv2
+
+defaultSize = 512
+
+class TestSceneRender():
+
+    def __init__(self, bgImg = None, fgImg = None, deformation = False, noise = 0.0, speed = 0.25, **params):
+        self.time = 0.0
+        self.timeStep = 1.0 / 30.0
+        self.foreground = fgImg
+        self.deformation = deformation
+        self.noise = noise
+        self.speed = speed
+
+        if bgImg is not None:
+            self.sceneBg = bgImg.copy()
+        else:
+            self.sceneBg = np.zeros(defaultSize, defaultSize, np.uint8)
+
+        self.w = self.sceneBg.shape[0]
+        self.h = self.sceneBg.shape[1]
+
+        if fgImg is not None:
+            self.foreground = fgImg.copy()
+            self.center = self.currentCenter = (int(self.w/2 - fgImg.shape[0]/2), int(self.h/2 - fgImg.shape[1]/2))
+
+            self.xAmpl = self.sceneBg.shape[0] - (self.center[0] + fgImg.shape[0])
+            self.yAmpl = self.sceneBg.shape[1] - (self.center[1] + fgImg.shape[1])
+
+        self.initialRect = np.array([ (self.h/2, self.w/2), (self.h/2, self.w/2 + self.w/10),
+         (self.h/2 + self.h/10, self.w/2 + self.w/10), (self.h/2 + self.h/10, self.w/2)]).astype(int)
+        self.currentRect = self.initialRect
+        np.random.seed(10)
+
+    def getXOffset(self, time):
+        return int(self.xAmpl*cos(time*self.speed))
+
+
+    def getYOffset(self, time):
+        return int(self.yAmpl*sin(time*self.speed))
+
+    def setInitialRect(self, rect):
+        self.initialRect = rect
+
+    def getRectInTime(self, time):
+
+        if self.foreground is not None:
+            tmp = np.array(self.center) + np.array((self.getXOffset(time), self.getYOffset(time)))
+            x0, y0 = tmp
+            x1, y1 = tmp + self.foreground.shape[0:2]
+            return np.array([y0, x0, y1, x1])
+        else:
+            x0, y0 = self.initialRect[0] + np.array((self.getXOffset(time), self.getYOffset(time)))
+            x1, y1 = self.initialRect[2] + np.array((self.getXOffset(time), self.getYOffset(time)))
+            return np.array([y0, x0, y1, x1])
+
+    def getCurrentRect(self):
+
+        if self.foreground is not None:
+
+            x0 = self.currentCenter[0]
+            y0 = self.currentCenter[1]
+            x1 = self.currentCenter[0] + self.foreground.shape[0]
+            y1 = self.currentCenter[1] + self.foreground.shape[1]
+            return np.array([y0, x0, y1, x1])
+        else:
+            x0, y0 = self.currentRect[0]
+            x1, y1 = self.currentRect[2]
+            return np.array([x0, y0, x1, y1])
+
+    def getNextFrame(self):
+        img = self.sceneBg.copy()
+
+        if self.foreground is not None:
+            self.currentCenter = (self.center[0] + self.getXOffset(self.time), self.center[1] + self.getYOffset(self.time))
+            img[self.currentCenter[0]:self.currentCenter[0]+self.foreground.shape[0],
+             self.currentCenter[1]:self.currentCenter[1]+self.foreground.shape[1]] = self.foreground
+        else:
+            self.currentRect = self.initialRect + np.int( 30*cos(self.time) + 50*sin(self.time/3))
+            if self.deformation:
+                self.currentRect[1:3] += int(self.h/20*cos(self.time))
+            cv2.fillConvexPoly(img, self.currentRect, (0, 0, 255))
+
+        self.time += self.timeStep
+
+        if self.noise:
+            noise = np.zeros(self.sceneBg.shape, np.int8)
+            cv2.randn(noise, np.zeros(3), np.ones(3)*255*self.noise)
+            img = cv2.add(img, noise, dtype=cv2.CV_8UC3)
+        return img
+
+    def resetTime(self):
+        self.time = 0.0
+
+
+if __name__ == '__main__':
+
+    backGr = cv2.imread('../../../samples/data/lena.jpg')
+
+    render = TestSceneRender(backGr, noise = 0.5)
+
+    while True:
+
+        img = render.getNextFrame()
+        cv2.imshow('img', img)
+
+        ch = 0xFF & cv2.waitKey(3)
+        if  ch == 27:
+            break
+    cv2.destroyAllWindows()
\ No newline at end of file

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/opencv.git



More information about the debian-science-commits mailing list