Найти новый (X, Y) после изменения размера и обрезки изображения - PullRequest
0 голосов
/ 26 апреля 2018

У меня есть изображение, которое нужно обрезать вокруг ограничительной рамки и изменить его размер до 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

Ответы [ 2 ]

0 голосов
/ 26 апреля 2018

Вот функция, которая будет переводить непосредственно из исходных координат в обрезанные и масштабированные координаты.Вы можете пропустить все другие функции и преобразовать точки напрямую с помощью этого

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)
0 голосов
/ 26 апреля 2018

Поскольку вы определяете

endX = startX + 256
endY = startY + 256

и делаете выходное изображение как

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

Разве новые ширина и высота не должны быть 256?вместо этого вы определяете их как

newWidth = 256 + dim
newHeight = 256 + dim

Я думаю, что dim здесь не нужно

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...