[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