简体   繁体   English

调整48位PNG的大小,保留其48位,而不将其丢弃为24位文件

[英]Resizing a 48bit PNG retaining its 48bits, without dropping it to a 24bit file

I'm trying to resize the following 48bit PNG from 1242 x 375 to 256 x 256 but retain its 48 bits. 我正在尝试将以下48位PNG的大小从1242 x 375调整为256 x 256,但保留其48位。

This PNG Ground Truth Image is available for download here 此PNG地面真相图像可从此处下载

I was wondering if there is a way to code it so that the 48bits is retained ? 我想知道是否有办法对其进行编码以保留48位?

I have tried a few different libraries, however the resultant file becomes a 24bit PNG. 我尝试了几个不同的库,但结果文件变为24位PNG。

# Resize 48bit PNG file and maintain 48bit PNG when saving to file

from PIL import Image
from numpngw import write_png
import cv2
import scipy
import imageio
import skimage

PNG_Location_Filepath = "..\\..\\000000_10.png"
out = "output_images\\"
#The Pillow way
im = Image.open(PNG_Location_Filepath)
PIL_imResized = im.resize((256,256), Image.ANTIALIAS)
libraryname = "Pillow"
savedfilename = out + libraryname + '.png'
PIL_imResized.save(savedfilename)

#The numpngw way
im = cv2.imread(PNG_Location_Filepath, cv2.IMREAD_UNCHANGED)
cv2_imResized = cv2.resize(im, (256,256), interpolation=cv2.INTER_AREA)
libraryname = "numpngw"
savedfilename = out + libraryname + '.png'
write_png(savedfilename, cv2_imResized)

#The Scipy way / ImageIOSkimage way
#im = scipy.misc.imread(PNG_Location_Filepath,mode='RGB')
im = imageio.imread(PNG_Location_Filepath)
#Scipy_imResized = scipy.misc.imresize(im, [256, 256])
Skimage_imResized = skimage.transform.resize(im, (256, 256))
libraryname = "ImageIoSkimage"
savedfilename = out + libraryname + '.png'
#scipy.misc.imsave(savedfilename, Scipy_imResized)
imageio.imwrite(savedfilename, Skimage_imResized)

# `imread` is deprecated in SciPy 1.0.0, and will be removed in 1.2.0.
# Use ``imageio.imread`` instead
# `imresize` is deprecated in SciPy 1.0.0, and will be removed in 1.2.0.
# Use ``skimage.transform.resize`` instead
# `imsave` is deprecated in SciPy 1.0.0, and will be removed in 1.2.0
# Use ``imageio.imwrite`` instead. 

I also tried this code, but received an error message 我也试过这段代码,但收到了错误信息

import cv2
import imageio
imageio.plugins.freeimage.download()
PNG_Location_Filepath = "..\\..\\000000_10.png"
Resized_Location_Filepath = "..\\..\\000000_10_resized.png"

imageio.plugins.freeimage.FreeimagePngFormat.Reader._open
(PNG_Location_Filepath)
img_in_imageio = imageio.imread(PNG_Location_Filepath, format='PNG-FI')
Resized_Image = cv2.resize(img_in_imageio, (256,256))
Saved_Filename = Resized_Location_Filepath
imageio.imwrite(Saved_Filename, Resized_Image, format='PNG-FI')

Error: 错误:

Traceback (most recent call last):  File "c:\.vscode\extensions\ms-python.python-2019.6.24221\pythonFiles\ptvsd_launcher.py", line 43, in <module>    main(ptvsdArgs)  File "c:\.vscode\extensions\ms-python.python-2019.6.24221\pythonFiles\lib\python\ptvsd\__main__.py", line 434, in main
    run()
  File "c:\.vscode\extensions\ms-python.python-2019.6.24221\pythonFiles\lib\python\ptvsd\__main__.py", line 312, in run_file
    runpy.run_path(target, run_name='__main__')
  File "C:\AppData\Local\Programs\Python\Python37\lib\runpy.py", line 263, in run_path
    pkg_name=pkg_name, script_name=fname)
  File "C:\AppData\Local\Programs\Python\Python37\lib\runpy.py", line 96, in _run_module_code
    mod_name, mod_spec, pkg_name, script_name)
  File "C:\AppData\Local\Programs\Python\Python37\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "c:\Documents\DeepLearning\Learning\Code\Sandpit\Resize48bitKeeping48bit.py", line 10, in <module>
    img_in_imageio = imageio.plugins.freeimage.FreeimagePngFormat.Reader._open(PNG_Location_Filepath)
  File "C:\AppData\Local\Programs\Python\Python37\lib\site-packages\freeimage.py", line 221, in _open
    return FreeimageFormat.Reader._open(self, flags)
  File "C:\AppData\Local\Programs\Python\Python37\lib\site-packages\imageio\plugins\freeimage.py", line 81, in _open
    self._bm = fi.create_bitmap(self.request.filename, self.format.fif, flags)
AttributeError: 'str' object has no attribute 'request'

So I tried this code 所以我尝试了这段代码

import cv2
import imageio
imageio.plugins.freeimage.download()
PNG_Location_Filepath = "..\\..\\000000_10.png"
Resized_Location_Filepath = "..\\..\\000000_10_resized.png"
img_in_imageio = imageio.imread(PNG_Location_Filepath, format='PNG-FI')
#img_in_imageio.resize((256,256,3))
Resized_Image = cv2.resize(img_in_imageio, (256,256))
Saved_Filename = Resized_Location_Filepath
imageio.imwrite(Saved_Filename, img_in_imageio, format='PNG-FI')

And this copied the file, but it didn't resize it 这复制了文件,但没有调整大小

I am expecting the file format at uint48 to be maintained, however the output file seems to be 24bits 我希望维护uint48的文件格式,但输出文件似乎是24位

You can use imageio with freeimage library using format='PNG-FI' in imageio.imread / imageoio.imwrite . 您可以在imageio.imread / imageoio.imwrite使用format='PNG-FI'imageiofreeimage库结合使用。

Based on information in source code of freeimage.py in imageio to install freeimage library you can use imageio : 根据imageioimageio源代码中的信息安装freeimage库,你可以使用imageio

  • in command line (on Linux it works even without full path) 在命令行中(在Linux上它即使没有完整路径也可以工作)

     imageio_download_bin freeimage 
  • using python code 使用python代码

     import imageio imageio.plugins.freeimage.download() 

Probably if you install library ( .dll / .so ) directly from FreeImage webpage then it will also work. 可能如果你直接从FreeImage网页安装库( .dll / .so )那么它也可以工作。


Image has to be copied ( img.copy() ). 必须复制图像( img.copy() )。 Because making image smaller it removed pixels with the biggest values so I work with part of image and make its bigger. 因为使图像变小,所以删除了具有最大值的像素,因此我使用部分图像并使其更大。

# read 48bit color
img = imageio.imread("..\\..\\000000_10.png", format='PNG-FI')

# max values in image
print('shape:', img.shape)
print('max R:', img[:,:,0].max())
print('max G:', img[:,:,1].max())
print('max B:', img[:,:,2].max())
print('---')

# cut-off part of image (with)
img = img.copy()
img = img[370:375,1020:1025,:]
img = img.copy()
img.resize((256,256,3))

print('shape:', img.shape)
print('max R:', img[:,:,0].max())
print('max G:', img[:,:,1].max())
print('max B:', img[:,:,2].max())
print('---')

# find X,Y for first max red value
print('max X:', img[:,:,0].max(axis=0).argmax())
print('max Y:', img[:,:,0].max(axis=1).argmax())
print(' flat:', img[:,:,0].argmax())
print('---')

# find X,Y for all max red values
max_r = img[:,:,0].max()

for y, row in enumerate(img[:,:,0]):
    for x, it in enumerate(row):
        if it == max_r:
            print('value/x/y:', max_r, x, y)

# write 48bit color
imageio.imwrite('output_48bit.png', img, format='PNG-FI')

Output: 输出:

shape: (375, 1242, 3)
max R: 40827
max G: 36674
max B: 1
---
shape: (256, 256, 3)
max R: 40827
max G: 36506
max B: 1
---
max X: 14
max Y: 0
 flat: 14
---
value/x/y: 40827 14 0

In Linux I can use program `file in command line to check if file use 48bit color (16bits per color) 在Linux中,我可以在命令行中使用程序`文件来检查文件是否使用48位颜色(每种颜色16位)

$ file 000000_10.png

000000_10.png: PNG image data, 1242 x 375, 16-bit/color RGB, non-interlaced


$ file output_48bit.png 

output_48bit.png: PNG image data, 256 x 256, 16-bit/color RGB, non-interlaced

If you have RGBA then it will use 64bit color. 如果你有RGBA那么它将使用64位颜色。

Example from imageio issues: Unable to properly read multi-channel 16-bit png files imageio问题示例: 无法正确读取多通道16位png文件

import imageio
import numpy as np

img_out = np.zeros((256, 256, 4), dtype=np.uint16)
color_grad = np.reshape(np.arange(2**16), (256,-1))
img_out[:, :, 0] = color_grad
img_out[:, :, 1] = np.rot90(color_grad, 1)
img_out[:, :, 2] = np.rot90(color_grad, 2)
img_out[:, :, 3] = np.rot90(color_grad, 3)

print('Write unique values: R={}, G={}, B={}, A={}'.format(
    len(set(img_out[:, :, 0].flatten().tolist())),
    len(set(img_out[:, :, 1].flatten().tolist())),
    len(set(img_out[:, :, 2].flatten().tolist())),
    len(set(img_out[:, :, 3].flatten().tolist()))))
imageio.imwrite('64bit_imageio.png', img_out, format='PNG-FI')

img_in_imageio = imageio.imread('64bit_imageio.png', format='PNG-FI')
print('imageio PNG unique values: R={}, G={}, B={}, A={}'.format(
    len(set(img_in_imageio[:, :, 0].flatten().tolist())),
    len(set(img_in_imageio[:, :, 1].flatten().tolist())),
    len(set(img_in_imageio[:, :, 2].flatten().tolist())),
    len(set(img_in_imageio[:, :, 3].flatten().tolist()))))

Output: 输出:

Write unique values: R=65536, G=65536, B=65536, A=65536
imageio PNG unique values: R=65536, G=65536, B=65536, A=65536

output_48bit.png: PNG image data, 5 x 5, 16-bit/color RGB, non-interlaced

EDIT: Your last code with more readable names for variables (lower_case_names) and few free lines to make it also more readable. 编辑:您的最后一个代码具有更易读的变量名称(lower_case_names)和少量自由行,使其更具可读性。

In original code you had mess so finally you wrote original image instead of resized one. 在原始代码中你弄得很乱,所以最后你写了原始图像而不是调整大小的图像。

import cv2
import imageio

# need it only once 
#imageio.plugins.freeimage.download()

input_filename  = "..\\..\\000000_10.png"
output_filename = "..\\..\\000000_10_resized.png"

input_image  = imageio.imread(input_filename, format='PNG-FI')
output_image = cv2.resize(input_image, (256, 256))

imageio.imwrite(output_filename, output_image, format='PNG-FI')
# Resize 48bit PNG file and maintain 48bit PNG when saving to file WORKING

import cv2
import imageio
imageio.plugins.freeimage.download()
PNG_Location_Filepath = "..\\..\\000000_10.png"
Resized_Location_Filepath = "..\\..\\000000_10_resized.png"
img_in_imageio = imageio.imread(PNG_Location_Filepath, format='PNG-FI')
Resized_Image = cv2.resize(img_in_imageio, (256,256))
Saved_Filename = Resized_Location_Filepath
imageio.imwrite(Saved_Filename, Resized_Image, format='PNG-FI')

#This works to resize the image, keeping 48bits

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM