Add segmentation and object tracking python tests
This commit is contained in:
parent
0c6e09f060
commit
e4fed417d2
@ -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;
|
||||
|
@ -39,7 +39,7 @@ class camshift_test(NewOpenCVTests):
|
||||
|
||||
def prepareRender(self):
|
||||
|
||||
self.render = TestSceneRender(self.get_sample('samples/data/pca_test1.jpg'), True)
|
||||
self.render = TestSceneRender(self.get_sample('samples/data/pca_test1.jpg'), deformation = True)
|
||||
|
||||
def runTracker(self):
|
||||
|
||||
@ -53,7 +53,6 @@ class camshift_test(NewOpenCVTests):
|
||||
while True:
|
||||
framesCounter += 1
|
||||
self.frame = self.render.getNextFrame()
|
||||
vis = self.frame.copy()
|
||||
hsv = cv2.cvtColor(self.frame, cv2.COLOR_BGR2HSV)
|
||||
mask = cv2.inRange(hsv, np.array((0., 60., 32.)), np.array((180., 255., 255.)))
|
||||
|
||||
@ -67,11 +66,6 @@ class camshift_test(NewOpenCVTests):
|
||||
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)
|
||||
|
||||
vis_roi = vis[y0:y1, x0:x1]
|
||||
cv2.bitwise_not(vis_roi, vis_roi)
|
||||
vis[mask == 0] = 0
|
||||
|
||||
self.selection = False
|
||||
|
||||
if self.track_window and self.track_window[2] > 0 and self.track_window[3] > 0:
|
||||
@ -81,8 +75,6 @@ class camshift_test(NewOpenCVTests):
|
||||
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)
|
||||
|
||||
if self.show_backproj:
|
||||
vis[:] = prob[...,np.newaxis]
|
||||
trackingRect = np.array(self.track_window)
|
||||
trackingRect[2] += trackingRect[0]
|
||||
trackingRect[3] += trackingRect[1]
|
||||
|
160
modules/python/test/test_feature_homography.py
Normal file
160
modules/python/test/test_feature_homography.py
Normal 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.ORB_create( nfeatures = 1000 )
|
||||
self.matcher = cv2.FlannBasedMatcher(flann_params, {}) # bug : need to pass empty dict (#1329)
|
||||
self.targets = []
|
||||
self.frame_points = []
|
||||
|
||||
def add_target(self, image, rect, data=None):
|
||||
'''Add a new tracking target.'''
|
||||
x0, y0, x1, y1 = rect
|
||||
raw_points, raw_descrs = self.detect_features(image)
|
||||
points, descs = [], []
|
||||
for kp, desc in zip(raw_points, raw_descrs):
|
||||
x, y = kp.pt
|
||||
if x0 <= x <= x1 and y0 <= y <= y1:
|
||||
points.append(kp)
|
||||
descs.append(desc)
|
||||
descs = np.uint8(descs)
|
||||
self.matcher.add([descs])
|
||||
target = PlanarTarget(image = image, rect=rect, keypoints = points, descrs=descs, data=data)
|
||||
self.targets.append(target)
|
||||
|
||||
def clear(self):
|
||||
'''Remove all targets'''
|
||||
self.targets = []
|
||||
self.matcher.clear()
|
||||
|
||||
def track(self, frame):
|
||||
'''Returns a list of detected TrackedTarget objects'''
|
||||
self.frame_points, frame_descrs = self.detect_features(frame)
|
||||
if len(self.frame_points) < MIN_MATCH_COUNT:
|
||||
return []
|
||||
matches = self.matcher.knnMatch(frame_descrs, k = 2)
|
||||
matches = [m[0] for m in matches if len(m) == 2 and m[0].distance < m[1].distance * 0.75]
|
||||
if len(matches) < MIN_MATCH_COUNT:
|
||||
return []
|
||||
matches_by_id = [[] for _ in xrange(len(self.targets))]
|
||||
for m in matches:
|
||||
matches_by_id[m.imgIdx].append(m)
|
||||
tracked = []
|
||||
for imgIdx, matches in enumerate(matches_by_id):
|
||||
if len(matches) < MIN_MATCH_COUNT:
|
||||
continue
|
||||
target = self.targets[imgIdx]
|
||||
p0 = [target.keypoints[m.trainIdx].pt for m in matches]
|
||||
p1 = [self.frame_points[m.queryIdx].pt for m in matches]
|
||||
p0, p1 = np.float32((p0, p1))
|
||||
H, status = cv2.findHomography(p0, p1, cv2.RANSAC, 3.0)
|
||||
status = status.ravel() != 0
|
||||
if status.sum() < MIN_MATCH_COUNT:
|
||||
continue
|
||||
p0, p1 = p0[status], p1[status]
|
||||
|
||||
x0, y0, x1, y1 = target.rect
|
||||
quad = np.float32([[x0, y0], [x1, y0], [x1, y1], [x0, y1]])
|
||||
quad = cv2.perspectiveTransform(quad.reshape(1, -1, 2), H).reshape(-1, 2)
|
||||
|
||||
track = TrackedTarget(target=target, p0=p0, p1=p1, H=H, quad=quad)
|
||||
tracked.append(track)
|
||||
tracked.sort(key = lambda t: len(t.p0), reverse=True)
|
||||
return tracked
|
||||
|
||||
def detect_features(self, frame):
|
||||
'''detect_features(self, frame) -> keypoints, descrs'''
|
||||
keypoints, descrs = self.detector.detectAndCompute(frame, None)
|
||||
if descrs is None: # detectAndCompute returns descs=None if not keypoints found
|
||||
descrs = []
|
||||
return keypoints, descrs
|
67
modules/python/test/test_grabcut.py
Normal file
67
modules/python/test/test_grabcut.py
Normal 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 == None:
|
||||
self.assertEqual(0, 1, '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 == None:
|
||||
mask_prob = mask.copy()
|
||||
cv2.imwrite(self.extraTestDataPath + '/cv/grabcut/mask_probpy.png', mask_prob)
|
||||
if exp_mask1 == 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 == 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)
|
96
modules/python/test/test_lk_homography.py
Normal file
96
modules/python/test/test_lk_homography.py
Normal 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)
|
111
modules/python/test/test_lk_track.py
Normal file
111
modules/python/test/test_lk_track.py
Normal 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
|
69
modules/python/test/test_mser.py
Normal file
69
modules/python/test/test_mser.py
Normal 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)
|
51
modules/python/test/test_watershed.py
Normal file
51
modules/python/test/test_watershed.py
Normal file
@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
Watershed segmentation
|
||||
=========
|
||||
|
||||
This program demonstrates the watershed segmentation algorithm
|
||||
in OpenCV: watershed().
|
||||
|
||||
Usage
|
||||
-----
|
||||
watershed.py [image filename]
|
||||
|
||||
Keys
|
||||
----
|
||||
1-7 - switch marker color
|
||||
SPACE - update segmentation
|
||||
r - reset
|
||||
a - toggle autoupdate
|
||||
ESC - exit
|
||||
|
||||
'''
|
||||
|
||||
|
||||
# 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 == None or markers == 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 == 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)
|
@ -37,7 +37,7 @@ class NewOpenCVTests(unittest.TestCase):
|
||||
with open(candidate, 'rb') as f:
|
||||
filedata = f.read()
|
||||
if filedata is None:
|
||||
filedata = urlopen(NewOpenCVTests.repoUrl + '/' + filename).read()
|
||||
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]
|
||||
|
||||
@ -64,10 +64,16 @@ class NewOpenCVTests(unittest.TestCase):
|
||||
def intersectionRate(s1, s2):
|
||||
|
||||
x1, y1, x2, y2 = s1
|
||||
s1 = [[x1, y1], [x2,y1], [x2, y2], [x1, y2] ]
|
||||
s1 = np.array([[x1, y1], [x2,y1], [x2, y2], [x1, y2]])
|
||||
|
||||
x1, y1, x2, y2 = s2
|
||||
s2 = [[x1, y1], [x2,y1], [x2, y2], [x1, y2] ]
|
||||
#print(np.array(s2))
|
||||
area, intersection = cv2.intersectConvexConvex(np.array(s1), np.array(s2))
|
||||
return 2 * area / (cv2.contourArea(np.array(s1)) + cv2.contourArea(np.array(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
|
@ -13,41 +13,89 @@ defaultSize = 512
|
||||
|
||||
class TestSceneRender():
|
||||
|
||||
def __init__(self, bgImg = None, deformation = False, **params):
|
||||
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 != None:
|
||||
self.sceneBg = bgImg.copy()
|
||||
else:
|
||||
self.sceneBg = np.zeros((defaultSize, defaultSize, 3), np.uint8)
|
||||
self.sceneBg = np.zeros(defaultSize, defaultSize, np.uint8)
|
||||
|
||||
self.w = self.sceneBg.shape[0]
|
||||
self.h = self.sceneBg.shape[1]
|
||||
|
||||
if fgImg != 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 != 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):
|
||||
x0, y0 = self.currentRect[0]
|
||||
x1, y1 = self.currentRect[2]
|
||||
return np.array([x0, y0, x1, y1])
|
||||
|
||||
if self.foreground != 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):
|
||||
self.time += self.timeStep
|
||||
img = self.sceneBg.copy()
|
||||
|
||||
self.currentRect = self.initialRect + np.int( 30*cos(self.time) + 50*sin(self.time/3))
|
||||
if(self.deformation):
|
||||
self.currentRect[1:3] += np.int(self.h/20*cos(self.time))
|
||||
if self.foreground != 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))
|
||||
|
||||
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):
|
||||
@ -58,7 +106,7 @@ if __name__ == '__main__':
|
||||
|
||||
backGr = cv2.imread('../../../samples/data/lena.jpg')
|
||||
|
||||
render = TestSceneRender(backGr)
|
||||
render = TestSceneRender(backGr, noise = 0.5)
|
||||
|
||||
while True:
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user