VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > python爬虫 >
  • python爬虫之旋转傻乌龟——几何变换实践(2)

本站最新发布   Python从入门到精通|Python基础教程
试听地址  
https://www.xin3721.com/eschool/pythonxin3721/


再解决双线性插值,关于该算法的原理挺简单的,读者可以网上查找(提一点,理解双线性插值时可以想象3D模型,Z轴为灰度值)。对于该函数,借鉴一下remap函数,输入参数设两个map,分别表示x,y的映射。map的大小跟图片大小相同,也就是说,一共有rows*cols点需要插值,除了用两个for迭代,我们也可以将rows和cols作为矩阵的两个额外维度,表示样本数。计算的话,利用矩阵的点乘代替凌乱的长算式,显得很简洁,公式如下:

 

 代码如下,经测试,执行一次该函数,花费时间为45ms,这要比原来的1.4s快多了(实在不知道该怎么进一步优化了,mxy、img下表索引、求和各花了15ms)


def InterLinearMap(img,mapx,mapy): #(rows,cols) inty = np.int32(mapy) intx = np.int32(mapx) nxty = 1+inty nxtx = 1+intx #(rows,cols) party = mapy - inty partx = mapx - intx resy = 1-party resx = 1-partx #(4,rows,cols) mxy = np.stack((resy*partx,resy*resx,partx*party, resx*party)) mxy = np.expand_dims(mxy,axis=-1) #(4,rows,cols,3) mf = np.stack((img[inty,nxtx],img[inty,intx],img[nxty,nxtx],img[nxty,intx])) #res -> shape(rows,cols,3) res = np.sum(mxy*mf,axis=0) res = np.uint8(res+0.5) return res

 

 

综上,给出完整代码:


import cv2 import numpy as np img = cv2.imread('image/turtle.jpg') size = img.shape[:-1] cv2.namedWindow('img') #缩放矩阵 def GetResizeMatrix(scalex,scaley): M = np.zeros((3,3),dtype=np.float32) M.itemset((0,0),scalex) M.itemset((1,1),scaley) M.itemset((2,2),1) return M #平移矩阵 def GetMoveMatrix(x,y): M = np.zeros((3, 3), dtype=np.float32) M.itemset((0, 0), 1) M.itemset((1, 1), 1) M.itemset((2, 2), 1) M.itemset((0, 2), x) M.itemset((1, 2), y) return M #旋转矩阵 def GetRotationMatrix(angle): M = np.zeros((3, 3), dtype=np.float32) M.itemset((0, 0), np.cos(angle)) M.itemset((0, 1), -np.sin(angle)) M.itemset((1, 0), np.sin(angle)) M.itemset((1, 1), np.cos(angle)) M.itemset((2, 2), 1) return M def InterLinearMap(img,mapx,mapy): #(rows,cols) inty = np.int32(mapy) intx = np.int32(mapx) nxty = 1+inty nxtx = 1+intx #(rows,cols) party = mapy - inty partx = mapx - intx resy = 1-party resx = 1-partx #(4,rows,cols) mxy = np.stack((resy*partx,resy*resx,partx*party, resx*party)) mxy = np.expand_dims(mxy,axis=-1) #(4,rows,cols,3) mf = np.stack((img[inty,nxtx],img[inty,intx],img[nxty,nxtx],img[nxty,intx])) #res -> shape(rows,cols,3) res = np.sum(mxy*mf,axis=0) res = np.uint8(res+0.5) return res def WarpAffine(img,Mat,size): rows = size[0] cols = size[1] #生成矩阵[X Y 1] ones = np.ones((rows, cols), dtype=np.float32) #gridx/gridy -> shape(rows,cols) gridx,gridy= np.meshgrid(np.arange(0, cols),np.arange(0, rows)) #dst -> shape(3,rows,cols) dst = np.stack((gridx, gridy, ones)) #求逆矩阵 M -> shape(3,3) Mat = np.linalg.inv(Mat) #获得矩阵[x,y,1] -> shape(3,rows,cols) src = np.tensordot(Mat,dst,axes=[[-1],[0]]) #mapx/mapy -> shape(rows,cols) mapx = src[0]#坐标非整数 mapy = src[1]#坐标非整数 #仿射出界的设为原点 flags = (mapy > rows - 2) + (mapy < 0) + (mapx > cols - 2) + (mapx < 0) mapy[flags] = 0 mapx[flags] = 0 #双线性插值 result = InterLinearMap(img, mapx, mapy) return result if __name__ == '__main__': center_x = size[1]/2 center_y = size[0]/2 for x in np.linspace(0,2*np.pi,100): angle = 360*x/2/np.pi scale = 0.2+0.2*np.sin(x) path_x = x*50+100 path_y = (np.sin(x)+1)*100+100 M = GetMoveMatrix(path_x,path_y)@GetRotationMatrix(x)\ @GetResizeMatrix(scale,scale)@GetMoveMatrix(-center_x,-center_y) dst = WarpAffine(img,M,size) cv2.imshow('img',dst) cv2.waitKey(1)
 
 

 

__EOF__

作  者KenSporger

相关教程