Merge remote-tracking branch 'upstream/3.4' into merge-3.4
This commit is contained in:
@@ -18,6 +18,8 @@ endif()
|
||||
|
||||
add_subdirectory(bindings)
|
||||
|
||||
add_subdirectory(test)
|
||||
|
||||
if(NOT OPENCV_SKIP_PYTHON_LOADER)
|
||||
include("./python_loader.cmake")
|
||||
message(STATUS "OpenCV Python: during development append to PYTHONPATH: ${CMAKE_BINARY_DIR}/python_loader")
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
set(MODULE_NAME "python_tests")
|
||||
set(OPENCV_MODULE_IS_PART_OF_WORLD FALSE)
|
||||
ocv_add_module(${MODULE_NAME} INTERNAL)
|
||||
|
||||
set(OPENCV_PYTHON_TESTS_CONFIG_FILE_DIR "${OpenCV_BINARY_DIR}" CACHE INTERNAL "")
|
||||
set(OPENCV_PYTHON_TESTS_CONFIG_FILE "${OPENCV_PYTHON_TESTS_CONFIG_FILE_DIR}/opencv_python_tests.cfg" CACHE INTERNAL "")
|
||||
|
||||
# get list of modules to wrap
|
||||
set(OPENCV_PYTHON_MODULES)
|
||||
foreach(m ${OPENCV_MODULES_BUILD})
|
||||
if(";${OPENCV_MODULE_${m}_WRAPPERS};" MATCHES ";python.*;" AND HAVE_${m})
|
||||
list(APPEND OPENCV_PYTHON_MODULES ${m})
|
||||
#message(STATUS "\t${m}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
file(RELATIVE_PATH __loc_relative "${OPENCV_PYTHON_TESTS_CONFIG_FILE_DIR}" "${CMAKE_CURRENT_LIST_DIR}")
|
||||
set(opencv_tests_locations "${__loc_relative}")
|
||||
foreach(m ${OPENCV_PYTHON_MODULES})
|
||||
set(__loc "${OPENCV_MODULE_${m}_LOCATION}/misc/python/test")
|
||||
if(EXISTS "${__loc}")
|
||||
file(RELATIVE_PATH __loc_relative "${OPENCV_PYTHON_TESTS_CONFIG_FILE_DIR}" "${__loc}")
|
||||
list(APPEND opencv_tests_locations "${__loc_relative}")
|
||||
endif()
|
||||
endforeach(m)
|
||||
|
||||
string(REPLACE ";" "\n" opencv_tests_locations_ "${opencv_tests_locations}")
|
||||
ocv_update_file("${OPENCV_PYTHON_TESTS_CONFIG_FILE}" "${opencv_tests_locations_}")
|
||||
|
||||
#
|
||||
# TODO: Install rules (with test data?)
|
||||
#
|
||||
@@ -1,4 +1,9 @@
|
||||
#!/usr/bin/env python
|
||||
'''
|
||||
Location of tests:
|
||||
- <opencv_src>/modules/python/test
|
||||
- <opencv_src>/modules/<module>/misc/python/test/
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
@@ -20,7 +25,35 @@ from tests_common import NewOpenCVTests
|
||||
basedir = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
def load_tests(loader, tests, pattern):
|
||||
tests.addTests(loader.discover(basedir, pattern=os.environ.get('OPENCV_PYTEST_FILTER', 'test_') + '*.py'))
|
||||
cwd = os.getcwd()
|
||||
config_file = 'opencv_python_tests.cfg'
|
||||
locations = [cwd, basedir]
|
||||
if os.path.exists(config_file):
|
||||
with open(config_file, 'r') as f:
|
||||
locations += [str(s).strip() for s in f.readlines()]
|
||||
else:
|
||||
print('WARNING: OpenCV tests config file ({}) is missing, running subset of tests'.format(config_file))
|
||||
|
||||
tests_pattern = os.environ.get('OPENCV_PYTEST_FILTER', 'test_') + '*.py'
|
||||
if tests_pattern != 'test_*py':
|
||||
print('Tests filter: {}'.format(tests_pattern))
|
||||
|
||||
processed = set()
|
||||
for l in locations:
|
||||
if not os.path.isabs(l):
|
||||
l = os.path.normpath(os.path.join(cwd, l))
|
||||
if l in processed:
|
||||
continue
|
||||
processed.add(l)
|
||||
print('Discovering python tests from: {}'.format(l))
|
||||
sys_path_modify = l not in sys.path
|
||||
if sys_path_modify:
|
||||
sys.path.append(l) # Hack python loader
|
||||
discovered_tests = loader.discover(l, pattern=tests_pattern, top_level_dir=l)
|
||||
print(' found {} tests'.format(discovered_tests.countTestCases()))
|
||||
tests.addTests(loader.discover(l, pattern=tests_pattern))
|
||||
if sys_path_modify:
|
||||
sys.path.remove(l)
|
||||
return tests
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
#!/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 as cv
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
class calibration_test(NewOpenCVTests):
|
||||
|
||||
def test_calibration(self):
|
||||
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
|
||||
for fn in img_names:
|
||||
img = self.get_sample(fn, 0)
|
||||
if img is None:
|
||||
continue
|
||||
|
||||
h, w = img.shape[:2]
|
||||
found, corners = cv.findChessboardCorners(img, pattern_size)
|
||||
if found:
|
||||
term = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_COUNT, 30, 0.1)
|
||||
cv.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 = cv.calibrateCamera(obj_points, img_points, (w, h), None, None, flags = 0)
|
||||
|
||||
eps = 0.01
|
||||
normCamEps = 10.0
|
||||
normDistEps = 0.05
|
||||
|
||||
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(cv.norm(camera_matrix - cameraMatrixTest, cv.NORM_L1), normCamEps)
|
||||
self.assertLess(cv.norm(dist_coefs - distCoeffsTest, cv.NORM_L1), normDistEps)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
@@ -1,201 +0,0 @@
|
||||
#!/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 as cv
|
||||
|
||||
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 = cv.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 = cv.warpAffine(img, M, (SZ, SZ), flags=cv.WARP_INVERSE_MAP | cv.INTER_LINEAR)
|
||||
return img
|
||||
|
||||
class StatModel(object):
|
||||
def load(self, fn):
|
||||
self.model.load(fn) # Known bug: https://github.com/opencv/opencv/issues/4969
|
||||
def save(self, fn):
|
||||
self.model.save(fn)
|
||||
|
||||
class KNearest(StatModel):
|
||||
def __init__(self, k = 3):
|
||||
self.k = k
|
||||
self.model = cv.ml.KNearest_create()
|
||||
|
||||
def train(self, samples, responses):
|
||||
self.model.train(samples, cv.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 = cv.ml.SVM_create()
|
||||
self.model.setGamma(gamma)
|
||||
self.model.setC(C)
|
||||
self.model.setKernel(cv.ml.SVM_RBF)
|
||||
self.model.setType(cv.ml.SVM_C_SVC)
|
||||
|
||||
def train(self, samples, responses):
|
||||
self.model.train(samples, cv.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 = cv.Sobel(img, cv.CV_32F, 1, 0)
|
||||
gy = cv.Sobel(img, cv.CV_32F, 0, 1)
|
||||
mag, ang = cv.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(cv.norm(confusionMatrixes[0] - confusionKNN, cv.NORM_L1), normEps)
|
||||
self.assertLess(cv.norm(confusionMatrixes[1] - confusionSVM, cv.NORM_L1), normEps)
|
||||
|
||||
self.assertLess(errors[0] - 0.034, eps)
|
||||
self.assertLess(errors[1] - 0.018, eps)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
@@ -1,182 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
import os
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
|
||||
from tests_common import NewOpenCVTests, unittest
|
||||
|
||||
def normAssert(test, a, b, lInf=1e-5):
|
||||
test.assertLess(np.max(np.abs(a - b)), lInf)
|
||||
|
||||
def inter_area(box1, box2):
|
||||
x_min, x_max = max(box1[0], box2[0]), min(box1[2], box2[2])
|
||||
y_min, y_max = max(box1[1], box2[1]), min(box1[3], box2[3])
|
||||
return (x_max - x_min) * (y_max - y_min)
|
||||
|
||||
def area(box):
|
||||
return (box[2] - box[0]) * (box[3] - box[1])
|
||||
|
||||
def box2str(box):
|
||||
left, top = box[0], box[1]
|
||||
width, height = box[2] - left, box[3] - top
|
||||
return '[%f x %f from (%f, %f)]' % (width, height, left, top)
|
||||
|
||||
def normAssertDetections(test, ref, out, confThreshold=0.0, scores_diff=1e-5, boxes_iou_diff=1e-4):
|
||||
ref = np.array(ref, np.float32)
|
||||
refClassIds, testClassIds = ref[:, 1], out[:, 1]
|
||||
refScores, testScores = ref[:, 2], out[:, 2]
|
||||
refBoxes, testBoxes = ref[:, 3:], out[:, 3:]
|
||||
|
||||
matchedRefBoxes = [False] * len(refBoxes)
|
||||
errMsg = ''
|
||||
for i in range(len(refBoxes)):
|
||||
testScore = testScores[i]
|
||||
if testScore < confThreshold:
|
||||
continue
|
||||
|
||||
testClassId, testBox = testClassIds[i], testBoxes[i]
|
||||
matched = False
|
||||
for j in range(len(refBoxes)):
|
||||
if (not matchedRefBoxes[j]) and testClassId == refClassIds[j] and \
|
||||
abs(testScore - refScores[j]) < scores_diff:
|
||||
interArea = inter_area(testBox, refBoxes[j])
|
||||
iou = interArea / (area(testBox) + area(refBoxes[j]) - interArea)
|
||||
if abs(iou - 1.0) < boxes_iou_diff:
|
||||
matched = True
|
||||
matchedRefBoxes[j] = True
|
||||
if not matched:
|
||||
errMsg += '\nUnmatched prediction: class %d score %f box %s' % (testClassId, testScore, box2str(testBox))
|
||||
|
||||
for i in range(len(refBoxes)):
|
||||
if (not matchedRefBoxes[i]) and refScores[i] > confThreshold:
|
||||
errMsg += '\nUnmatched reference: class %d score %f box %s' % (refClassIds[i], refScores[i], box2str(refBoxes[i]))
|
||||
if errMsg:
|
||||
test.fail(errMsg)
|
||||
|
||||
|
||||
# Returns a simple one-layer network created from Caffe's format
|
||||
def getSimpleNet():
|
||||
prototxt = """
|
||||
name: "simpleNet"
|
||||
input: "data"
|
||||
layer {
|
||||
type: "Identity"
|
||||
name: "testLayer"
|
||||
top: "testLayer"
|
||||
bottom: "data"
|
||||
}
|
||||
"""
|
||||
return cv.dnn.readNetFromCaffe(bytearray(prototxt, 'utf8'))
|
||||
|
||||
|
||||
def testBackendAndTarget(backend, target):
|
||||
net = getSimpleNet()
|
||||
net.setPreferableBackend(backend)
|
||||
net.setPreferableTarget(target)
|
||||
inp = np.random.standard_normal([1, 2, 3, 4]).astype(np.float32)
|
||||
try:
|
||||
net.setInput(inp)
|
||||
net.forward()
|
||||
except BaseException as e:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
haveInfEngine = testBackendAndTarget(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_TARGET_CPU)
|
||||
dnnBackendsAndTargets = [
|
||||
[cv.dnn.DNN_BACKEND_OPENCV, cv.dnn.DNN_TARGET_CPU],
|
||||
]
|
||||
|
||||
if haveInfEngine:
|
||||
dnnBackendsAndTargets.append([cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_TARGET_CPU])
|
||||
if testBackendAndTarget(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_TARGET_MYRIAD):
|
||||
dnnBackendsAndTargets.append([cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_TARGET_MYRIAD])
|
||||
|
||||
if cv.ocl.haveOpenCL() and cv.ocl.useOpenCL():
|
||||
dnnBackendsAndTargets.append([cv.dnn.DNN_BACKEND_OPENCV, cv.dnn.DNN_TARGET_OPENCL])
|
||||
dnnBackendsAndTargets.append([cv.dnn.DNN_BACKEND_OPENCV, cv.dnn.DNN_TARGET_OPENCL_FP16])
|
||||
if haveInfEngine and cv.ocl_Device.getDefault().isIntel():
|
||||
dnnBackendsAndTargets.append([cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_TARGET_OPENCL])
|
||||
dnnBackendsAndTargets.append([cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_TARGET_OPENCL_FP16])
|
||||
|
||||
|
||||
def printParams(backend, target):
|
||||
backendNames = {
|
||||
cv.dnn.DNN_BACKEND_OPENCV: 'OCV',
|
||||
cv.dnn.DNN_BACKEND_INFERENCE_ENGINE: 'DLIE'
|
||||
}
|
||||
targetNames = {
|
||||
cv.dnn.DNN_TARGET_CPU: 'CPU',
|
||||
cv.dnn.DNN_TARGET_OPENCL: 'OCL',
|
||||
cv.dnn.DNN_TARGET_OPENCL_FP16: 'OCL_FP16',
|
||||
cv.dnn.DNN_TARGET_MYRIAD: 'MYRIAD'
|
||||
}
|
||||
print('%s/%s' % (backendNames[backend], targetNames[target]))
|
||||
|
||||
|
||||
class dnn_test(NewOpenCVTests):
|
||||
|
||||
def find_dnn_file(self, filename, required=True):
|
||||
return self.find_file(filename, [os.environ.get('OPENCV_DNN_TEST_DATA_PATH', os.getcwd())], required=required)
|
||||
|
||||
def test_blobFromImage(self):
|
||||
np.random.seed(324)
|
||||
|
||||
width = 6
|
||||
height = 7
|
||||
scale = 1.0/127.5
|
||||
mean = (10, 20, 30)
|
||||
|
||||
# Test arguments names.
|
||||
img = np.random.randint(0, 255, [4, 5, 3]).astype(np.uint8)
|
||||
blob = cv.dnn.blobFromImage(img, scale, (width, height), mean, True, False)
|
||||
blob_args = cv.dnn.blobFromImage(img, scalefactor=scale, size=(width, height),
|
||||
mean=mean, swapRB=True, crop=False)
|
||||
normAssert(self, blob, blob_args)
|
||||
|
||||
# Test values.
|
||||
target = cv.resize(img, (width, height), interpolation=cv.INTER_LINEAR)
|
||||
target = target.astype(np.float32)
|
||||
target = target[:,:,[2, 1, 0]] # BGR2RGB
|
||||
target[:,:,0] -= mean[0]
|
||||
target[:,:,1] -= mean[1]
|
||||
target[:,:,2] -= mean[2]
|
||||
target *= scale
|
||||
target = target.transpose(2, 0, 1).reshape(1, 3, height, width) # to NCHW
|
||||
normAssert(self, blob, target)
|
||||
|
||||
|
||||
def test_face_detection(self):
|
||||
testdata_required = bool(os.environ.get('OPENCV_DNN_TEST_REQUIRE_TESTDATA', False))
|
||||
proto = self.find_dnn_file('dnn/opencv_face_detector.prototxt2', required=testdata_required)
|
||||
model = self.find_dnn_file('dnn/opencv_face_detector.caffemodel', required=testdata_required)
|
||||
if proto is None or model is None:
|
||||
raise unittest.SkipTest("Missing DNN test files (dnn/opencv_face_detector.{prototxt/caffemodel}). Verify OPENCV_DNN_TEST_DATA_PATH configuration parameter.")
|
||||
|
||||
img = self.get_sample('gpu/lbpcascade/er.png')
|
||||
blob = cv.dnn.blobFromImage(img, mean=(104, 177, 123), swapRB=False, crop=False)
|
||||
|
||||
ref = [[0, 1, 0.99520785, 0.80997437, 0.16379407, 0.87996572, 0.26685631],
|
||||
[0, 1, 0.9934696, 0.2831718, 0.50738752, 0.345781, 0.5985168],
|
||||
[0, 1, 0.99096733, 0.13629119, 0.24892329, 0.19756334, 0.3310290],
|
||||
[0, 1, 0.98977017, 0.23901358, 0.09084064, 0.29902688, 0.1769477],
|
||||
[0, 1, 0.97203469, 0.67965847, 0.06876482, 0.73999709, 0.1513494],
|
||||
[0, 1, 0.95097077, 0.51901293, 0.45863652, 0.5777427, 0.5347801]]
|
||||
|
||||
print('\n')
|
||||
for backend, target in dnnBackendsAndTargets:
|
||||
printParams(backend, target)
|
||||
|
||||
net = cv.dnn.readNet(proto, model)
|
||||
net.setPreferableBackend(backend)
|
||||
net.setPreferableTarget(target)
|
||||
net.setInput(blob)
|
||||
out = net.forward().reshape(-1, 7)
|
||||
|
||||
scoresDiff = 4e-3 if target in [cv.dnn.DNN_TARGET_OPENCL_FP16, cv.dnn.DNN_TARGET_MYRIAD] else 1e-5
|
||||
iouDiff = 2e-2 if target in [cv.dnn.DNN_TARGET_OPENCL_FP16, cv.dnn.DNN_TARGET_MYRIAD] else 1e-4
|
||||
|
||||
normAssertDetections(self, ref, out, 0.5, scoresDiff, iouDiff)
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
@@ -1,92 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
face detection using haar cascades
|
||||
'''
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
|
||||
def detect(img, cascade):
|
||||
rects = cascade.detectMultiScale(img, scaleFactor=1.275, minNeighbors=4, minSize=(30, 30),
|
||||
flags=cv.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):
|
||||
cascade_fn = self.repoPath + '/data/haarcascades/haarcascade_frontalface_alt.xml'
|
||||
nested_fn = self.repoPath + '/data/haarcascades/haarcascade_eye.xml'
|
||||
|
||||
cascade = cv.CascadeClassifier(cascade_fn)
|
||||
nested = cv.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 = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
|
||||
gray = cv.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)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
@@ -1,164 +0,0 @@
|
||||
#!/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 as cv
|
||||
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 = cv.intersectConvexConvex(s1, np.array(s2))
|
||||
return 2 * area / (cv.contourArea(s1) + cv.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 boundary quad in input frame
|
||||
'''
|
||||
TrackedTarget = namedtuple('TrackedTarget', 'target, p0, p1, H, quad')
|
||||
|
||||
class PlaneTracker:
|
||||
def __init__(self):
|
||||
self.detector = cv.AKAZE_create(threshold = 0.003)
|
||||
self.matcher = cv.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 = cv.findHomography(p0, p1, cv.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 = cv.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
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
@@ -1,40 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Python 2/3 compatibility
|
||||
from __future__ import print_function
|
||||
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
class TestGoodFeaturesToTrack_test(NewOpenCVTests):
|
||||
def test_goodFeaturesToTrack(self):
|
||||
arr = self.get_sample('samples/data/lena.jpg', 0)
|
||||
original = arr.copy(True)
|
||||
threshes = [ x / 100. for x in range(1,10) ]
|
||||
numPoints = 20000
|
||||
|
||||
results = dict([(t, cv.goodFeaturesToTrack(arr, numPoints, t, 2, useHarrisDetector=True)) for t in threshes])
|
||||
# Check that GoodFeaturesToTrack has not modified input image
|
||||
self.assertTrue(arr.tostring() == original.tostring())
|
||||
# Check for repeatability
|
||||
for i in range(1):
|
||||
results2 = dict([(t, cv.goodFeaturesToTrack(arr, numPoints, t, 2, useHarrisDetector=True)) for t in threshes])
|
||||
for t in threshes:
|
||||
self.assertTrue(len(results2[t]) == len(results[t]))
|
||||
for i in range(len(results[t])):
|
||||
self.assertTrue(cv.norm(results[t][i][0] - results2[t][i][0]) == 0)
|
||||
|
||||
for t0,t1 in zip(threshes, threshes[1:]):
|
||||
r0 = results[t0]
|
||||
r1 = results[t1]
|
||||
# Increasing thresh should make result list shorter
|
||||
self.assertTrue(len(r0) > len(r1))
|
||||
# Increasing thresh should monly truncate result list
|
||||
for i in range(len(r1)):
|
||||
self.assertTrue(cv.norm(r1[i][0] - r0[i][0])==0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
@@ -1,171 +0,0 @@
|
||||
#!/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 as cv
|
||||
|
||||
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 = cv.ml.RTrees_create()
|
||||
|
||||
def train(self, samples, responses):
|
||||
#sample_n, var_n = samples.shape
|
||||
self.model.setMaxDepth(20)
|
||||
self.model.train(samples, cv.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 = cv.ml.KNearest_create()
|
||||
|
||||
def train(self, samples, responses):
|
||||
self.model.train(samples, cv.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 = cv.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([cv.ml.VAR_NUMERICAL] * var_n + [cv.ml.VAR_CATEGORICAL, cv.ml.VAR_CATEGORICAL], np.uint8)
|
||||
|
||||
self.model.setWeakCount(15)
|
||||
self.model.setMaxDepth(10)
|
||||
self.model.train(cv.ml.TrainData_create(new_samples, cv.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 = cv.ml.SVM_create()
|
||||
|
||||
def train(self, samples, responses):
|
||||
self.model.setType(cv.ml.SVM_C_SVC)
|
||||
self.model.setC(1)
|
||||
self.model.setKernel(cv.ml.SVM_RBF)
|
||||
self.model.setGamma(.1)
|
||||
self.model.train(samples, cv.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 = cv.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(cv.ml.ANN_MLP_BACKPROP)
|
||||
self.model.setBackpropMomentumScale(0)
|
||||
self.model.setBackpropWeightScale(0.001)
|
||||
self.model.setTermCriteria((cv.TERM_CRITERIA_COUNT, 20, 0.01))
|
||||
self.model.setActivationFunction(cv.ml.ANN_MLP_SIGMOID_SYM, 2, 1)
|
||||
|
||||
self.model.train(samples, cv.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)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
@@ -1,100 +0,0 @@
|
||||
#!/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 as cv
|
||||
|
||||
#local modules
|
||||
from tst_scene_render import TestSceneRender
|
||||
from tests_common import NewOpenCVTests, isPointInRect
|
||||
|
||||
lk_params = dict( winSize = (19, 19),
|
||||
maxLevel = 2,
|
||||
criteria = (cv.TERM_CRITERIA_EPS | cv.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 = cv.calcOpticalFlowPyrLK(img0, img1, p0, None, **lk_params)
|
||||
p0r, _st, _err = cv.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 = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
|
||||
self.frame0 = frame.copy()
|
||||
self.p0 = cv.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 = cv.cvtColor(frame, cv.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 = cv.findHomography(self.p0, self.p1, cv.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:
|
||||
self.p0 = cv.goodFeaturesToTrack(frame_gray, **feature_params)
|
||||
|
||||
self.assertEqual(isForegroundHomographyFound, True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
@@ -1,115 +0,0 @@
|
||||
#!/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 as cv
|
||||
|
||||
#local modules
|
||||
from tst_scene_render import TestSceneRender
|
||||
from tests_common import NewOpenCVTests, intersectionRate, isPointInRect
|
||||
|
||||
lk_params = dict( winSize = (15, 15),
|
||||
maxLevel = 2,
|
||||
criteria = (cv.TERM_CRITERIA_EPS | cv.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(cv.norm(point, cv.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 = cv.cvtColor(frame, cv.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 = cv.calcOpticalFlowPyrLK(img0, img1, p0, None, **lk_params)
|
||||
p0r, _st, _err = cv.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]:
|
||||
cv.circle(mask, (x, y), 5, 0, -1)
|
||||
p = cv.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
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
@@ -1,65 +0,0 @@
|
||||
#!/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 as cv
|
||||
|
||||
|
||||
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 = cv.HOGDescriptor()
|
||||
hog.setSVMDetector( cv.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)
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
@@ -1,86 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
import cv2 as cv
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
class stitching_test(NewOpenCVTests):
|
||||
|
||||
def test_simple(self):
|
||||
|
||||
img1 = self.get_sample('stitching/a1.png')
|
||||
img2 = self.get_sample('stitching/a2.png')
|
||||
|
||||
stitcher = cv.Stitcher.create(cv.Stitcher_PANORAMA)
|
||||
(_result, pano) = stitcher.stitch((img1, img2))
|
||||
|
||||
#cv.imshow("pano", pano)
|
||||
#cv.waitKey()
|
||||
|
||||
self.assertAlmostEqual(pano.shape[0], 685, delta=100, msg="rows: %r" % list(pano.shape))
|
||||
self.assertAlmostEqual(pano.shape[1], 1025, delta=100, msg="cols: %r" % list(pano.shape))
|
||||
|
||||
class stitching_detail_test(NewOpenCVTests):
|
||||
|
||||
def test_simple(self):
|
||||
img = self.get_sample('stitching/a1.png')
|
||||
finder= cv.ORB.create()
|
||||
imgFea = cv.detail.computeImageFeatures2(finder,img)
|
||||
self.assertIsNotNone(imgFea)
|
||||
|
||||
matcher = cv.detail_BestOf2NearestMatcher(False, 0.3)
|
||||
self.assertIsNotNone(matcher)
|
||||
matcher = cv.detail_AffineBestOf2NearestMatcher(False, False, 0.3)
|
||||
self.assertIsNotNone(matcher)
|
||||
matcher = cv.detail_BestOf2NearestRangeMatcher(2, False, 0.3)
|
||||
self.assertIsNotNone(matcher)
|
||||
estimator = cv.detail_AffineBasedEstimator()
|
||||
self.assertIsNotNone(estimator)
|
||||
estimator = cv.detail_HomographyBasedEstimator()
|
||||
self.assertIsNotNone(estimator)
|
||||
|
||||
adjuster = cv.detail_BundleAdjusterReproj()
|
||||
self.assertIsNotNone(adjuster)
|
||||
adjuster = cv.detail_BundleAdjusterRay()
|
||||
self.assertIsNotNone(adjuster)
|
||||
adjuster = cv.detail_BundleAdjusterAffinePartial()
|
||||
self.assertIsNotNone(adjuster)
|
||||
adjuster = cv.detail_NoBundleAdjuster()
|
||||
self.assertIsNotNone(adjuster)
|
||||
|
||||
compensator=cv.detail.ExposureCompensator_createDefault(cv.detail.ExposureCompensator_NO)
|
||||
self.assertIsNotNone(compensator)
|
||||
compensator=cv.detail.ExposureCompensator_createDefault(cv.detail.ExposureCompensator_GAIN)
|
||||
self.assertIsNotNone(compensator)
|
||||
compensator=cv.detail.ExposureCompensator_createDefault(cv.detail.ExposureCompensator_GAIN_BLOCKS)
|
||||
self.assertIsNotNone(compensator)
|
||||
|
||||
seam_finder = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_NO)
|
||||
self.assertIsNotNone(seam_finder)
|
||||
seam_finder = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_NO)
|
||||
self.assertIsNotNone(seam_finder)
|
||||
seam_finder = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_VORONOI_SEAM)
|
||||
self.assertIsNotNone(seam_finder)
|
||||
|
||||
seam_finder = cv.detail_GraphCutSeamFinder("COST_COLOR")
|
||||
self.assertIsNotNone(seam_finder)
|
||||
seam_finder = cv.detail_GraphCutSeamFinder("COST_COLOR_GRAD")
|
||||
self.assertIsNotNone(seam_finder)
|
||||
seam_finder = cv.detail_DpSeamFinder("COLOR")
|
||||
self.assertIsNotNone(seam_finder)
|
||||
seam_finder = cv.detail_DpSeamFinder("COLOR_GRAD")
|
||||
self.assertIsNotNone(seam_finder)
|
||||
|
||||
blender = cv.detail.Blender_createDefault(cv.detail.Blender_NO)
|
||||
self.assertIsNotNone(blender)
|
||||
blender = cv.detail.Blender_createDefault(cv.detail.Blender_FEATHER)
|
||||
self.assertIsNotNone(blender)
|
||||
blender = cv.detail.Blender_createDefault(cv.detail.Blender_MULTI_BAND)
|
||||
self.assertIsNotNone(blender)
|
||||
|
||||
timelapser = cv.detail.Timelapser_createDefault(cv.detail.Timelapser_AS_IS);
|
||||
self.assertIsNotNone(timelapser)
|
||||
timelapser = cv.detail.Timelapser_createDefault(cv.detail.Timelapser_CROP);
|
||||
self.assertIsNotNone(timelapser)
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import print_function
|
||||
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
class Bindings(NewOpenCVTests):
|
||||
|
||||
def check_name(self, name):
|
||||
#print(name)
|
||||
self.assertFalse(name == None)
|
||||
self.assertFalse(name == "")
|
||||
|
||||
def test_registry(self):
|
||||
self.check_name(cv.videoio_registry.getBackendName(cv.CAP_ANY));
|
||||
self.check_name(cv.videoio_registry.getBackendName(cv.CAP_FFMPEG))
|
||||
self.check_name(cv.videoio_registry.getBackendName(cv.CAP_OPENCV_MJPEG))
|
||||
backends = cv.videoio_registry.getBackends()
|
||||
for backend in backends:
|
||||
self.check_name(cv.videoio_registry.getBackendName(backend))
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
Reference in New Issue
Block a user