如何重新缩放图像坐标的信息以处理相似图像的缩放版本
How to re scale information of an image coordinates to work on a scaled version of similar image
我使用 yolov3 来检测尺寸为 416x416
的帧中的物体。我使用该边界框信息在该 416x416
图像上绘制框。
但由于图片太小,看不清楚,所以我用了同样的框架,但有暗淡1920x1080
。我想缩放边界框信息和 x、y 坐标,使其缩放到高暗图片,但我无法正确缩放它。
显然信息有误。
注意!在通过帧之前,我使用这种方法将帧的大小从 1920,1080 调整为 416,416
def letterbox_resize(img, size=(resized_image_size,resized_image_size), padColor=0):
h, w = img.shape[:2]
sh, sw = size
# interpolation method
if h > sh or w > sw: # shrinking image
interp = cv2.INTER_AREA
else: # stretching image
interp = cv2.INTER_CUBIC
# aspect ratio of image
aspect = w/h # if on Python 2, you might need to cast as a float: float(w)/h
# compute scaling and pad sizing
if aspect > 1: # horizontal image
new_w = sw
new_h = np.round(new_w/aspect).astype(int)
pad_vert = (sh-new_h)/2
pad_top, pad_bot = np.floor(pad_vert).astype(int), np.ceil(pad_vert).astype(int)
pad_left, pad_right = 0, 0
elif aspect < 1: # vertical image
new_h = sh
new_w = np.round(new_h*aspect).astype(int)
pad_horz = (sw-new_w)/2
pad_left, pad_right = np.floor(pad_horz).astype(int), np.ceil(pad_horz).astype(int)
pad_top, pad_bot = 0, 0
else: # square image
new_h, new_w = sh, sw
pad_left, pad_right, pad_top, pad_bot = 0, 0, 0, 0
# set pad color
if len(img.shape) is 3 and not isinstance(padColor, (list, tuple, np.ndarray)): # color image but only one color provided
padColor = [padColor]*3
# scale and pad
scaled_img = cv2.resize(img, (new_w, new_h), interpolation=interp)
scaled_img = cv2.copyMakeBorder(scaled_img, pad_top, pad_bot, pad_left, pad_right, borderType=cv2.BORDER_CONSTANT, value=padColor)
return scaled_img
如果有人帮我写一个脚本来重新缩放 yolo 预测的 x、y、w、h 信息,这样我就可以在图像上正确地绘制准确的框。
您的重新缩放过程没有考虑顶部的零填充区域。在乘以比例比之前删除顶部的零垫,你应该能够得到正确的结果。
这是所有 3 种情况的示例代码,其中边界框是与 YOLO 结果对应的点。
def boundBox_restore(boundingbox, ori_size=(ori_image_width,ori_image_height), resized_size=(resized_image_size,resized_image_size)):
h, w = ori_size
sh, sw = resized_size
scale_ratio = w / sw
ox,oy,ow,oh = boundingbox
# aspect ratio of image
aspect = w/h # if on Python 2, you might need to cast as a float: float(w)/h
# compute scaling and pad sizing
if aspect > 1: # horizontal image
new_w = sw
new_h = np.round(new_w/aspect).astype(int)
pad_vert = (sh-new_h)/2
pad_top, pad_bot = np.floor(pad_vert).astype(int), np.ceil(pad_vert).astype(int)
pad_left, pad_right = 0, 0
elif aspect < 1: # vertical image
new_h = sh
new_w = np.round(new_h*aspect).astype(int)
pad_horz = (sw-new_w)/2
pad_left, pad_right = np.floor(pad_horz).astype(int), np.ceil(pad_horz).astype(int)
pad_top, pad_bot = 0, 0
else: # square image
new_h, new_w = sh, sw
pad_left, pad_right, pad_top, pad_bot = 0, 0, 0, 0
# remove pad
ox = ox - pad_left
oy = oy - pad_top
# rescale
ox = ox * scale_ratio
oy = oy * scale_ratio
ow = ow * scale_ratio
oh = oh * scale_ratio
return (ox,oy,oh,ow)
我使用 yolov3 来检测尺寸为 416x416
的帧中的物体。我使用该边界框信息在该 416x416
图像上绘制框。
但由于图片太小,看不清楚,所以我用了同样的框架,但有暗淡1920x1080
。我想缩放边界框信息和 x、y 坐标,使其缩放到高暗图片,但我无法正确缩放它。
显然信息有误。
注意!在通过帧之前,我使用这种方法将帧的大小从 1920,1080 调整为 416,416
def letterbox_resize(img, size=(resized_image_size,resized_image_size), padColor=0):
h, w = img.shape[:2]
sh, sw = size
# interpolation method
if h > sh or w > sw: # shrinking image
interp = cv2.INTER_AREA
else: # stretching image
interp = cv2.INTER_CUBIC
# aspect ratio of image
aspect = w/h # if on Python 2, you might need to cast as a float: float(w)/h
# compute scaling and pad sizing
if aspect > 1: # horizontal image
new_w = sw
new_h = np.round(new_w/aspect).astype(int)
pad_vert = (sh-new_h)/2
pad_top, pad_bot = np.floor(pad_vert).astype(int), np.ceil(pad_vert).astype(int)
pad_left, pad_right = 0, 0
elif aspect < 1: # vertical image
new_h = sh
new_w = np.round(new_h*aspect).astype(int)
pad_horz = (sw-new_w)/2
pad_left, pad_right = np.floor(pad_horz).astype(int), np.ceil(pad_horz).astype(int)
pad_top, pad_bot = 0, 0
else: # square image
new_h, new_w = sh, sw
pad_left, pad_right, pad_top, pad_bot = 0, 0, 0, 0
# set pad color
if len(img.shape) is 3 and not isinstance(padColor, (list, tuple, np.ndarray)): # color image but only one color provided
padColor = [padColor]*3
# scale and pad
scaled_img = cv2.resize(img, (new_w, new_h), interpolation=interp)
scaled_img = cv2.copyMakeBorder(scaled_img, pad_top, pad_bot, pad_left, pad_right, borderType=cv2.BORDER_CONSTANT, value=padColor)
return scaled_img
如果有人帮我写一个脚本来重新缩放 yolo 预测的 x、y、w、h 信息,这样我就可以在图像上正确地绘制准确的框。
您的重新缩放过程没有考虑顶部的零填充区域。在乘以比例比之前删除顶部的零垫,你应该能够得到正确的结果。
这是所有 3 种情况的示例代码,其中边界框是与 YOLO 结果对应的点。
def boundBox_restore(boundingbox, ori_size=(ori_image_width,ori_image_height), resized_size=(resized_image_size,resized_image_size)):
h, w = ori_size
sh, sw = resized_size
scale_ratio = w / sw
ox,oy,ow,oh = boundingbox
# aspect ratio of image
aspect = w/h # if on Python 2, you might need to cast as a float: float(w)/h
# compute scaling and pad sizing
if aspect > 1: # horizontal image
new_w = sw
new_h = np.round(new_w/aspect).astype(int)
pad_vert = (sh-new_h)/2
pad_top, pad_bot = np.floor(pad_vert).astype(int), np.ceil(pad_vert).astype(int)
pad_left, pad_right = 0, 0
elif aspect < 1: # vertical image
new_h = sh
new_w = np.round(new_h*aspect).astype(int)
pad_horz = (sw-new_w)/2
pad_left, pad_right = np.floor(pad_horz).astype(int), np.ceil(pad_horz).astype(int)
pad_top, pad_bot = 0, 0
else: # square image
new_h, new_w = sh, sw
pad_left, pad_right, pad_top, pad_bot = 0, 0, 0, 0
# remove pad
ox = ox - pad_left
oy = oy - pad_top
# rescale
ox = ox * scale_ratio
oy = oy * scale_ratio
ow = ow * scale_ratio
oh = oh * scale_ratio
return (ox,oy,oh,ow)