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