【问题标题】:Saving numpy array to image shrinks image parts to wrong size将 numpy 数组保存到图像会将图像部分缩小到错误的大小
【发布时间】:2020-05-25 06:56:36
【问题描述】:

在弄清楚如何在搅拌机脚本中导出外部图像时,我遇到了这个问题。但我想这不再与搅拌机直接相关,更多的是与 numpy 以及如何处理数组有关。 Here is post about first problem.

所以问题是当将 numpy 数组保存到图像时,它会失真并且有多个相同的图像。请看下图以获得更好的理解。

我们的目标是试图弄清楚如何使用搅拌机自己的像素数据与 numpy 和 python 一起工作。所以避免使用像 PIL 或 cv2 这样的库,这些库不包含在 blender python 中。

当保存数据时,所有最终尺寸的图像都可以正常工作。当尝试将 4 个较小的部分合并为最终的较大图像时,它无法正确导出。

我在blender中用python做了示例脚本来演示这个问题:

# Example script to show how to merge external images in Blender
# using numpy. In this example we use 4 images (2x2) that should
# be merged to one actual final image. 
# Regular (not cropped render borders) seems to work fine but
# how to merge cropped images properly???
#
# Usage: Just run script and it will export image named "MERGED_IMAGE"
# to root of this project folder and you'll see what's the problem.

import bpy, os
import numpy as np

ctx = bpy.context
scn = ctx.scene

print('START')

# Get all image files
def get_files_in_folder(path):
    path = bpy.path.abspath(path)
    render_files = []
    for root, dirs, files in os.walk(path):
        for file in files:
            if (file.lower().endswith(('.png', '.jpg', '.jpeg', '.tiff', '.bmp', '.gif'))):
                render_files.append(file)
    return render_files

def merge_images(image_files, image_cropped = True):

    image_pixels = []
    final_image_pixels = 0

    print(image_files)

    for file in image_files:
        if image_cropped is True:
            filepath = bpy.path.abspath('//Cropped\\' + file)
        else:
            filepath = bpy.path.abspath('//Regular\\' + file)
        loaded_pixels = bpy.data.images.load(filepath, check_existing=True).pixels
        image_pixels.append(loaded_pixels)

    np_array = np.array(image_pixels)

    # Merge images
    if image_cropped:
        final_image_pixels = np_array
        # HOW MERGE PROPERLY WHEN USING CROPPED IMAGES???
    else:
        for arr in np_array:
            final_image_pixels += arr

    # Save output image
    output_image = bpy.data.images.new('MERGED_IMAGE', alpha=True, width=256, height=256)
    output_image.file_format = 'PNG'
    output_image.alpha_mode = 'STRAIGHT'
    output_image.pixels = final_image_pixels.ravel()
    output_image.filepath_raw = bpy.path.abspath("//MERGED_IMAGE.png")
    output_image.save()   

images_cropped = get_files_in_folder("//Cropped")
images_regular = get_files_in_folder('//Regular')

# Change between these to get different example
merge_images(images_cropped)
#merge_images(images_regular, False)

print('END')

所以我猜这个问题与如何用numpy处理图像像素数据和数组有关。

这是 zip 文件中的项目文件夹,其中包含工作测试脚本示例,您可以在其中测试其在搅拌机中的工作方式。 https://drive.google.com/file/d/1R4G_fubEzFWbHZMLtAAES-QsRhKyLKWb/view?usp=sharing

【问题讨论】:

    标签: python arrays numpy image-processing blender


    【解决方案1】:

    由于您所有的图像都与128x128 的尺寸相同,并且由于 OpenCV 图像是 Numpy 数组,因此这里有三种方法。您可以使用cv2.imwrite 保存图像。

    输入图像:

    方法#1: np.hstack + np.vstack

    hstack1 = np.hstack((image1, image2))
    hstack2 = np.hstack((image3, image4))
    hstack_result = np.vstack((hstack1, hstack2))
    

    方法#2: np.concatenate

    concatenate1 = np.concatenate((image1, image2), axis=1)
    concatenate2 = np.concatenate((image3, image4), axis=1)
    concatenate_result = np.concatenate((concatenate1, concatenate2), axis=0) 
    

    方法#3: cv2.hconcat + cv2.vconcat

    hconcat1 = cv2.hconcat([image1, image2])
    hconcat2 = cv2.hconcat([image3, image4])
    hconcat_result = cv2.vconcat([hconcat1, hconcat2])
    

    所有方法的结果应该相同

    完整代码

    import cv2
    import numpy as np
    
    # Load images
    image1 = cv2.imread('Fart_1_2.png')
    image2 = cv2.imread('Fart_2_2.png')
    image3 = cv2.imread('Fart_1_1.png')
    image4 = cv2.imread('Fart_2_1.png')
    
    # Method #1
    hstack1 = np.hstack((image1, image2))
    hstack2 = np.hstack((image3, image4))
    hstack_result = np.vstack((hstack1, hstack2))
    
    # Method #2
    concatenate1 = np.concatenate((image1, image2), axis=1)
    concatenate2 = np.concatenate((image3, image4), axis=1)
    concatenate_result = np.concatenate((concatenate1, concatenate2), axis=0) 
    
    # Method #3
    hconcat1 = cv2.hconcat([image1, image2])
    hconcat2 = cv2.hconcat([image3, image4])
    hconcat_result = cv2.vconcat([hconcat1, hconcat2])
    
    # Display
    cv2.imshow('concatenate_result', concatenate_result)
    cv2.imshow('hstack_result', hstack_result)
    cv2.imshow('hconcat_result', hconcat_result)
    cv2.waitKey()
    

    【讨论】:

    • 优秀而清晰的答案!问题是在这种情况下我不能使用 cv2,因为 Blender 中没有。试图弄清楚如何完全在 numpy 和 python 中完成这项工作。我想问题可能是搅拌器读取像素的方式与 cv2 不同。所以也许我需要为原始像素数据做一些事情,然后才能使用它以避免使用 cv2 库。不过,这对于理解这些工作原理非常有用。
    • 我明白了,如果您可以将图像转换为与 opencv 相同的像素格式,您应该可以使用这些方法。祝你好运!
    • 为什么不将 opencv 安装到您的搅拌机环境中?使用 /python --ensure pip 然后 pip install opencv。也适用于 matplotlib 和其他东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-22
    • 2020-06-14
    相关资源
    最近更新 更多