Как изменить размер изображения с OpenCV2.0 и Python2.6

163

Я хочу использовать OpenCV2.0 и Python2.6 для отображения изображений с измененным размером. Я использовал и принял пример по адресу http://opencv.willowgarage.com/documentation/python/cookbook.html, но, к сожалению, этот код предназначен для 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

вместо этого, что не было проблемой в других приложениях. Тем не менее, у cv.iplimage нет строк атрибутов, столбцов или размера. Кто-нибудь может дать мне подсказку, как решить эту проблему? Спасибо.

Бастиан
источник
4
Если какой-либо из ответов был верным, отметьте его, так как это поможет другим.
Михал

Ответы:

343

Если вы хотите использовать 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 () не заставляет картинку терять информацию о себе?
8
Да, вы не можете уменьшить размер изображения без потери информации.
Rafael_Espericueta
1
Реализация opencv (0,05 мс на изображение), кажется, намного быстрее, чем реализация Scipy (0,33 мс изображение). Я изменил размеры с 210x160x1 до 84x84x1 с билинейной интерполяцией.
gizzmole
@gizzmole Интересное понимание. Я не проверял эффективность реализаций и не сравнивал результаты - поэтому конечный результат также может немного отличаться. Вы тестировали, чтобы увидеть, как измененные изображения соответствуют битам?
ЕМЕМ
Спасибо за указание на то, что функция изменения размера принимает (W * H), тогда как cv2 печатает как (H * W)
Шивам Котвалия
59

Пример удвоения размера изображения

Есть два способа изменить размер изображения. Новый размер может быть указан:

  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 - это не пустой массив и не скаляр». пожалуйста, порекомендуйте?
BenP
Вы сделали: src = cv2.imread('YOUR_PATH_TO_IMG')и отредактировали 'YOUR_PATH_TO_IMG', указав путь к своему изображению?
Жоау Картучо
делает cv2.resizeавтоматически использует обивку? каков размер окна, созданного с использованием желаемого размера вывода (width/10, height/10)?
Сералук
@makaros вы получаете изображение, которое в 10 раз меньше и по ширине, и по высоте
Жуан Картучо
@ JoãoCartucho Да, я понимаю это. Но когда используется near_neighbors, тогда окно должно применяться за кулисами. Это то, что я спрашиваю ..
seralouk
8

Вы можете использовать функцию 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

jlengrand
источник
6
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)
AndyP
источник
делает cv2.resizeавтоматически использует обивку? Каков размер окна, созданного с использованием (w, target_height)аргументов?
Сералук
4

Вот функция увеличения или уменьшения изображения на желаемую ширину или высоту при сохранении соотношения сторон

# 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(справа)

введите описание изображения здесь введите описание изображения здесь

nathancy
источник