[英]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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.