Skip to content

Commit

Permalink
Python samples adapted for Python3 compatibility
Browse files Browse the repository at this point in the history
Common fixes:
- print function
- int / float division
- map, zip iterators in py3 but lists in py2

Known bugs with opencv 3.0.0
- digits.py, called via digits_video.py: opencv#4969
- gaussian_mix.py: opencv#4232
- video_v4l2.py: opencv#5474

Not working:
- letter_recog.py due to changed ml_StatModel.train() signature
  • Loading branch information
bastelflp committed Dec 13, 2015
1 parent 5cdf0e3 commit 4ed2d63
Show file tree
Hide file tree
Showing 23 changed files with 218 additions and 131 deletions.
23 changes: 13 additions & 10 deletions samples/python2/asift.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
Press left mouse button on a feature point to see its matching point.
'''

# Python 2/3 compatibility
from __future__ import print_function

import numpy as np
import cv2

Expand Down Expand Up @@ -96,15 +99,15 @@ def f(p):
ires = pool.imap(f, params)

for i, (k, d) in enumerate(ires):
print 'affine sampling: %d / %d\r' % (i+1, len(params)),
print('affine sampling: %d / %d\r' % (i+1, len(params)), end='')
keypoints.extend(k)
descrs.extend(d)

print
print()
return keypoints, np.array(descrs)

if __name__ == '__main__':
print __doc__
print(__doc__)

import sys, getopt
opts, args = getopt.getopt(sys.argv[1:], '', ['feature='])
Expand All @@ -121,36 +124,36 @@ def f(p):
detector, matcher = init_feature(feature_name)

if img1 is None:
print 'Failed to load fn1:', fn1
print('Failed to load fn1:', fn1)
sys.exit(1)

if img2 is None:
print 'Failed to load fn2:', fn2
print('Failed to load fn2:', fn2)
sys.exit(1)

if detector is None:
print 'unknown feature:', feature_name
print('unknown feature:', feature_name)
sys.exit(1)

print 'using', feature_name
print('using', feature_name)

pool=ThreadPool(processes = cv2.getNumberOfCPUs())
kp1, desc1 = affine_detect(detector, img1, pool=pool)
kp2, desc2 = affine_detect(detector, img2, pool=pool)
print 'img1 - %d features, img2 - %d features' % (len(kp1), len(kp2))
print('img1 - %d features, img2 - %d features' % (len(kp1), len(kp2)))

def match_and_draw(win):
with Timer('matching'):
raw_matches = matcher.knnMatch(desc1, trainDescriptors = desc2, k = 2) #2
p1, p2, kp_pairs = filter_matches(kp1, kp2, raw_matches)
if len(p1) >= 4:
H, status = cv2.findHomography(p1, p2, cv2.RANSAC, 5.0)
print '%d / %d inliers/matched' % (np.sum(status), len(status))
print('%d / %d inliers/matched' % (np.sum(status), len(status)))
# do not draw outliers (there will be a lot of them)
kp_pairs = [kpp for kpp, flag in zip(kp_pairs, status) if flag]
else:
H, status = None, None
print '%d matches found, not enough for homography estimation' % len(p1)
print('%d matches found, not enough for homography estimation' % len(p1))

vis = explore_match(win, img1, img2, kp_pairs, None, H)

Expand Down
16 changes: 12 additions & 4 deletions samples/python2/contours.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,23 @@
A trackbar is put up which controls the contour level from -3 to 3
'''

# Python 2/3 compatibility
from __future__ import print_function
import sys
PY3 = sys.version_info[0] == 3

if PY3:
xrange = range

import numpy as np
import cv2

def make_image():
img = np.zeros((500, 500), np.uint8)
black, white = 0, 255
for i in xrange(6):
dx = (i%2)*250 - 30
dy = (i/2)*150
dx = int((i%2)*250 - 30)
dy = int((i/2.)*150)

if i == 0:
for j in xrange(11):
Expand All @@ -41,7 +49,7 @@ def make_image():
return img

if __name__ == '__main__':
print __doc__
print(__doc__)

img = make_image()
h, w = img.shape[:2]
Expand All @@ -52,7 +60,7 @@ def make_image():
def update(levels):
vis = np.zeros((h, w, 3), np.uint8)
levels = levels - 3
cv2.drawContours( vis, contours, (-1, 3)[levels <= 0], (128,255,255),
cv2.drawContours( vis, contours, (-1, 2)[levels <= 0], (128,255,255),
3, cv2.LINE_AA, hierarchy, abs(levels) )
cv2.imshow('contours', vis)
update(3)
Expand Down
28 changes: 16 additions & 12 deletions samples/python2/digits.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
digits.py
'''


# Python 2/3 compatibility
from __future__ import print_function

# built-in modules
from multiprocessing.pool import ThreadPool

Expand Down Expand Up @@ -50,7 +54,7 @@ def split2d(img, cell_size, flatten=True):
return cells

def load_digits(fn):
print 'loading "%s" ...' % fn
print('loading "%s" ...' % fn)
digits_img = cv2.imread(fn, 0)
digits = split2d(digits_img, (SZ, SZ))
labels = np.repeat(np.arange(CLASS_N), len(digits)/CLASS_N)
Expand All @@ -67,7 +71,7 @@ def deskew(img):

class StatModel(object):
def load(self, fn):
self.model.load(fn)
self.model.load(fn) # Known bug: https://github.com/Itseez/opencv/issues/4969
def save(self, fn):
self.model.save(fn)

Expand Down Expand Up @@ -101,14 +105,14 @@ def predict(self, samples):
def evaluate_model(model, digits, samples, labels):
resp = model.predict(samples)
err = (labels != resp).mean()
print 'error: %.2f %%' % (err*100)
print('error: %.2f %%' % (err*100))

confusion = np.zeros((10, 10), np.int32)
for i, j in zip(labels, resp):
confusion[i, j] += 1
print 'confusion matrix:'
print confusion
print
print('confusion matrix:')
print(confusion)
print()

vis = []
for img, flag in zip(digits, resp == labels):
Expand Down Expand Up @@ -145,17 +149,17 @@ def preprocess_hog(digits):


if __name__ == '__main__':
print __doc__
print(__doc__)

digits, labels = load_digits(DIGITS_FN)

print 'preprocessing...'
print('preprocessing...')
# shuffle digits
rand = np.random.RandomState(321)
shuffle = rand.permutation(len(digits))
digits, labels = digits[shuffle], labels[shuffle]

digits2 = map(deskew, digits)
digits2 = list(map(deskew, digits))
samples = preprocess_hog(digits2)

train_n = int(0.9*len(samples))
Expand All @@ -165,18 +169,18 @@ def preprocess_hog(digits):
labels_train, labels_test = np.split(labels, [train_n])


print 'training KNearest...'
print('training KNearest...')
model = KNearest(k=4)
model.train(samples_train, labels_train)
vis = evaluate_model(model, digits_test, samples_test, labels_test)
cv2.imshow('KNearest test', vis)

print 'training SVM...'
print('training SVM...')
model = SVM(C=2.67, gamma=5.383)
model.train(samples_train, labels_train)
vis = evaluate_model(model, digits_test, samples_test, labels_test)
cv2.imshow('SVM test', vis)
print 'saving SVM as "digits_svm.dat"...'
print('saving SVM as "digits_svm.dat"...')
model.save('digits_svm.dat')

cv2.waitKey(0)
39 changes: 24 additions & 15 deletions samples/python2/digits_adjust.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@
'''

# Python 2/3 compatibility
from __future__ import print_function
import sys
PY3 = sys.version_info[0] == 3

if PY3:
xrange = range

import numpy as np
import cv2
from multiprocessing.pool import ThreadPool
Expand All @@ -33,10 +41,10 @@ def f(i):
model.train(train_samples, train_labels)
resp = model.predict(test_samples)
score = (resp != test_labels).mean()
print ".",
print(".", end='')
return score
if pool is None:
scores = map(f, xrange(kfold))
scores = list(map(f, xrange(kfold)))
else:
scores = pool.map(f, xrange(kfold))
return np.mean(scores)
Expand All @@ -50,7 +58,7 @@ def preprocess(self):
digits, labels = load_digits(DIGITS_FN)
shuffle = np.random.permutation(len(digits))
digits, labels = digits[shuffle], labels[shuffle]
digits2 = map(deskew, digits)
digits2 = list(map(deskew, digits))
samples = preprocess_hog(digits2)
return samples, labels

Expand All @@ -68,7 +76,7 @@ def adjust_SVM(self):
scores = np.zeros((len(Cs), len(gammas)))
scores[:] = np.nan

print 'adjusting SVM (may take a long time) ...'
print('adjusting SVM (may take a long time) ...')
def f(job):
i, j = job
samples, labels = self.get_dataset()
Expand All @@ -79,20 +87,21 @@ def f(job):
ires = self.run_jobs(f, np.ndindex(*scores.shape))
for count, (i, j, score) in enumerate(ires):
scores[i, j] = score
print '%d / %d (best error: %.2f %%, last: %.2f %%)' % (count+1, scores.size, np.nanmin(scores)*100, score*100)
print scores
print('%d / %d (best error: %.2f %%, last: %.2f %%)' %
(count+1, scores.size, np.nanmin(scores)*100, score*100))
print(scores)

print 'writing score table to "svm_scores.npz"'
print('writing score table to "svm_scores.npz"')
np.savez('svm_scores.npz', scores=scores, Cs=Cs, gammas=gammas)

i, j = np.unravel_index(scores.argmin(), scores.shape)
best_params = dict(C = Cs[i], gamma=gammas[j])
print 'best params:', best_params
print 'best error: %.2f %%' % (scores.min()*100)
print('best params:', best_params)
print('best error: %.2f %%' % (scores.min()*100))
return best_params

def adjust_KNearest(self):
print 'adjusting KNearest ...'
print('adjusting KNearest ...')
def f(k):
samples, labels = self.get_dataset()
err = cross_validate(KNearest, dict(k=k), samples, labels)
Expand All @@ -101,24 +110,24 @@ def f(k):
for k, err in self.run_jobs(f, xrange(1, 9)):
if err < best_err:
best_err, best_k = err, k
print 'k = %d, error: %.2f %%' % (k, err*100)
print('k = %d, error: %.2f %%' % (k, err*100))
best_params = dict(k=best_k)
print 'best params:', best_params, 'err: %.2f' % (best_err*100)
print('best params:', best_params, 'err: %.2f' % (best_err*100))
return best_params


if __name__ == '__main__':
import getopt
import sys

print __doc__
print(__doc__)

args, _ = getopt.getopt(sys.argv[1:], '', ['model='])
args = dict(args)
args.setdefault('--model', 'svm')
args.setdefault('--env', '')
if args['--model'] not in ['svm', 'knearest']:
print 'unknown model "%s"' % args['--model']
print('unknown model "%s"' % args['--model'])
sys.exit(1)

t = clock()
Expand All @@ -127,4 +136,4 @@ def f(k):
app.adjust_KNearest()
else:
app.adjust_SVM()
print 'work time: %f s' % (clock() - t)
print('work time: %f s' % (clock() - t))
5 changes: 4 additions & 1 deletion samples/python2/digits_video.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#!/usr/bin/env python

# Python 2/3 compatibility
from __future__ import print_function

import numpy as np
import cv2

Expand All @@ -22,7 +25,7 @@ def main():

classifier_fn = 'digits_svm.dat'
if not os.path.exists(classifier_fn):
print '"%s" not found, run digits.py first' % classifier_fn
print('"%s" not found, run digits.py first' % classifier_fn)
return
model = SVM()
model.load(classifier_fn)
Expand Down
3 changes: 2 additions & 1 deletion samples/python2/edge.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from __future__ import print_function

import cv2
import numpy as np

# relative module
import video
Expand Down Expand Up @@ -45,7 +46,7 @@ def nothing(*arg):
thrs2 = cv2.getTrackbarPos('thrs2', 'edge')
edge = cv2.Canny(gray, thrs1, thrs2, apertureSize=5)
vis = img.copy()
vis /= 2
vis = np.uint8(vis/2.)
vis[edge != 0] = (0, 255, 0)
cv2.imshow('edge', vis)
ch = cv2.waitKey(5) & 0xFF
Expand Down
5 changes: 4 additions & 1 deletion samples/python2/feature_homography.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
Select a textured planar object to track by drawing a box with a mouse.
'''

# Python 2/3 compatibility
from __future__ import print_function

import numpy as np
import cv2

Expand Down Expand Up @@ -84,7 +87,7 @@ def run(self):


if __name__ == '__main__':
print __doc__
print(__doc__)

import sys
try:
Expand Down
Loading

0 comments on commit 4ed2d63

Please sign in to comment.