给定任意数量的较小平方矩阵的算法来创建方阵

时间:2014-01-15 10:44:28

标签: python numpy opencv matrix

我想用Opencv绘制一些图像,为此我想将图像粘合在一起。

想象一下,我有4张照片。最好的方法是将它们粘贴在2x2图像矩阵中。

a = img; a.shape == (48, 48)
b = img; b.shape == (48, 48)
c = img; c.shape == (48, 48)
d = img; d.shape == (48, 48)

我现在使用np.reshape,它接受[a,b,c,d]之类的列表,然后我手动放置尺寸以获得以下内容:

np.reshape([a,b,c,d], (a.shape*2, a.shape*2)).shape == (96, 96)

当我有3张照片时,问题就开始了。我有点想到我可以取列表长度的平方根,然后是天花板值,它将产生2(np.ceil(sqrt(len([a,b,c]))) == 2)的方阵矩阵。然后,我必须添加一个白色图像,其中第一个元素的维度到列表中,然后我们就去了。但我认为必须有一种更简单的方法来完成绘图,很可能已在某处定义。

那么,如何轻松地将任意数量的方矩阵组合成一个大的方阵?

编辑:

我想出了以下内容:

def plotimgs(ls):
    shp = ls[0].shape[0]         # the image's dimension
    dim = np.ceil(sqrt(len(ls))) # the amount of pictures per row AND column
    emptyimg = (ls[1]*0 + 1)*255 # used to add to the list to allow square matrix
    for i in range(int(dim*dim - len(ls))):
        ls.append(emptyimg)
    enddim = int(shp*dim)        # enddim by enddim is the final matrix dimension
    # Convert to 600x600 in the end to resize the pictures to fit the screen
    newimg = cv2.resize(np.reshape(ls, (enddim, enddim)), (600, 600))
    cv2.imshow("frame", newimg)
    cv2.waitKey(10)

 plotimgs([a,b,d])

不知何故,即使尺寸合适,它实际上也会克隆一些图片:

When I give 4 pictures, I get 8 pictures.
When I give 9 pictures, I get 27 pictures.
When I give 16 pictures, I get 64 pictures.

所以事实上,不是平方,我得到了图像的第三种力量。但是,例如

plotimg([a]*9)会给出尺寸为44*3 x 44*3 = 144x144的照片,对于9张照片应该是正确的吗?

2 个答案:

答案 0 :(得分:0)

这是我用来做这类事情的片段:

import numpy as np

def montage(imgarray, nrows=None, border=5, border_val=np.nan):
    """
    Returns an array of regularly spaced images in a regular grid, separated
    by a border

    imgarray: 
        3D array of 2D images (n_images, rows, cols)
    nrows:  
        the number of rows of images in the output array. if 
        unspecified, nrows = ceil(sqrt(n_images))
    border: 
        the border size separating images (px)
    border_val:
        the value of the border regions of the output array (np.nan
        renders as transparent with imshow)
    """

    dims = (imgarray.shape[0], imgarray.shape[1]+2*border,
        imgarray.shape[2] + 2*border)

    X = np.ones(dims, dtype=imgarray.dtype) * border_val
    X[:,border:-border,border:-border] = imgarray

    # array dims should be [imageno,r,c]
    count, m, n = X.shape

    if nrows != None:
        mm = nrows
        nn = int(np.ceil(count/nrows))
    else:
        mm = int(np.ceil(np.sqrt(count)))
        nn = mm

    M = np.ones((nn * n, mm * m)) * np.nan

    image_id = 0
    for j in xrange(mm):
        for k in xrange(nn):
            if image_id >= count: 
                break
            sliceM, sliceN = j * m, k * n
            img = X[image_id,:, :].T
            M[sliceN:(sliceN + n), sliceM:(sliceM + m)] = img
            image_id += 1

    return np.flipud(np.rot90(M))

示例:

from scipy.misc import lena
from matplotlib import pyplot as plt

img = lena().astype(np.float32)
img -= img.min()
img /= img.max()
imgarray = np.sin(np.linspace(0, 2*np.pi, 25)[:, None, None] + img)

m = montage(imgarray)
plt.imshow(m, cmap=plt.cm.jet)

enter image description here

答案 1 :(得分:0)

重用How do you split a list into evenly sized chunks?中的块:

def chunks(l, n):
    """ Yield successive n-sized chunks from l.
    """
    for i in xrange(0, len(l), n):
        yield l[i:i+n]

重写你的功能:

def plotimgs(ls):
    shp = ls[0].shape[0]         # the image's dimension
    dim = int(np.ceil(sqrt(len(ls)))) # the amount of pictures per row AND column
    emptyimg = (ls[1]*0 + 1)*255 # used to add to the list to allow square matrix
    ls.extend((dim **2 - ls) * [emptyimg]) # filling the list with missing images
    newimg = np.concatenate([np.concatenate(c, axis=0) for c in chunks(ls, dim)], axis=1)
    cv2.imshow("frame", newimg)
    cv2.waitKey(10)

 plotimgs([a,b,d])