簡體   English   中英

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

[英]Find new (X,Y) after resizing and cropping image

我有一個必須圍繞邊界框裁剪並調整為 256x256 的圖像。 在我的原始圖像中,我在邊界框中有許多點 (x,y)。

這是我的原始圖像,標有我的原始坐標:

在此處輸入圖片說明

這是裁剪后的結果,其中紅色點是正確的 x,y,藍色點是我當前的結果:

在此處輸入圖片說明

這是我的做法:

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 生成此圖像:

在此處輸入圖片說明

*編輯2:

使用@ChrisH 的解決方案非常完美,但仍有一點點:

在此處輸入圖片說明

這是一個函數,它將直接從原始坐標轉換為裁剪和縮放的坐標。 您可以跳過所有其他功能並直接使用此轉換點

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)

既然你定義

endX = startX + 256
endY = startY + 256

並使輸出圖像為

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

新的寬度和高度不應該是 256 嗎? 相反,您將它們定義為

newWidth = 256 + dim
newHeight = 256 + dim

我認為這里不需要dim

您可以使用Augmentit來完成任務。

    pip install augmentit

文檔鏈接: https : //github.com/sandesha-hegde/augmentit

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM