OpenCV是应用最被广泛的的开源视觉库。他允许你使用很少的代码来检测图片或视频中的人脸。
这里有一些互联网上的教程来阐述怎么在OpenCV中使用仿射变换(affine transform)旋转图片--他们并没有处理旋转一个图片里的矩形一般会把矩形的边角切掉这一问题,所以产生的图片需要修改。当正确的使用一点代码时,这是一点瑕疵。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
def rotate_about_center(src, angle, scale = 1. ):
w = src.shape[ 1 ]
h = src.shape[ 0 ]
rangle = np.deg2rad(angle) # angle in radians
# now calculate new image width and height
nw = ( abs (np.sin(rangle) * h) + abs (np.cos(rangle) * w)) * scale
nh = ( abs (np.cos(rangle) * h) + abs (np.sin(rangle) * w)) * scale
# ask OpenCV for the rotation matrix
rot_mat = cv2.getRotationMatrix2D((nw * 0.5 , nh * 0.5 ), angle, scale)
# calculate the move from the old center to the new center combined
# with the rotation
rot_move = np.dot(rot_mat, np.array([(nw - w) * 0.5 , (nh - h) * 0.5 , 0 ]))
# the move only affects the translation, so update the translation
# part of the transform
rot_mat[ 0 , 2 ] + = rot_move[ 0 ]
rot_mat[ 1 , 2 ] + = rot_move[ 1 ]
return cv2.warpAffine(src, rot_mat, ( int (math.ceil(nw)), int (math.ceil(nh))), flags = cv2.INTER_LANCZOS4)
|
从原始图像的中心到目标图像的中心,在旋转中的仿射变换必须结合 仿射变换的平移。一个在平面中(2D)的仿射变换是一个2x2的矩阵A和一个平移的向量a-它取得原始点p = (x,y)到目标:Ap + a.结合了两次变换Ap + a和Bp+b,先做A然后是B,软后得到了 B(Ap + a)+ b --另一个与矩阵BA和向量Ba + b的仿射变换。
在此情况下,我们正在把旋转功能与平移合并。作为相似变换的平移具有2x2矩阵I与运动矢量m的特征,所以,以Ip + m表示,我们想首先平移到新的中心,饭后旋转它,这样,在应用Ip + m 后我们旋转Rp + r,产生Rp + Rm + r,这解释了为什么我们不得不只增加两个系数。
附言:悲哀地说,如果numpy把输入的数据看作是矢量的矢量,而不是矩阵,那解释了乘法算子不是矩阵乘法,所以,我们必须明确地写入np.dot。
又附言:我们使用兰索斯插值,这一般对扩展有利而对把规模缩得非常小不利;考虑到应用方面,我们应该改编这个插值。
再附言:与Python的相互作用因cv2模块而改善很多,但是因为numpy的坐标不同于OpenCV,所以仍不可避免地有一些为完善之处。另外,因某个原因,OpenCV始终把各单元当作度数而不是弧度使用,等等。就numpy而言,图像阵列中的坐标是以[y,x]次序存取的,如首先垂直向下增加,接着水平向右增加一样。就OpenCV而言,大小用(宽度,高度)表示,次序正相反。