gpt4 book ai didi

python - 如何沿 X 和 Y 轴缩放图像并裁剪到特定的高度和宽度?

转载 作者:行者123 更新时间:2023-12-02 17:41:21 25 4
gpt4 key购买 nike

我需要在 X 和 Y 方向拉伸(stretch)图像,但同时保持目标图像大小为 300x300。我正在使用 Open CV。每次我缩放图像然后调整它的大小时,我都会失去缩放,它看起来和我喂它缩放的图像一样。我该如何做到这一点?

这是缩放的代码

def scale(infile,outfile,scx,scy):
img = cv2.imread(infile,0)
height, width = img.shape[:2]
#aspectRatio = width / height
rows,cols = img.shape
if scx > 1 or scy > 1:
scimg = cv2.resize(img,None, fx = scx, fy = scy, interpolation = cv2.INTER_LINEAR)
else:
scimg = cv2.resize(img,None, fx = scx, fy = scy, interpolation = cv2.INTER_CUBIC)

#cheight, cwidth = scimg.shape[:2]
#area = cheight * cwidth
#nheight = math.sqrt(area / aspectRatio)
#nwidth = nheight * aspectRatio
#cv2.resize(scimg,((int)(nwidth), (int)(nheight)), interpolation = cv2.INTER_CUBIC)
#top = (int) (0.2*rows)
#bottom = (int) (0.2*rows)
#left = (int) (0.2*cols)
#right = (int) (0.2*cols);
#cv2.copyMakeBorder(scimg,top,left,bottom,right,cv2.BORDER_CONSTANT,value=255)
cv2.imwrite(outfile,scimg)

我将 scales 数组用于 x 和 y 比例因子: scales = [(1,2),(2,1)]我希望最终图像应该是 300x300 并且应该包含图像的缩放版本。
谢谢!!

最佳答案

如果您只是为了显示目的,最简单的方法是使用 cv2.imshow()在您裁剪的图像上并使用 cv2.resizeWindow() 将窗口大小设置为原始图像大小。

import cv2
import numpy as np

img = cv2.imread('lena.png')
h, w = img.shape[:2]
scale = (0.6, 0.4) # define your scale
scaled_img = cv2.resize(img, None, fx=scale[0], fy=scale[1]) # scale image

cv2.namedWindow("Scaled image", cv2.WINDOW_NORMAL) # create a resizeable window
cv2.imshow("Scaled image", scaled_img) # display the image in the window
cv2.resizeWindow("Scaled image", w, h) # resize the window
cv2.waitKey(0)

将在窗口具有原始图像大小的窗口内显示缩放图像。即使您通过裁剪图像的右侧和顶部(图像锚定在窗口的左下角)来放大图像,这也将起作用。查看输出窗口:

Scaled Lena display

但是,如果您希望将其保存到另一个矩阵中,那么您需要在图像之外使用您想要的任何颜色填充图像。最简单的方法是使用该颜色创建一个矩阵,然后创建一个与缩放图像大小相同的 ROI,并将缩放图像放置在 ROI 内。
import cv2
import numpy as np

img = cv2.imread('lena.png')
scale = (0.6, 0.4) # define your scale
scaled_img = cv2.resize(img, None, fx=scale[0], fy=scale[1]) # scale image

sh, sw = scaled_img.shape[:2] # get h, w of scaled image
padded_scaled = np.zeros(img.shape, dtype=np.uint8)
padded_scaled[0:sh, 0:sw] = scaled_img

cv2.imshow("Scaled image", padded_scaled)
cv2.waitKey(0)

这会将缩放后的图像放在 0,0在目的地 padded_scaled :

Padded and scaled image

如果你希望它显示在中心,你可以做一些简单的计算来获得图像的中心,然后将缩放图像的宽度和高度的一半移动到起始位置。
import cv2
import numpy as np

img = cv2.imread('lena.png')
scale = (0.6, 0.4) # define your scale
scaled_img = cv2.resize(img, None, fx=scale[0], fy=scale[1]) # scale image

h, w = img.shape[:2] # get h, w of image
sh, sw = scaled_img.shape[:2] # get h, w of scaled image
center_y = int(h/2 - sh/2)
center_x = int(w/2 - sw/2)
padded_scaled = np.zeros(img.shape, dtype=np.uint8) # using img.shape to obtain #channels
padded_scaled[center_y:center_y+sh, center_x:center_x+sw] = scaled_img

cv2.imshow("Scaled image", padded_scaled)
cv2.waitKey(0)

这会将缩放后的图像放置在填充矩阵的中心:

Scaled and centered image

这仅在图像缩放小于原始图像时才有效,因为您将较小的图像放入较大的空白矩阵中。但是,如果您想允许更大的缩放比例,那么此时您需要进行裁剪。您可以从与原始图像大小相同的缩放图像中裁剪一个区域。但是,如果比例在一个维度上大于 1,而在另一个维度上小于 1,则需要同时裁剪和填充。我把它分成 if 的两个部分语句:首先创建一个最多为图像大小的结果,如有必要,通过裁剪,然后填充,如果它更小。
import cv2
import numpy as np

img = cv2.imread('lena.png')
scale_x, scale_y = 13, .3 # define your scale
h, w = img.shape[:2] # get h, w of image

if scale_x > 1 or scale_y > 1:

scaled_img = cv2.resize(img, None, fx=scale_x, fy=scale_y, interpolation = cv2.INTER_LINEAR) # scale image
sh, sw = scaled_img.shape[:2] # get h, w of scaled image
center_y = int(sh/2 - h/2)
center_x = int(sw/2 - w/2)
cropped = scaled_img[center_y:center_y+h, center_x:center_x+w]

result = cropped

elif scale_x > 0 or scale_y > 0:
scaled_img = cv2.resize(img, None, fx=scale_x, fy=scale_y, interpolation = cv2.INTER_CUBIC) # scale image
result = scaled_img

else: # scale_x or scale_y is negative
print("Scales must be greater than 0; returning the original image.")
result = img

if result.shape < img.shape: # one of the dimensions was scaled smaller, so need to pad
sh, sw = result.shape[:2] # get h, w of cropped, scaled image
center_y = int(h/2 - sh/2)
center_x = int(w/2 - sw/2)
padded_scaled = np.zeros(img.shape, dtype=np.uint8)
padded_scaled[center_y:center_y+sh, center_x:center_x+sw] = result
result = padded_scaled

cv2.imshow("Scaled padded/cropped image", result)
cv2.waitKey(0)

一个方向的拉伸(stretch)较大而另一个方向的比例较小,这将导致图像显示如下:

Scaled, cropped, and padded image

关于python - 如何沿 X 和 Y 轴缩放图像并裁剪到特定的高度和宽度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44401085/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com