mirror of https://github.com/opencv/opencv.git
Merge pull request #6171 from terfendail:vt/new_python_tests_backport
commit
3afb5a6006
26 changed files with 1989 additions and 31 deletions
@ -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/cpp/left0{}.jpg'.format(str(i))) |
||||
elif i != 10: |
||||
img_names.append('samples/cpp/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) |
@ -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/python2/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() |
@ -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/gpu/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) |
@ -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/python2/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) |
@ -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/c/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) |
@ -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/python2/data/graf1.png'), |
||||
self.get_sample('samples/c/box.png'), noise = 0.4, 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 |
@ -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) |
@ -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) |
@ -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) |
@ -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/cpp/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) |
@ -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/cpp/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) |
@ -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) |
@ -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/cpp/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) |
@ -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/python2/data/graf1.png'), |
||||
self.get_sample('samples/c/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) |
@ -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/python2/data/graf1.png'), self.get_sample('samples/c/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 |
@ -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/gpu/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]) |
@ -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 = True #int(np.random.rand(1,1)*2) != 0 #binarized images are processed incorrectly |
||||
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) |
@ -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/gpu/' |
||||
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) |
@ -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/cpp/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) |
@ -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/cpp/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) |
@ -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) |
@ -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 |
@ -0,0 +1,102 @@ |
||||
#!/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 |
After Width: | Height: | Size: 929 KiB |
After Width: | Height: | Size: 32 KiB |
Loading…
Reference in new issue