目录
1. 比例缩放
2. 使用letterbox
目标检测训练中,我们的数据集尺寸大部分时侯都是不符合网络输入的,需要对尺寸进行修改,下面我介绍两种常用尺寸变换方法:
这种方法就是简单的对图片尺寸进行比例缩放,一般使用cv2.resize()对图片进行缩放,然后计算长宽缩放比例,再通过比例来缩放标注的目标框尺寸。具体代码如下:
def read_and_resize_picture(img_path, img_boxes):
"""
:function:读取图片,并缩放图片尺寸到指定尺寸,同时修改目标框尺寸
:param img_path: 单张图片路径
:param img_boxes: 对应图片目标框[[xmin,ymin,xmax,ymax],...,[xmin,ymin,xmax,ymax]]
:return:图片(已经读取啦),修改的目标框
"""
img = cv2.imread(img_path,flags=1)
height, width = img.shape[0:2]
if height == 416 and width == 416:
return img, img_boxes
else:
h_s = height / 416.
w_s = width / 416.
# box = img_boxes
# 将原图resize成300,300
img_resize = cv2.resize(img, dsize=(416, 416), interpolation=cv2.INTER_LINEAR)
# imgs.append(img_resize)
img_boxes[:, 0:3:2] = img_boxes[:, 0:3:2] / w_s
img_boxes[:, 1:4:2] = img_boxes[:, 1:4:2] / h_s
# boxes.append(box)
return img_resize, img_boxes
这种方法修改图片尺寸方便,但是会改变图片特征
先对图片填充黑边,使图片尺寸为正方形,然后再缩放,这样不会改变图片尺寸,代码如下:
import numpy as np
import cv2
import math
def cv2_letterbox_image(image, expected_size, box):
"""
function:使用letterbox填充并修改图片尺寸
:param image: 原图
:param expected_size: 想要修改后的尺寸
:param box: 原图目标框
:return: 修改后的图片,目标框
"""
ih, iw = image.shape[0:2]
ew, eh = expected_size
scale = min(eh / ih, ew / iw)
nh = int(ih * scale)
nw = int(iw * scale)
for i in range(4):
box[i] = box[i] * scale
image = cv2.resize(image, (nw, nh), interpolation=cv2.INTER_CUBIC)
top = (eh - nh) // 2
box[1] = box[1] + top
box[3] = box[3] + top
bottom = eh - nh - top
left = (ew - nw) // 2
box[0] = box[0] + left
box[2] = box[2] + left
right = ew - nw - left
new_img = cv2.copyMakeBorder(image, top, bottom, left, right, cv2.BORDER_CONSTANT)
return new_img, box
def cv2_deletterbox_image(image, current_size, box):
"""
function:去除图像灰边,并还原目标框尺寸
:param image: 原图
:param current_size: 当前图片尺寸(网络输入尺寸)
:param box: 网络输入尺寸下的目标框
:return: 匹配原图的目标框
"""
ih, iw = image.shape[0:2]
ew, eh = current_size
scale = min(eh / ih, ew / iw)
nh = int(ih * scale)
nw = int(iw * scale)
top = (eh - nh) // 2
box[1] = box[1] - top
box[3] = box[3] - top
left = (ew - nw) // 2
box[0] = box[0] - left
box[2] = box[2] - left
for i in range(4):
box[i] = box[i] / scale
return box
def view_1():
box = np.array([147, 336, 402, 437])
ptr1 = (box[0], box[1])
ptr2 = (box[2], box[3])
color = (0, 0, 255)
path = "YOLOV3_high/data/val/JPEG/image_1.jpg"
img = cv2.imread(path)
dst_img, box_new = cv2_letterbox_image(img, (415, 415), box)
cv2.rectangle(img, ptr1, ptr2, color, 2)
cv2.imshow('src_img', img)
cv2.rectangle(dst_img, (box_new[0], box_new[1]), (box_new[2], box_new[3]), color, 2)
cv2.imshow("dst_img", dst_img)
# cv2.imwrite("pred_img.jpg",dst_img)
cv2.waitKey(0)
def view_2():
box = np.array([147, 336, 402, 437])
ptr1 = (box[0], box[1])
ptr2 = (box[2], box[3])
color = (0, 0, 255)
path = "YOLOV3_high/data/val/JPEG/image_1.jpg"
img = cv2.imread(path)
img_src = img.copy()
dst_img, box_new = cv2_letterbox_image(img, (416, 416), box)
cv2.rectangle(img, ptr1, ptr2, color, 2)
cv2.imshow('src_img', img)
cv2.rectangle(dst_img, (box_new[0], box_new[1]), (box_new[2], box_new[3]), color, 2)
cv2.imshow("dst_img", dst_img)
box_src = cv2_deletterbox_image(img_src, (416,416), box_new)
cv2.rectangle(img_src, (box_src[0], box_src[1]), (box_src[2], box_src[3]), color, 2)
cv2.imshow("img_src", img_src)
cv2.waitKey(0)
if __name__ == "__main__":
# view_1()
view_2()