不管是在目标检测还是在OCR文本检测的时候,都会有数据预处理这一步。那我们在对图像进行缩放、旋转的过程中,标注的位置信息肯定也是会变化的。
1 缩放
图像利用OpenCV进行缩放,我们可以使用resize方法进行。但是标注信息呢?以按照原点进行缩放为例,原图大小的宽度和高度分别为w和h,我们可以先求出在高度和宽度上缩放的比例。这样在resize的时候可以指定fx和fy的缩放比例了。
然后针对标注点做同样的缩放比例即可,代码如下所示。
im = cv2.imread(input_images_path + image)
img = im.copy()
h, w = img.shape[:2]
# 放大或缩小比例系数
scale_width = float(scaling_width) / float(w)
scale_height = float(scaling_height) / float(h)
scaling_image = cv2.resize(img, (0, 0), fx=scale_width, fy=scale_height)
line_list = []
with open(input_gt_path + filename + '.txt', 'r') as f:
reader = csv.reader(f)
for line in reader:
line_dict = {'x1': 0, 'y1': 0, 'x2': 0, 'y2': 0, 'x3': 0, 'y3': 0, 'x4': 0, 'y4': 0, 'label': ''}
label = line[-1]
x1, y1, x2, y2, x3, y3, x4, y4 = list(map(int, line[:8]))
line_dict['x1'] = int(x1 * scale_width)
line_dict['x2'] = int(x2 * scale_width)
line_dict['x3'] = int(x3 * scale_width)
line_dict['x4'] = int(x4 * scale_width)
line_dict['y1'] = int(y1 * scale_height)
line_dict['y2'] = int(y2 * scale_height)
line_dict['y3'] = int(y3 * scale_height)
line_dict['y4'] = int(y4 * scale_height)
line_dict['label'] = label
line_list.append(line_dict)
f.close()
2 旋转
旋转主要是根据仿射矩阵进行仿射变换。我们可以首先根据需要的旋转角度计算出仿射矩阵。传递一个旋转角度值,进行计算。对图像旋转以及获得仿射矩阵的示例代码如下。
def rotate_image(image, degree):
# 逆时针旋转图像degree角度(原尺寸)
# 旋转中心为图像中心
h, w = image.shape[:2]
# 计算二维旋转的仿射变换矩阵
RotateMatrix = cv2.getRotationMatrix2D((w / 2.0, h / 2.0), degree, 1)
# print(RotateMatrix)
# 仿射变换,背景色填充为白色
rotate = cv2.warpAffine(image, RotateMatrix, (w, h), borderValue=(255, 255, 255))
return rotate, RotateMatrix
返回值中的rotate是旋转后的CV图像,RotateMatrix是仿射变换矩阵(两行三列)。我们对需要旋转的点构造一个三行一列的矩阵,这样通过矩阵的乘法获得的另一个矩阵就是我们需要的旋转变换后的点的坐标。获得旋转后的点坐标的示例代码如下所示。
for line_dict in line_list:
dict_new = {'x1': 0, 'y1': 0, 'x2': 0, 'y2': 0, 'x3': 0, 'y3': 0, 'x4': 0, 'y4': 0}
member = np.array([[float(line_dict['x1'])], [float(line_dict['y1'])], [1]], dtype=np.float32)
result = np.dot(RotateMatrix, member).astype(np.int)
dict_new['x1'] = result[0][0]
dict_new['y1'] = result[1][0]
...
变换之后的标注信息就可以直接拿来用了,很方便~