簡體   English   中英

如何指定numpy矩陣的子集來放置較小的矩陣?

[英]How can I specify a subset of a numpy matrix for placement of smaller matrix?

我有一個向下采樣率為2的圖像金字塔。也就是說,我的金字塔的底部是形狀為(256, 256)的圖像,下一個級別是(128, 128)等。

我的目標是將此金字塔顯示為單個圖像。 第一張圖片位於左側。 第二個放置在右上角。 每個后續圖像必須放置在前一個圖像的下方並楔入角落。

這是我當前的功能:

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]

如果查看輸出,可以看到我正在嘗試引用輸出圖像的2切片,以便將金字塔的下一層放置在其中。

問題是我執行的切片沒有給出我期望的形狀的2d數組。 它認為我正在嘗試將(n,n)矩陣放入(0,n)矩陣中。

當我指定像new_img[256:320, 128:192]這樣的切片時,為什么返回形狀為(0, 64) new_img[256:320, 128:192] (0, 64) ,NOT (64, 64)呢?

有沒有更簡單的方法可以做我想做的事情?

這是一個例子。

首先創建金字塔:

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:])]))

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM