缩小Python中图像的一部分

时间:2015-06-26 22:12:19

标签: python image-processing numpy resize python-imaging-library

我正在尝试从(x,y)坐标开始缩小图像的一部分,并将宽度和高度设置为500,将其调整为40x40。通过这样做,我将周围的像素平均为一个。 (我能找到的最简单的方法)但结果很奇怪。

原始图片为512x512 png

原始图片:

enter image description here

预期结果:

enter image description here

实际结果:

enter image description here

以下是代码段:

from PIL import Image
import numpy as np


defined_size = 40
img = Image.open("lena.png")
pix = np.array(img)
changed_img = shrink(pix, 0, 0, 500)
changed_img = np.array(changed_img)
resized = Image.fromarray(changed_img, 'RGB')

def shrink(img, x, y, size):
     result = [[0 for width in xrange(defined_size)] for height in xrange(defined_size)] 

     scale_factor = size/defined_size    
     for i in xrange(defined_size):
        for j in xrange(defined_size):
            temp = np.array([0,0,0])
            for t in xrange(scale_factor):
                print img[i*scale_factor+x, j*scale_factor+y]
                temp = np.add(temp, img[i*scale_factor+x, j*scale_factor+y])
            result[i][j] = np.divide(temp, scale_factor)
            print result[i][j]

     return result

3 个答案:

答案 0 :(得分:1)

@rayryeng-恢复莫妮卡的最新代码来自您的答案,但现在将通过平均周围像素将任何尺寸的输入图像调整为尺寸的四分之一。早期版本仅适用于正方形图像。谢谢你的帖子!

def quarter_res_avg(im):

    original_width = im.shape[1]
    original_height = im.shape[0]
    width = original_width / 4
    height = original_height / 4

    resized_image = np.zeros(shape=(height, width, 3), dtype=np.uint8)
    scale = 4

    for i in range(height):
        for j in range(width):
            temp = np.array([0, 0, 0])
            for x in range(scale):
                for y in range(scale):
                    temp += im[i*scale + x, j*scale + y]
            resized_image[i, j] = temp/(scale*scale)

    return resized_image

im = cv2.imread('Lenna_test_image.png', 1)
cv2.imwrite('Lenna_test_image_resized.png', quarter_res_avg(im))  

另一种方法:

def quarter_res_avg(im):

    original_width = im.shape[1]
    original_height = im.shape[0]

    width = original_width / 4
    height = original_height / 4

    resized_image = np.zeros(shape=(height, width, 3), dtype=np.uint8)

    scale = 4

    for i in range(0, original_height, scale):
        for j in range(0, original_width, scale):
           resized_image[i/scale, j/scale] = np.mean(im[i:i + scale, j:j+scale], axis=(0, 1))

    return resized_image

答案 1 :(得分:0)

为什么不使用库函数? Python库非常棒。

import PIL.Image
import scipy.misc

lena = scipy.misc.lena()
resized = scipy.misc.imresize(lena, (40, 40), interp='bilinear')
image = PIL.Image.fromarray(resized)

答案 2 :(得分:0)

您的代码存在一些问题。让我们一次解决一个问题:

问题#1 - (x,y)shrink定义

中无用

我知道你要去哪里(x,y)。您正在使用它来遍历每个较大的块,对所有像素求和并除以条目总数以获得平均RGB像素。对于图像中的每个块,您将此设置为(0,0),因此您实际上并未获得块中的所有像素。您需要使用一对for循环来允许遍历每个块。我也冒昧地删除了(x,y)输入,并将所需大小作为输入添加到您的函数中。

问题#2 - 输出不是三通道

您初始化了一个二维列表,但图片有​​三个频道。因为您正在使用numpy为您执行计算...为什么不首先通过zeros声明np.zeros数组?这样,您就不必在完成后转换回numpy数组。我已经更改了输出图像的声明,因此它是numpy类型为uint8的数组。这个演员很重要!

问题#3 - 没有正确迭代每个子采样块

正如我们在问题#1中所讨论的那样,您不是每个子采样块正确收集像素。我为您插入了另一对for循环...枚举为xy。我还删除了np.add并使用+为您执行操作,因为它更容易阅读。

问题#4 - 除错因子

因为它是您尝试计算的子样本的平均值,所以必须除以每个块中的值的总数。这等于scale_factor*scale_factor。你只是除以scale_factor

我还冒昧地显示已调整大小的图像并将其保存到文件中。没有进一步的麻烦这里是更正的代码。我还将您的测试代码放在__main__块中,以便于测试:

from PIL import Image
import numpy as np

def shrink(img, size, defined_size): # Change - Issue #1
     result = np.zeros((defined_size, defined_size, 3), dtype=np.uint8) # Change - Issue #2

     scale_factor = size/defined_size    
     for i in xrange(defined_size):
        for j in xrange(defined_size):
            temp = np.array([0,0,0])
            for x in xrange(scale_factor): # Change - Issue #3
                for y in xrange(scale_factor): # Change - Issue #3    
                    temp += img[i*scale_factor + x, j*scale_factor + y] # Change - Issue #3

            result[i,j] = temp / (scale_factor*scale_factor) # Change          

     return result

if __name__ == '__main__':
    img = Image.open("lena.png")
    pix = np.array(img)
    changed_img = shrink(pix, 512, 40) # Change - Issue #1
    resized = Image.fromarray(changed_img, 'RGB')
    resized.show() # Change
    resized.save("lena_resize.png")

...我们得到了这张已调整大小的图片:

enter image description here

相关问题