如何重新缩放图像坐标的信息以在相似图像的缩放版本上工作

时间:2018-12-01 13:50:15

标签: python image opencv yolo

我用yolov3来检测416x416大小的帧中的对象。我使用边界框信息在该1920x1080图像上绘制了框。

但是由于图片太小,我无法正确看到它,因此我使用了暗淡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 的同一帧。我想缩放边界框信息和x,y坐标,以使其缩放到高暗淡的图片,但是我无法正确缩放它。

显然,信息已经消失了。

注意!在传递帧之前,我使用此方法将帧的大小从1920,1080调整为416,416

{{1}}

如果有人帮助我编写脚本,该脚本将重新缩放yolo预测的x,y,w,h信息,以便我可以在图像上正确绘制准确的方框。

1 个答案:

答案 0 :(得分:1)

您的重新缩放过程未考虑顶部的零填充区域。在乘以缩放比例之前,请先移除顶部的零垫,这样您便可以获得正确的结果。

以下是所有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)