Merge pull request #6025 from sovrasov:new_python_tests

This commit is contained in:
Vadim Pisarevsky 2016-03-12 17:11:19 +00:00
commit cd1426ba8d
31 changed files with 2058 additions and 77 deletions

View File

@ -361,7 +361,7 @@ public:
*/
CV_WRAP virtual void detectRegions( InputArray image,
CV_OUT std::vector<std::vector<Point> >& msers,
std::vector<Rect>& bboxes ) = 0;
CV_OUT std::vector<Rect>& bboxes ) = 0;
CV_WRAP virtual void setDelta(int delta) = 0;
CV_WRAP virtual int getDelta() const = 0;

52
modules/python/test/test.py Normal file → Executable file
View File

@ -23,48 +23,16 @@ try:
except ImportError:
from urllib import urlopen
class NewOpenCVTests(unittest.TestCase):
# path to local repository folder containing 'samples' folder
repoPath = 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 filedata is 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()).digest()
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)))
from tests_common import NewOpenCVTests
# Tests to run first; check the handful of basic operations that the later tests rely on
basedir = os.path.abspath(os.path.dirname(__file__))
def load_tests(loader, tests, pattern):
tests.addTests(loader.discover(basedir, pattern='test_*.py'))
return tests
class Hackathon244Tests(NewOpenCVTests):
def test_int_array(self):
@ -165,6 +133,10 @@ if __name__ == '__main__':
print("Testing OpenCV", cv2.__version__)
print("Local repo path:", args.repo)
NewOpenCVTests.repoPath = args.repo
try:
NewOpenCVTests.extraTestDataPath = os.environ['OPENCV_TEST_DATA_PATH']
except KeyError:
print('Missing opencv extra repository. Some of tests may fail.')
random.seed(0)
unit_argv = [sys.argv[0]] + other;
unittest.main(argv=unit_argv)
unittest.main(argv=unit_argv)

View File

@ -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)

View File

@ -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()

View File

@ -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)

View File

@ -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.ml.KNearest_create()
def train(self, samples, responses):
self.model.train(samples, cv2.ml.ROW_SAMPLE, responses)
def predict(self, samples):
retval, results, neigh_resp, dists = self.model.findNearest(samples, self.k)
return results.ravel()
class SVM(StatModel):
def __init__(self, C = 1, gamma = 0.5):
self.model = cv2.ml.SVM_create()
self.model.setGamma(gamma)
self.model.setC(C)
self.model.setKernel(cv2.ml.SVM_RBF)
self.model.setType(cv2.ml.SVM_C_SVC)
def train(self, samples, responses):
self.model.train(samples, cv2.ml.ROW_SAMPLE, responses)
def predict(self, samples):
return self.model.predict(samples)[1].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)

View File

@ -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)

View File

@ -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.AKAZE_create(threshold = 0.003)
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 no keypoints found
descrs = []
return keypoints, descrs

View File

@ -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 = ['DIST_L2', 'DIST_L1', 'DIST_L12', 'DIST_FAIR', 'DIST_WELSCH', '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, 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)

View File

@ -0,0 +1,60 @@
#!/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.ml.EM_create()
em.setClustersNumber(cluster_n)
em.setCovarianceMatrixType(cv2.ml.EM_COV_MAT_GENERIC)
em.trainEM(points)
means = em.getMeans()
covs = em.getCovs() # 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)

View File

@ -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)

View File

@ -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.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)

View File

@ -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)

View File

@ -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, None, 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)

View File

@ -0,0 +1,167 @@
#!/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.ml.RTrees_create()
def train(self, samples, responses):
sample_n, var_n = samples.shape
self.model.setMaxDepth(20)
self.model.train(samples, cv2.ml.ROW_SAMPLE, responses.astype(int))
def predict(self, samples):
ret, resp = self.model.predict(samples)
return resp.ravel()
class KNearest(LetterStatModel):
def __init__(self):
self.model = cv2.ml.KNearest_create()
def train(self, samples, responses):
self.model.train(samples, cv2.ml.ROW_SAMPLE, responses)
def predict(self, samples):
retval, results, neigh_resp, dists = self.model.findNearest(samples, k = 10)
return results.ravel()
class Boost(LetterStatModel):
def __init__(self):
self.model = cv2.ml.Boost_create()
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.ml.VAR_NUMERICAL] * var_n + [cv2.ml.VAR_CATEGORICAL, cv2.ml.VAR_CATEGORICAL], np.uint8)
self.model.setWeakCount(15)
self.model.setMaxDepth(10)
self.model.train(cv2.ml.TrainData_create(new_samples, cv2.ml.ROW_SAMPLE, new_responses.astype(int), varType = var_types))
def predict(self, samples):
new_samples = self.unroll_samples(samples)
ret, resp = self.model.predict(new_samples)
return resp.ravel().reshape(-1, self.class_n).argmax(1)
class SVM(LetterStatModel):
def __init__(self):
self.model = cv2.ml.SVM_create()
def train(self, samples, responses):
self.model.setType(cv2.ml.SVM_C_SVC)
self.model.setC(1)
self.model.setKernel(cv2.ml.SVM_RBF)
self.model.setGamma(.1)
self.model.train(samples, cv2.ml.ROW_SAMPLE, responses.astype(int))
def predict(self, samples):
ret, resp = self.model.predict(samples)
return resp.ravel()
class MLP(LetterStatModel):
def __init__(self):
self.model = cv2.ml.ANN_MLP_create()
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.setLayerSizes(layer_sizes)
self.model.setTrainMethod(cv2.ml.ANN_MLP_BACKPROP)
self.model.setBackpropMomentumScale(0)
self.model.setBackpropWeightScale(0.001)
self.model.setTermCriteria((cv2.TERM_CRITERIA_COUNT, 20, 0.01))
self.model.setActivationFunction(cv2.ml.ANN_MLP_SIGMOID_SYM, 2, 1)
self.model.train(samples, cv2.ml.ROW_SAMPLE, np.float32(new_responses))
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)

View File

@ -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)

View File

@ -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

View File

@ -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])

View File

@ -0,0 +1,69 @@
#!/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
mserExtractor = cv2.MSER_create()
mserExtractor.setDelta(kDelta)
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.setMinArea(kMinArea)
mserExtractor.setMaxArea(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, boxes = mserExtractor.detectRegions(src)
nmsers = len(msers)
self.assertEqual(nmsers, len(boxes))
self.assertLessEqual(minRegs, nmsers)
self.assertGreaterEqual(maxRegs, nmsers)

View File

@ -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)

View File

@ -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)
bin, 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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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()

View File

@ -112,7 +112,7 @@ if __name__ == '__main__':
import sys, getopt
opts, args = getopt.getopt(sys.argv[1:], '', ['feature='])
opts = dict(opts)
feature_name = opts.get('--feature', 'sift-flann')
feature_name = opts.get('--feature', 'brisk-flann')
try:
fn1, fn2 = args
except:

View File

@ -173,6 +173,7 @@ class RectSelector:
x, y = np.int16([x, y]) # BUG
if event == cv2.EVENT_LBUTTONDOWN:
self.drag_start = (x, y)
return
if self.drag_start:
if flags & cv2.EVENT_FLAG_LBUTTON:
xo, yo = self.drag_start

View File

@ -87,8 +87,11 @@ class App:
for fn in glob('*.py'):
name = splitfn(fn)[1]
if fn[0] != '_' and name not in exclude_list:
demos_lb.insert(tk.END, name)
self.samples[name] = fn
for name in sorted(self.samples):
demos_lb.insert(tk.END, name)
demos_lb.bind('<<ListboxSelect>>', self.on_demo_select)
self.cmd_entry = cmd_entry = tk.Entry(right)

View File

@ -27,9 +27,12 @@ def main():
if not os.path.exists(classifier_fn):
print('"%s" not found, run digits.py first' % classifier_fn)
return
model = SVM()
model.load(classifier_fn)
if True:
model = cv2.ml.SVM_load(classifier_fn)
else:
model = cv2.ml.SVM_create()
model.load_(classifier_fn) #Known bug: https://github.com/Itseez/opencv/issues/4969
while True:
ret, frame = cap.read()

View File

@ -68,7 +68,7 @@ def filter_matches(kp1, kp2, matches, ratio = 0.75):
p1 = np.float32([kp.pt for kp in mkp1])
p2 = np.float32([kp.pt for kp in mkp2])
kp_pairs = zip(mkp1, mkp2)
return p1, p2, kp_pairs
return p1, p2, list(kp_pairs)
def explore_match(win, img1, img2, kp_pairs, status = None, H = None):
h1, w1 = img1.shape[:2]
@ -119,7 +119,7 @@ def explore_match(win, img1, img2, kp_pairs, status = None, H = None):
if flags & cv2.EVENT_FLAG_LBUTTON:
cur_vis = vis0.copy()
r = 8
m = (anorm(p1 - (x, y)) < r) | (anorm(p2 - (x, y)) < r)
m = (anorm(np.array(p1) - (x, y)) < r) | (anorm(np.array(p2) - (x, y)) < r)
idxs = np.where(m)[0]
kp1s, kp2s = [], []
for i in idxs:
@ -143,7 +143,7 @@ if __name__ == '__main__':
import sys, getopt
opts, args = getopt.getopt(sys.argv[1:], '', ['feature='])
opts = dict(opts)
feature_name = opts.get('--feature', 'sift')
feature_name = opts.get('--feature', 'brisk')
try:
fn1, fn2 = args
except:

View File

@ -65,13 +65,12 @@ class RTrees(LetterStatModel):
def train(self, samples, responses):
sample_n, var_n = samples.shape
var_types = np.array([cv2.ml.VAR_NUMERICAL] * var_n + [cv2.ml.VAR_CATEGORICAL], np.uint8)
#CvRTParams(10,10,0,false,15,0,true,4,100,0.01f,CV_TERMCRIT_ITER));
params = dict(max_depth=10 )
self.model.train(samples, cv2.ml.ROW_SAMPLE, responses, varType = var_types, params = params)
self.model.setMaxDepth(20)
self.model.train(samples, cv2.ml.ROW_SAMPLE, responses.astype(int))
def predict(self, samples):
return [self.model.predict(s) for s in samples]
ret, resp = self.model.predict(samples)
return resp.ravel()
class KNearest(LetterStatModel):
@ -79,10 +78,10 @@ class KNearest(LetterStatModel):
self.model = cv2.ml.KNearest_create()
def train(self, samples, responses):
self.model.train(samples, responses)
self.model.train(samples, cv2.ml.ROW_SAMPLE, responses)
def predict(self, samples):
retval, results, neigh_resp, dists = self.model.find_nearest(samples, k = 10)
retval, results, neigh_resp, dists = self.model.findNearest(samples, k = 10)
return results.ravel()
@ -95,15 +94,16 @@ class Boost(LetterStatModel):
new_samples = self.unroll_samples(samples)
new_responses = self.unroll_responses(responses)
var_types = np.array([cv2.ml.VAR_NUMERICAL] * var_n + [cv2.ml.VAR_CATEGORICAL, cv2.ml.VAR_CATEGORICAL], np.uint8)
#CvBoostParams(CvBoost::REAL, 100, 0.95, 5, false, 0 )
params = dict(max_depth=5) #, use_surrogates=False)
self.model.train(new_samples, cv2.ml.ROW_SAMPLE, new_responses, varType = var_types, params=params)
self.model.setWeakCount(15)
self.model.setMaxDepth(10)
self.model.train(cv2.ml.TrainData_create(new_samples, cv2.ml.ROW_SAMPLE, new_responses.astype(int), varType = var_types))
def predict(self, samples):
new_samples = self.unroll_samples(samples)
pred = np.array( [self.model.predict(s, returnSum = True) for s in new_samples] )
pred = pred.reshape(-1, self.class_n).argmax(1)
return pred
ret, resp = self.model.predict(new_samples)
return resp.ravel().reshape(-1, self.class_n).argmax(1)
class SVM(LetterStatModel):
@ -111,13 +111,15 @@ class SVM(LetterStatModel):
self.model = cv2.ml.SVM_create()
def train(self, samples, responses):
params = dict( kernel_type = cv2.ml.SVM_LINEAR,
svm_type = cv2.ml.SVM_C_SVC,
C = 1 )
self.model.train(samples, responses, params = params)
self.model.setType(cv2.ml.SVM_C_SVC)
self.model.setC(1)
self.model.setKernel(cv2.ml.SVM_RBF)
self.model.setGamma(.1)
self.model.train(samples, cv2.ml.ROW_SAMPLE, responses.astype(int))
def predict(self, samples):
return self.model.predict_all(samples).ravel()
ret, resp = self.model.predict(samples)
return resp.ravel()
class MLP(LetterStatModel):
@ -127,22 +129,23 @@ class MLP(LetterStatModel):
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)
# CvANN_MLP_TrainParams::BACKPROP,0.001
params = dict( term_crit = (cv2.TERM_CRITERIA_COUNT, 300, 0.01),
train_method = cv2.ml.ANN_MLP_TRAIN_PARAMS_BACKPROP,
bp_dw_scale = 0.001,
bp_moment_scale = 0.0 )
self.model.train(samples, np.float32(new_responses), None, params = params)
self.model.setLayerSizes(layer_sizes)
self.model.setTrainMethod(cv2.ml.ANN_MLP_BACKPROP)
self.model.setBackpropMomentumScale(0.0)
self.model.setBackpropWeightScale(0.001)
self.model.setTermCriteria((cv2.TERM_CRITERIA_COUNT, 20, 0.01))
self.model.setActivationFunction(cv2.ml.ANN_MLP_SIGMOID_SYM, 2, 1)
self.model.train(samples, cv2.ml.ROW_SAMPLE, np.float32(new_responses))
def predict(self, samples):
ret, resp = self.model.predict(samples)
return resp.argmax(-1)
if __name__ == '__main__':
import getopt
import sys
@ -155,7 +158,7 @@ if __name__ == '__main__':
args, dummy = getopt.getopt(sys.argv[1:], '', ['model=', 'data=', 'load=', 'save='])
args = dict(args)
args.setdefault('--model', 'rtrees')
args.setdefault('--model', 'svm')
args.setdefault('--data', '../data/letter-recognition.data')
print('loading data %s ...' % args['--data'])
@ -173,8 +176,8 @@ if __name__ == '__main__':
model.train(samples[:train_n], responses[:train_n])
print('testing...')
train_rate = np.mean(model.predict(samples[:train_n]) == responses[:train_n])
test_rate = np.mean(model.predict(samples[train_n:]) == responses[train_n:])
train_rate = np.mean(model.predict(samples[:train_n]) == responses[:train_n].astype(int))
test_rate = np.mean(model.predict(samples[train_n:]) == responses[train_n:].astype(int))
print('train rate: %f test rate: %f' % (train_rate*100, test_rate*100))