如何使用OpenCV2.0和Python2.6调整图像大小

220

我想使用OpenCV2.0和Python2.6来显示调整大小的图像。我使用并采用了这个例子,但不幸的是,这段代码是针对OpenCV2.1编写的,似乎在2.0上无法工作。这是我的代码:

import os, glob
import cv

ulpath = "exampleshq/"

for infile in glob.glob( os.path.join(ulpath, "*.jpg") ):
    im = cv.LoadImage(infile)
    thumbnail = cv.CreateMat(im.rows/10, im.cols/10, cv.CV_8UC3)
    cv.Resize(im, thumbnail)
    cv.NamedWindow(infile)
    cv.ShowImage(infile, thumbnail)
    cv.WaitKey(0)
    cv.DestroyWindow(name)

由于我无法使用

cv.LoadImageM

我使用了

cv.LoadImage

但在其他应用程序中没有问题,可以使用Matlab。然而,cv.iplimage没有属性行、列或大小。有人能给我一个提示,如何解决这个问题吗?


8
如果有任何一个答案是正确的,请标记它,这将帮助其他人。 - Michał
5个回答

432

如果您想使用CV2,您需要使用resize函数。

例如,以下代码会将两个轴都缩小一半:

small = cv2.resize(image, (0,0), fx=0.5, fy=0.5) 

这将调整图像大小为100列(宽度)和50行(高度):

resized_image = cv2.resize(image, (100, 50)) 

另一个选择是使用scipy模块,方法如下:

small = scipy.misc.imresize(image, 0.5)

在这些函数的文档中( cv2.resize, scipy.misc.imresize )中,显然有更多的选项可供阅读。


更新:
根据SciPy文档

imresize在SciPy 1.0.0中已被弃用,将在1.2.0中删除。
请使用skimage.transform.resize代替。

注意,如果你想要按比例缩放,你实际上可能想使用skimage.transform.rescale


1
resize()函数会使图片失去自身的信息吗? - user4772964
16
是的,你不能在不丢失信息的情况下缩小图像尺寸。 - Rafael_Espericueta
1
OpenCV (每张图像0.05毫秒)的实现似乎比Scipy(每张图像0.33毫秒)的实现快得多。我使用双线性插值将210x160x1大小的图像调整为84x84x1大小的图像。 - gizzmole
@gizzmole 有趣的见解。我没有测试实现的效率,也没有比较结果 - 因此最终结果可能也会略有不同。你测试过调整大小后的图像是否按位匹配吗? - emem
1
感谢指出resize函数接受的参数是(W * H),而cv2打印的是(H * W)。 - Shivam Kotwalia
显示剩余5条评论

83

示例:将图像大小加倍

有两种方法可以调整图像大小,可以指定新的大小:

  1. 手动指定;

    height, width = src.shape[:2]

    dst = cv2.resize(src, (2*width, 2*height), interpolation=cv2.INTER_CUBIC)

  2. 通过缩放因子。

    dst = cv2.resize(src, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC), 其中 fx 是水平轴上的缩放因子,fy 是垂直轴上的缩放因子。

要缩小图像,最好使用 INTER_AREA 插值,而要放大图像,则最好使用 INTER_CUBIC(慢)或 INTER_LINEAR(较快但仍然效果不错)。

示例:缩小图像以适应最大高度/宽度(保持长宽比)

import cv2

img = cv2.imread('YOUR_PATH_TO_IMG')

height, width = img.shape[:2]
max_height = 300
max_width = 300

# only shrink if img is bigger than required
if max_height < height or max_width < width:
    # get scaling factor
    scaling_factor = max_height / float(height)
    if max_width/float(width) < scaling_factor:
        scaling_factor = max_width / float(width)
    # resize image
    img = cv2.resize(img, None, fx=scaling_factor, fy=scaling_factor, interpolation=cv2.INTER_AREA)

cv2.imshow("Shrinked image", img)
key = cv2.waitKey()

使用cv2与您的代码

import cv2 as cv

im = cv.imread(path)

height, width = im.shape[:2]

thumbnail = cv.resize(im, (round(width / 10), round(height / 10)), interpolation=cv.INTER_AREA)

cv.imshow('exampleshq', thumbnail)
cv.waitKey(0)
cv.destroyAllWindows()

您使用缩放因子的解决方案在cv2.resize()上返回错误,提示“src不是numpy数组,也不是标量”。请指导? - BenP
你是否已经执行了这条指令:src = cv2.imread('YOUR_PATH_TO_IMG') 并将 'YOUR_PATH_TO_IMG' 修改为你自己图片的路径? - João Cartucho
cv2.resize 是否自动使用填充?当期望的输出大小为 (width/10, height/10) 时,创建的窗口大小是多少? - seralouk
@makaros,你会得到一张图像,宽度和高度都缩小了10倍。 - João Cartucho
@JoãoCartucho 是的,我明白这一点。但是当使用nearest_neighbors时,幕后应该应用一个窗口。这就是我所问的。 - seralouk
最近邻是什么? - João Cartucho

9
您可以使用GetSize函数获取这些信息,cv.GetSize(im)将返回一个元组,其中包含图像的宽度和高度。您还可以使用im.depth和img.nChan获取更多信息。
要调整图像大小,我会使用稍微不同的过程,而不是使用矩阵,而是使用另一个图像。尝试使用相同类型的数据进行操作更好。
size = cv.GetSize(im)
thumbnail = cv.CreateImage( ( size[0] / 10, size[1] / 10), im.depth, im.nChannels)
cv.Resize(im, thumbnail)

希望这能帮到你;) Julien

8
这是一个函数,可以按照所需的宽度或高度进行图像的放大或缩小,同时保持长宽比。
# Resizes a image and maintains aspect ratio
def maintain_aspect_ratio_resize(image, width=None, height=None, inter=cv2.INTER_AREA):
    # Grab the image size and initialize dimensions
    dim = None
    (h, w) = image.shape[:2]

    # Return original image if no need to resize
    if width is None and height is None:
        return image

    # We are resizing height if width is none
    if width is None:
        # Calculate the ratio of the height and construct the dimensions
        r = height / float(h)
        dim = (int(w * r), height)
    # We are resizing width if height is none
    else:
        # Calculate the ratio of the width and construct the dimensions
        r = width / float(w)
        dim = (width, int(h * r))

    # Return the resized image
    return cv2.resize(image, dim, interpolation=inter)

使用方法

import cv2

image = cv2.imread('1.png')
cv2.imshow('width_100', maintain_aspect_ratio_resize(image, width=100))
cv2.imshow('width_300', maintain_aspect_ratio_resize(image, width=300))
cv2.waitKey()

使用此示例图像

输入图片描述

只需缩小到width=100(左)或放大到width=300(右)

输入图片描述 输入图片描述


7
def rescale_by_height(image, target_height, method=cv2.INTER_LANCZOS4):
    """Rescale `image` to `target_height` (preserving aspect ratio)."""
    w = int(round(target_height * image.shape[1] / image.shape[0]))
    return cv2.resize(image, (w, target_height), interpolation=method)

def rescale_by_width(image, target_width, method=cv2.INTER_LANCZOS4):
    """Rescale `image` to `target_width` (preserving aspect ratio)."""
    h = int(round(target_width * image.shape[0] / image.shape[1]))
    return cv2.resize(image, (target_width, h), interpolation=method)

cv2.resize 函数是否自动使用填充?使用 (w, target_height) 参数创建的窗口大小是多少? - seralouk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接