簡體   English   中英

如何在不破壞圖像外觀的情況下使用 PIL 縮放圖像?

[英]How can I scale an image with PIL without ruining its appearence?

我注意到,即使對於等於 1 的系數,簡單地乘法和除法數組也會使圖像變形。

我需要重新縮放圖像像素,因為我需要將它們提供給 ML model,但我注意到在這個過程中似乎有大量信息丟失。

這是原始圖像(示例):

Image.fromarray((np.array(out_img.resize((224, 224)))),'L')

原圖

如果我將它除以 255,結果會變成這樣:

Image.fromarray((np.array(out_img.resize((224, 224)))/255),'L')

在此處輸入圖像描述

很多信息似乎丟失了,顯然我無法恢復到原來的狀態:

(np.array(out_img.resize((224, 224)))/255*255==np.array(out_img.resize((224, 224)))).all()    
Image.fromarray((np.array(out_img.resize((224, 224)))/255*255),'L')

在此處輸入圖像描述 如果你看到我檢查過乘以和除以 255 將返回相同的數組,但圖像看起來不同。

即使我天真地除以 1 並乘以 1,也會發生同樣的情況:

Image.fromarray((np.array(out_img.resize((224, 224)))*(1/1)),'L')

在此處輸入圖像描述

是否有對此行為的解釋或防止信息丟失的方法?

但是您不能從浮點數組創建“L”模式 PIL 圖像。 PIL.Image.fromarray只是將傳遞的數組中的數據插入到圖像中。 那些具有L模式的數據應該是字節。 而你給的是花車。

請參見以下示例

from PIL import Image
import numpy as np
img = np.array([[3.141592653589793, 12, 13, 14], [15, 16, 17, 18]])
limg=np.array(Image.fromarray(img, 'L'))

limg 現在是一個與 img 形狀相同的數組。 由於從 img 構建的 PIL 圖像具有此分辨率。 但是數據是 8 個字節(因為有 8 個像素,我們說格式是 L),這是從img中獲取的前 8 個字節。

img.tobytes()
# b'\x18-DT\xfb!\t@\x00\x00\x00\x00\x00\x00(@\x00\x00\x00\x00\x00\x00*@\x00\x00\x00\x00\x00\x00,@\x00\x00\x00\x00\x00\x00.@\x00\x00\x00\x00\x00\x000@\x00\x00\x00\x00\x00\x001@\x00\x00\x00\x00\x00\x002@'
limg.tobytes()
# b'\x18-DT\xfb!\t@'

我們甚至可以嘗試解碼

import struct
limg
# array([[ 24,  45,  68,  84],
#       [251,  33,   9,  64]], dtype=uint8)
struct.pack('BBBBBBBB', 24, 45, 68, 84, 251, 33, 9, 64)
# b'\x18-DT\xfb!\t@'
# See, it is the same things. Just the bytes of limg, that is the 8 1st bytes of img, shown as uint8

struct.unpack('d', struct.pack('BBBBBBBB', 24, 45, 68, 84, 251, 33, 9, 64))
# (3.141592653589793,)
# See, it is just the 8 bytes of float representation of the first float in img (the 7 other are lost

因此,您在此處擁有的圖像是浮點數據字節的圖像(浮點數據的第 1 個和第 8 個字節,因為沒有更多空間)。 每組 8 個像素是一個浮點數的 8 個字節。

將 uint8 的 ndarray 轉換為 float 的 ndarray 的任何操作都會發生同樣的情況。 包括乘以(1/1)

解決方案

我不知道你用的是什么ML model。 我懷疑它需要 PIL 圖像。 所以,你可以將它傳遞給 ndarray。 如果需要,包括花車。

如果你真的需要使用 PIL 圖像,那么你可以使用“F”模式而不是“L”(這意味着 8 位灰度)。

請注意,如果您只是沒有將 'L' 參數傳遞給fromarray ,它會自己猜測模式(灰度,因為 H×W 形狀 - 而不是 H×W×3,即 RGB,或 H×W× 2 將是 LA,... — 'F' 因為 float dtype)

另請注意,您的問題與縮放無關。 如果沒有任何resize ,您會遇到完全相同的問題。 Image.fromarray(np.array(img)*1.0, 'L')會有同樣的問題。 這不是縮放質量問題。 它是一種圖像格式,甚至是一種數據格式,問題; 您正在使用包含浮點數的 memory,並要求 PIL 將其解釋為包含 uint8。

暫無
暫無

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

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