图像预处理
原始图像大小为(h,w),缩放为需要的尺寸(ih,iw),假设原始图像shape=(800,1200),缩放的尺寸为shape=(416,416),缩放比例为scale=min(ih/h,iw/w),scale的值则为0.347,则压缩之后的图像形状为
nw=w*scale,nh=h*scale。nw=416,nh=277。
对缩放后的图像需要进行填充,填充为shape=(416,416),如示例图像上下两端需要进行填充,左右两端不需要填充,灰度条的高为(416-277)/2=69。
使用labelimg标注软件标注的真实框也需要跟随缩放比例进行缩放,缩放后需要与增加的灰度条的高或者宽相加才是添加灰度条后在图像上的真实位置。
代码
def image_preprocess(image,boxes_data,target_shape,maxnum_boxes):
#boxes_data的形状为shape=(100,5),boxes_data=[[xmin,ymin,xmax,ymax,label],...]
"""目标resize尺寸"""
iw, ih = target_shape
"""原始图像尺寸"""
h, w,_= image.shape
"""计算缩放后图像的尺寸"""
scale = min(iw / w, ih / h)
nw, nh = int(scale * w), int(scale * h)
image_resized = cv.resize(image, (nw, nh))
"""
创建一张画布,画布的尺寸就是目标尺寸
fill_value=120为灰色画布
"""
image_paded = np.full(shape=[ih, iw, 3], fill_value=120)
dw, dh = (iw - nw) // 2, (ih - nh) // 2
print("dw,dh",dw,dh)
"""将缩放后的图片放在画布中央"""
image_paded[dh:nh + dh, dw:nw + dw, :] = image_resized
image_paded= (image_paded).astype(np.uint8)
box_data=np.zeros((maxnum_boxes,5))
box=boxes_data
"""
box为[xyxyl,xyxyl,...]
计算缩放后的box大小
"""
if len(box)>0:
np.random.shuffle(box)
box[:,[0,2]]=(box[:,[0,2]]*nw/w+dw).astype(np.int32)
box[:,[1,3]]=(box[:,[1,3]]*nh/h+dh).astype(np.int32)
box_data[:len(box)]=box
# 如果不需要显示一定要将以下代码注释,因为cv.waitKey会使代码暂停
xmin,ymin,xmax,ymax,label=box_data[0]
cv.rectangle(image_paded,(int(xmin), int(ymax)), (int(xmax), int(ymin)), (0, 255, 0), 1)
cv.namedWindow("image_resized",cv.WINDOW_NORMAL)
cv.imshow("image_resized",image_paded)
cv.waitKey(0)
return image_paded,box_data