今天看了看imgaug库关于仿射变化后图片上标注点和标注框的问题,感觉比较繁琐。因此还是使用自己写的代码来进行这些操作把。本篇讲一下旋转后标注框的变化:
1:图片旋转后尺寸分为原图像尺寸,对图像进行剪裁
2:图片旋转后尺寸从新计算,使用旋转后的尺寸进行仿射。
首先上个图:
图上theta代表旋转角度,取值范围0-360,可为负数。坐标建立按照opencv的坐标系。旋转后的宽和高按照上面的公式进行计算即可。
这个公式是仿射变化的公式,tx,ty是偏移量。
####input: 1.img type:numpy_array 2.angle type:int 3.point type:numpy_array shape(None,8)
####output: 1.img 2.point 旋转后变化后的点坐标 shape(None,8) 8个坐标,顺序左上,右上,右下,左下
def rotation_point(img,angle=15,point=None,keep_size = False):
if keep_size:
cols = img.shape[1]
rows = img.shape[0]
M = cv2.getRotationMatrix2D((cols / 2, rows / 2), angle, 1)
img = cv2.warpAffine(img, M, (cols, rows))
a = M[:, :2] ##a.shape (2,2)
b = M[:, 2:] ###b.shape(2,1)
b = np.reshape(b,newshape=(1,2))
a = np.transpose(a)
point = np.reshape(point,newshape=(len(point)*4,2))
point = np.dot(point,a)+b
point = np.reshape(point,newshape=(len(point)/4,8))
return img,point
else:
cols = img.shape[1]
rows = img.shape[0]
M = cv2.getRotationMatrix2D((cols / 2, rows / 2), angle, 1)
heightNew = int(cols * fabs(sin(radians(angle))) + rows* fabs(cos(radians(angle))))
widthNew = int(rows * fabs(sin(radians(angle))) + cols* fabs(cos(radians(angle))))
M[0, 2] += (widthNew - cols) / 2
M[1, 2] += (heightNew - rows) / 2
img = cv2.warpAffine(img, M, (widthNew, heightNew))
a = M[:, :2] ##a.shape (2,2)
b = M[:, 2:] ###b.shape(2,1)
b = np.reshape(b, newshape=(1, 2))
a = np.transpose(a)
point = np.reshape(point, newshape=(len(point) * 4, 2))
point = np.dot(point, a) + b
point = np.reshape(point, newshape=(len(point) / 4, 8))
return img, point
函数keep_size参数用于是否进行裁剪和使用变化后的尺寸进行输出。下面是结果图:
原图 裁剪图
未裁剪图
对于我们进行目标检测来讲,裁剪图上的有些点的坐标已经超过了图像正常宽、高的取值范围。有可能四边形会切割成五边型,如何去处理此类的坐标点,我暂时没有想到好的方法,可以求交点来解决不知道对不对。但是,最好还是不要裁剪,然后resize后可以送入网络进行训练,这样可以节省好多不必要的麻烦。
有什么问题,可以留言或者邮箱给我。