我需要在X和Y方向拉伸图像,但同时保持目标图像尺寸为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)
我将scale数组用于x和y比例因子:scales = [(1,2),(2,1)]
我希望最终图像应该是300x300,并且应该包含图像的缩放版本。
谢谢!!
答案 0 :(得分:1)
如果您只想将其用于显示目的,最简单的方法是在裁剪后的图像上使用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)
将在窗口具有原始图像大小的窗口内显示缩放图像。通过裁剪图像的右侧和顶部(图像锚定在窗口的左下角),即使您缩放图像也可以使用此功能。请参阅输出窗口:
但是,如果您希望将其保存到另一个矩阵中,则需要使用图像外部的任何颜色填充图像。最简单的方法是使用该颜色创建矩阵,然后创建与缩放图像大小相同的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
:
如果你希望它显示在中心,你可以做一些简单的计算来获得图像的中心,然后将缩放图像的宽度和高度的一半移动到起始位置。
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)
这会将缩放后的图像放在填充矩阵的中心:
仅当图像比原始图像缩小小时才会起作用,因为您将较小的图像放入较大的空白矩阵中。但是,如果要允许更大的缩放比例,那么此时您需要裁剪。您可以从缩放图像中裁剪与原始图像大小相同的区域。但是,如果比例在一个维度中大于1而在另一个维度中小于1,则您需要同时裁剪和 pad。我将其分为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)
在一个方向上有一个较大的拉伸而在另一个方向上的比例较小,这将导致图像显示如下: