parent
0c6e09f060
commit
e4fed417d2
10 changed files with 627 additions and 27 deletions
@ -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 |
@ -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) |
@ -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) |
@ -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 |
@ -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) |
@ -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) |
Loading…
Reference in new issue