2016-09-24 5 views
0

У меня есть изображения пирамида с понижающей частотой дискретизации 2. То есть, в нижней части моей пирамиды является изображением формы (256, 256), где на следующем уровне является (128, 128) и т.д.Как указать подмножество матрицы numpy для размещения меньшей матрицы?

Моей цели, чтобы отобразить это пирамиды в одно изображение. Первое изображение расположено слева. Второй находится в верхнем правом углу. Каждое последующее изображение должно быть помещено под предыдущим и вклиниваться в угол.

Вот моя текущая функция:

def pyramid2img(pmd): 
    ''' 
    Given a pre-constructed pyramid, this is a helper 
    function to display the pyramid in a single image. 
    ''' 

    # orignal shape (pyramid goes from biggest to smallest) 
    org_img_shp = pmd[0].shape 

    # the output will have to have 1.5 times the width 
    out_shp = tuple(int(x*y) \ 
     for (x,y) in zip(org_img_shp, (1, 1.5))) 
    new_img = np.zeros(out_shp, dtype=np.int8) 

    # i keep track of the top left corner of where I want to 
    # place the current image matrix 
    origin = [0, 0] 
    for lvl, img_mtx in enumerate(pmd): 

     # trying to specify the subset to place the next img_mtx in 
     sub = new_img[origin[0]:origin[0]+pmd[lvl].shape[0], 
      origin[1]:origin[1]+pmd[lvl].shape[1]]# = img_mtx 

     # some prints to see exactly whats being called above^
     print 'level {}, sub {}, mtx {}'.format(
      lvl, sub.shape, img_mtx.shape) 
     print 'sub = new_img[{}:{}, {}:{}]'.format(
      origin[0], origin[0]+pmd[lvl].shape[0], 
      origin[1], origin[1]+pmd[lvl].shape[1]) 

     # first shift moves the origin to the right 
     if lvl == 0: 
      origin[0] += pmd[lvl].shape[0] 
     # the rest move the origin downward 
     else: 
      origin[1] += pmd[lvl].shape[1] 

    return new_img 

ВЫХОД ИЗ ПЕЧАТИ ОТЧЕТНОСТЬ:

level 0, sub (256, 256), mtx (256, 256) 
sub = new_img[0:256, 0:256] 


level 1, sub (0, 128), mtx (128, 128) 
sub = new_img[256:384, 0:128] 


level 2, sub (0, 64), mtx (64, 64) 
sub = new_img[256:320, 128:192] 


level 3, sub (0, 32), mtx (32, 32) 
sub = new_img[256:288, 192:224] 


level 4, sub (0, 16), mtx (16, 16) 
sub = new_img[256:272, 224:240] 


level 5, sub (0, 8), mtx (8, 8) 
sub = new_img[256:264, 240:248] 


level 6, sub (0, 4), mtx (4, 4) 
sub = new_img[256:260, 248:252] 

Если вы посмотрите на выходе, вы можете увидеть, что я пытаюсь сделать ссылку на 2d-срез выходного изображения, чтобы я мог разместить в нем следующий уровень пирамиды.

Проблема в том, что нарезка, которую я выполняю, не дает 2d-массив с формой, которую я ожидаю. Он думает, что я пытаюсь поместить матрицу (n, n) в матрицу (0, n).

Как получилось, когда я указываю срез как new_img[256:320, 128:192], он возвращает объект с формой (0, 64), NOT (64, 64)?

Есть ли более простой способ сделать то, что я пытаюсь сделать?

ответ

1

Вот пример.

Создать пирамиду первым:

import numpy as np 
import pylab as pl 
import cv2 

img = cv2.imread("earth.jpg")[:, :, ::-1] 

size = 512 
imgs = [] 
while size >= 2: 
    imgs.append(cv2.resize(img, (size, size))) 
    size //= 2 

А вот код для объединения изображений:

def align(size, width, loc): 
    if loc in ("left", "top"): 
     return 0 
    elif loc in ("right", "bottom"): 
     return size - width 
    elif loc == "center": 
     return (size - width) // 2 

def resize_canvas(img, shape, loc, fill=255): 
    new_img = np.full(shape + img.shape[2:], fill, dtype=img.dtype) 
    y = align(shape[0], img.shape[0], loc[0]) 
    x = align(shape[1], img.shape[1], loc[1]) 
    new_img[y:y+img.shape[0], x:x+img.shape[1], ...] = img 
    return new_img 

def vbox(imgs, align="right", fill=255): 
    width = max(img.shape[1] for img in imgs) 
    return np.concatenate([ 
      resize_canvas(img, (img.shape[0], width), ("top", align), fill=fill) 
      for img in imgs 
     ]) 

def hbox(imgs, align="top", fill=255): 
    height = max(img.shape[0] for img in imgs) 
    return np.concatenate([ 
      resize_canvas(img, (height, img.shape[1]), (align, "left"), fill=fill) 
      for img in imgs 
     ], axis=1) 

выхода:

pl.imshow(hbox([imgs[0], vbox(imgs[1:])])) 

enter image description here

+0

Wow, что умный способ сделать это ! Огромное вам спасибо :) Я начал читать о том, как многократно нарезать/шагать по http://stackoverflow.com/questions/4257394/slicing-of-a-numpy-2d-array-or-how-do-extext -an-mxm-submatrix-from-an-nxn-ar , который казался кошмаром. Ваше решение очень интуитивно. Спасибо. – spanishgum

Смежные вопросы