#!/usr/bin/env python ''' This module contais some common routines used by other samples. ''' import numpy as np import cv2 import os from contextlib import contextmanager import itertools as it image_extensions = ['.bmp', '.jpg', '.jpeg', '.png', '.tif', '.tiff', '.pbm', '.pgm', '.ppm'] class Bunch(object): def __init__(self, **kw): self.__dict__.update(kw) def __str__(self): return str(self.__dict__) def splitfn(fn): path, fn = os.path.split(fn) name, ext = os.path.splitext(fn) return path, name, ext def anorm2(a): return (a*a).sum(-1) def anorm(a): return np.sqrt( anorm2(a) ) def homotrans(H, x, y): xs = H[0, 0]*x + H[0, 1]*y + H[0, 2] ys = H[1, 0]*x + H[1, 1]*y + H[1, 2] s = H[2, 0]*x + H[2, 1]*y + H[2, 2] return xs/s, ys/s def to_rect(a): a = np.ravel(a) if len(a) == 2: a = (0, 0, a[0], a[1]) return np.array(a, np.float64).reshape(2, 2) def rect2rect_mtx(src, dst): src, dst = to_rect(src), to_rect(dst) cx, cy = (dst[1] - dst[0]) / (src[1] - src[0]) tx, ty = dst[0] - src[0] * (cx, cy) M = np.float64([[ cx, 0, tx], [ 0, cy, ty], [ 0, 0, 1]]) return M def lookat(eye, target, up = (0, 0, 1)): fwd = np.asarray(target, np.float64) - eye fwd /= anorm(fwd) right = np.cross(fwd, up) right /= anorm(right) down = np.cross(fwd, right) R = np.float64([right, down, fwd]) tvec = -np.dot(R, eye) return R, tvec def mtx2rvec(R): w, u, vt = cv2.SVDecomp(R - np.eye(3)) p = vt[0] + u[:,0]*w[0] # same as np.dot(R, vt[0]) c = np.dot(vt[0], p) s = np.dot(vt[1], p) axis = np.cross(vt[0], vt[1]) return axis * np.arctan2(s, c) def draw_str(dst, (x, y), s): cv2.putText(dst, s, (x+1, y+1), cv2.FONT_HERSHEY_PLAIN, 1.0, (0, 0, 0), thickness = 2, lineType=cv2.CV_AA) cv2.putText(dst, s, (x, y), cv2.FONT_HERSHEY_PLAIN, 1.0, (255, 255, 255), lineType=cv2.CV_AA) class Sketcher: def __init__(self, windowname, dests, colors_func): self.prev_pt = None self.windowname = windowname self.dests = dests self.colors_func = colors_func self.dirty = False self.show() cv2.setMouseCallback(self.windowname, self.on_mouse) def show(self): cv2.imshow(self.windowname, self.dests[0]) def on_mouse(self, event, x, y, flags, param): pt = (x, y) if event == cv2.EVENT_LBUTTONDOWN: self.prev_pt = pt if self.prev_pt and flags & cv2.EVENT_FLAG_LBUTTON: for dst, color in zip(self.dests, self.colors_func()): cv2.line(dst, self.prev_pt, pt, color, 5) self.dirty = True self.prev_pt = pt self.show() else: self.prev_pt = None # palette data from matplotlib/_cm.py _jet_data = {'red': ((0., 0, 0), (0.35, 0, 0), (0.66, 1, 1), (0.89,1, 1), (1, 0.5, 0.5)), 'green': ((0., 0, 0), (0.125,0, 0), (0.375,1, 1), (0.64,1, 1), (0.91,0,0), (1, 0, 0)), 'blue': ((0., 0.5, 0.5), (0.11, 1, 1), (0.34, 1, 1), (0.65,0, 0), (1, 0, 0))} cmap_data = { 'jet' : _jet_data } def make_cmap(name, n=256): data = cmap_data[name] xs = np.linspace(0.0, 1.0, n) channels = [] eps = 1e-6 for ch_name in ['blue', 'green', 'red']: ch_data = data[ch_name] xp, yp = [], [] for x, y1, y2 in ch_data: xp += [x, x+eps] yp += [y1, y2] ch = np.interp(xs, xp, yp) channels.append(ch) return np.uint8(np.array(channels).T*255) def nothing(*arg, **kw): pass def clock(): return cv2.getTickCount() / cv2.getTickFrequency() @contextmanager def Timer(msg): print msg, '...', start = clock() try: yield finally: print "%.2f ms" % ((clock()-start)*1000) class StatValue: def __init__(self, smooth_coef = 0.5): self.value = None self.smooth_coef = smooth_coef def update(self, v): if self.value is None: self.value = v else: c = self.smooth_coef self.value = c * self.value + (1.0-c) * v class RectSelector: def __init__(self, win, callback): self.win = win self.callback = callback cv2.setMouseCallback(win, self.onmouse) self.drag_start = None self.drag_rect = None def onmouse(self, event, x, y, flags, param): x, y = np.int16([x, y]) # BUG if event == cv2.EVENT_LBUTTONDOWN: self.drag_start = (x, y) if self.drag_start: if flags & cv2.EVENT_FLAG_LBUTTON: xo, yo = self.drag_start x0, y0 = np.minimum([xo, yo], [x, y]) x1, y1 = np.maximum([xo, yo], [x, y]) self.drag_rect = None if x1-x0 > 0 and y1-y0 > 0: self.drag_rect = (x0, y0, x1, y1) else: rect = self.drag_rect self.drag_start = None self.drag_rect = None if rect: self.callback(rect) def draw(self, vis): if not self.drag_rect: return False x0, y0, x1, y1 = self.drag_rect cv2.rectangle(vis, (x0, y0), (x1, y1), (0, 255, 0), 2) return True @property def dragging(self): return self.drag_rect is not None def grouper(n, iterable, fillvalue=None): '''grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx''' args = [iter(iterable)] * n return it.izip_longest(fillvalue=fillvalue, *args) def mosaic(w, imgs): '''Make a grid from images. w -- number of grid columns imgs -- images (must have same size and format) ''' imgs = iter(imgs) img0 = imgs.next() pad = np.zeros_like(img0) imgs = it.chain([img0], imgs) rows = grouper(w, imgs, pad) return np.vstack(map(np.hstack, rows)) def getsize(img): h, w = img.shape[:2] return w, h def mdot(*args): return reduce(np.dot, args) def draw_keypoints(vis, keypoints, color = (0, 255, 255)): for kp in keypoints: x, y = kp.pt cv2.circle(vis, (int(x), int(y)), 2, color)
第15行: Bunch函数是将传入 的参数作为一个字典便于查询使用。使用例程如下
>>> jack = Bunch(a=4,b=5,c=6) >>> print(jack) {'c': 6, 'a': 4, 'b': 5}
bokeyuan={"b":1, "o":2, "k":3, "e":4, "y":5, "u":6, "a":7, "n":8, }
该对象是用于将一个字典转化成对象的代码例如 现在想转化一个对象,我们通常会这样写
class Dict2Obj: def __init__(self,bokeyuan): self.b = bokeyuan['b'] self.o = bokeyuan['o'] self.k = bokeyuan['k'] self.e = bokeyuan['e'] self.y = bokeyuan['y'] self.u = bokeyuan['u'] self.a = bokeyuan['a'] self.n = bokeyuan['n']
但是在了解这个方法时候我们会这样写,
1 class Dict2Obj: 2 def __init__(self,bokeyuan): 3 self.__dict__.update(bokeyuan)
然后这样调用
jack = Dict2Obj(bokeyuan)
总结:__dict__用于显示该对象的所有字典元素。__dict__.update()用于更新或者添加元素。
第21行:该函数的作用是传入路径,os.path.split分割 路径名和文件名 os.path.splitext传入文件名.后缀 用于分割文件名和后缀
>>> os.path.split('jack/2/3/asd.jpg') ('jack/2/3', 'asd.jpg') >>> os.path.splitext('asd.jpg') ('asd', '.jpg')
第26行: 矩阵相乘,然后每一行进行求和返回新的矩阵
第28行: 将第26行的结果开方
第31行: 3*3的矩阵 将第一行的元素乘以x第二行乘以x第三行乘以x 然后将第一行和第二行的结果除以第三行。
第37行: np.ravel将矩阵多维矩阵a (其中只有四个元素或两个元素)转化为一维矩阵,如果其中只有两个元素的话,进行如下操作
a = (0, 0, a[0], a[1])
然后将其转化为float类型的2*2的矩阵。
第43行: rect2rect_mtx(src, dst): 首先将传入的两个图像进行to_rect(a) 操作,然后(dst的第2行-第一行)/(src的第二行-第一行),