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