调整大小和裁剪图像后找到新的(X,Y)

时间:2018-04-25 23:12:48

标签: python opencv image-processing

我有一个图像必须在边界框周围裁剪并调整为256x256。在我的原始图像中,我有一些点(x,y)位于边界框中。

这是我的原始图像,原始坐标标记为:

enter image description here

下面是裁剪结果,其中红点是正确的x,y,蓝色是我当前的结果:

enter image description here

继承人我是怎么做的:

import numpy as np
import cv2

def scaleBB(bb, scale):
    centerX = (bb[0][0] + bb[1][0]) / 2
    centerY = (bb[0][1] + bb[2][1]) / 2
    center = (centerX, centerY)
    scl_center = (centerX * scale[0], centerY * scale[1])

    p1 = scale * (bb[0] - center) + scl_center
    p2 = scale * (bb[1] - center) + scl_center
    p3 = scale * (bb[2] - center) + scl_center
    p4 = scale * (bb[3] - center) + scl_center

    return np.array([p1, p2, p3, p4])


def expandBB(scaledBB, size):
    bbw = np.abs(scaledBB[0][0] - scaledBB[1][0])
    bbh = np.abs(scaledBB[0][1] - scaledBB[2][1])

    expandX = (size[0] - bbw) / 2
    expandY = (size[1] - bbh) / 2

    p1 = scaledBB[0] + (-expandX, -expandY)
    p2 = scaledBB[1] + (+expandX, -expandY)
    p3 = scaledBB[2] + (+expandX, +expandY)
    p4 = scaledBB[3] + (+expandX, +expandY)

    return np.array([p1, p2, p3, p4])

def recalculate_joints_points(oldX, oldY, newX, newY, joints):
    R_x = newX / oldX
    R_y = newY / oldY

    new_joints = []

    for index, joint in enumerate(joints):
        x = joint[0]
        y = joint[1]

        n_x = round(R_x * x)
        n_y = round(R_y * y)

        print(R_x, R_y, x, y, n_x, n_y)

        new_joints.append([n_x, n_y])

    return np.array(new_joints)

def cropAndResizeImage(label, bb):
    img_path = "original.jpg"
    # downscale
    image = cv2.imread(img_path)
    # orgSize = image.shape[:2]
    label = label
    bb = bb
    print(bb)
    dim = int(256 / 2)
    # define the target height of the bounding box
    targetHeight = 200.0
    w = np.abs(bb[0][0] - bb[1][0])
    h = np.abs(bb[0][1] - bb[2][1])
    targetScale = targetHeight / h
    print(targetScale)

    scaledImage = cv2.resize(image, (0, 0), fx=targetScale, fy=targetScale)
    scaledBB = scaleBB(bb, (targetScale, targetScale))
    cropRegion = expandBB(scaledBB, (256, 256))
    print(scaledBB)

    print(cropRegion)

    startX = int(cropRegion[0][0] + dim)
    startY = int(cropRegion[0][1] + dim)
    endX = startX + 256  # cropRegion[2][0] + dim
    endY = startY + 256  #cropRegion[2][1] + dim
    print(startX, startY, endX, endY)

    padded_image = np.pad(scaledImage, ((dim, dim), (dim, dim), (0, 0)), mode='constant')
    croppedImage = padded_image[startY:endY, startX:endX]

    # new label
    print(image.shape, croppedImage.shape)
    oldWidth = image.shape[1]
    oldHeight = image.shape[0]
    newWidth = 256 + dim
    newHeight = 256 + dim

    out_label = recalculate_joints_points(oldWidth, oldHeight, newWidth, newHeight, label)

    return [croppedImage, out_label]        

def main():
    labels = np.array([[1214, 598],
                        [1169, 424],
                        [1238, 273],
                        [1267, 285],
                        [1212, 453],
                        [1229, 622],
                        [1253, 279],
                        [1173, 114],
                        [1171, 113],
                        [1050, 60],
                        [1106, 143],
                        [1140, 100],
                        [1169, 80],
                        [1176, 148],
                        [1152, 280],
                        [1087, 391]])

    bb = np.array([[1050, 60],
                    [1267, 60],
                    [1267, 622],
                    [1050, 622]])

    img, label = cropAndResizeImage(labels, bb)

    for point in label:
        print(point)
        x,y = point
        cv2.circle(img,(int(x),int(y)),5,(255,0,0),-11)

    cv2.imshow("cropped", img)
    cv2.waitKey()    

if __name__ == '__main__':
    main()

据我所知,要获得新的(x,y),你必须计算比率(比例因子中的大小差异),但它似乎仍然没有。任何帮助表示赞赏。

编辑1:

使用newHeight / Width只生成256个图像:

enter image description here

*编辑2:

使用@ChrisH的解决方案非常完美但仍然有点偏离:

enter image description here

3 个答案:

答案 0 :(得分:4)

这是一个直接从原始坐标转换为裁剪和缩放坐标的函数。您可以使用此

直接跳过所有其他功能并转换点
def getNewCoords(x,y):
    bbUpperLeftX = bb[0][0]
    bbUpperLeftY = bb[0][1] 
    bbLowerRightX = bb[2][0] 
    bbLowerRightY = bb[2][1] 

    sizeX = bbLowerRightX - bbUpperLeftX
    sizeY =  bbLowerRightY - bbUpperLeftY

    sizeMax = max(sizeX, sizeY)

    centerX = (bbLowerRightX + bbUpperLeftX)/2
    centerY = (bbLowerRightY + bbUpperLeftY)/2

    offsetX = (centerX-sizeMax/2)*256/sizeMax
    offsetY = (centerY-sizeMax/2)*256/sizeMax

    x = x * 256/sizeMax - offsetX 
    y = y * 256/sizeMax - offsetY
    return (x,y)

答案 1 :(得分:1)

自定义

endX = startX + 256
endY = startY + 256

将输出图像设为

croppedImage = padded_image[startY:endY, startX:endX]

新的宽度和高度不应该是256吗?而是将它们定义为

newWidth = 256 + dim
newHeight = 256 + dim

我认为这里不需要dim

答案 2 :(得分:0)

您可以使用 augmentit 来完成任务。

    pip install augmentit

文档 链接:https://github.com/sandesha-hegde/augmentit