简体   繁体   English

如何在不使用 OpenCV 库的情况下在 Python 中读取多通道 16 位每通道图像?

[英]How to read multi-channel 16-bit-per-channel images in Python without using OpenCV library?

You can download a multi-channel, 16-bit png file from here (shown below).您可以从此处下载多通道 16 位 png 文件(如下所示)。 I have tried multiple Python packages for reading this multi-channel 16-bit-per-channel image.我尝试了多个 Python 包来读取这个多通道 16 位每通道图像。 But none work, and if they do somehow they transform the images (scaling etc).但是没有任何效果,如果它们以某种方式进行,它们会转换图像(缩放等)。 I tried using imageio , PIL.Image , scipy.ndimage.imread and a couple more.我尝试使用imageioPIL.Imagescipy.ndimage.imread等等。 It seems that they all can read single-channel 16-bit pngs properly but convert the multi-channel images into 8-bit-per-channel.似乎他们都可以正确读取单通道 16 位 png,但将多通道图像转换为每通道 8 位。 For instance, this is a GitHub issue thst indicates imageio cannot read multi-channel 16-bit images.例如,是一个 GitHub 问题,表明imageio无法读取多通道16 位图像。 Another issue ( here ) for Pillow seems to say the same thing. Pillow 的另一个问题(这里)似乎也说同样的话。

So I wonder, does anyone know how can I read multi-channel, 16-bit png files in Python without using OpenCV package properly?所以我想知道,有谁知道如何在不正确使用 OpenCV 包的情况下在 Python 中读取多通道、16 位 png 文件? Feel free to offer solutions from other packages that I didn't mention anything about here.随意提供我在这里没有提到的其他软件包的解决方案。

在此处输入图片说明

Option 1 - Split into channels with ImageMagick选项 1 - 使用 ImageMagick 分成多个通道

You could use ImageMagick (it is installed on most Linux distros and is available for macOS and Windows) at the command line.您可以在命令行中使用ImageMagick (它安装在大多数 Linux 发行版上,可用于 macOS 和 Windows)。

For example, this will separate your 16-bit 3-channel PNG into its constituent channels that you can then process individually in Pillow:例如,这会将您的 16 位 3 通道 PNG 分成其组成通道,然后您可以在 Pillow 中单独处理这些通道:

magick input.png -separate channel-$d.png

Now there are 3 separate channels:现在有 3 个独立的频道:

-rw-r--r--   1 mark  staff     2276  1 Apr 16:47 channel-2.png
-rw-r--r--   1 mark  staff     3389  1 Apr 16:47 channel-1.png
-rw-r--r--   1 mark  staff     2277  1 Apr 16:47 channel-0.png

and they are each 16-bit, single channel images that Pillow can open:它们都是 Pillow 可以打开的 16 位单通道图像:

magick identify channel-*

Sample Output样本输出

channel-0.png PNG 600x600 600x600+0+0 16-bit Grayscale Gray 2277B 0.000u 0:00.000
channel-1.png PNG 600x600 600x600+0+0 16-bit Grayscale Gray 3389B 0.000u 0:00.000
channel-2.png PNG 600x600 600x600+0+0 16-bit Grayscale Gray 2276B 0.000u 0:00.000

If you are using ImageMagick v6, replace magick with convert and replace magick identify with plain identify .如果您使用的是ImageMagick v6,请将magick替换为convert并将magick identify替换为普通的identify


Option 2 - Split into channels with NetPBM选项 2 - 使用 NetPBM 拆分为多个频道

As an alternative to ImageMagick , you could use the much lighter weight NetPBM tools to do the same thing:作为ImageMagick的替代方案,您可以使用重量更轻的 NetPBM 工具来做同样的事情:

pngtopam < rainbow.png | pamchannel - 0 -tupletype GRAYSCALE > channel-0.pam
pngtopam < rainbow.png | pamchannel - 1 -tupletype GRAYSCALE > channel-1.pam
pngtopam < rainbow.png | pamchannel - 2 -tupletype GRAYSCALE > channel-2.pam

Pillow can then open the PAM files. Pillow 然后可以打开 PAM 文件。


Option 3 - Use PyVips选项 3 - 使用 PyVips

As an alternative, you could use the extremely fast, memory-efficient pyvips to process your images.作为替代方案,您可以使用速度极快、内存高效的pyvips来处理您的图像。 Here is an example from the documentation that:这是文档中的一个示例:

  • crops 100 pixels off each side每边裁剪 100 个像素
  • shrinks an image by 10% with bilinear interpolation使用双线性插值将图像缩小 10%
  • sharpens with a convolution and re-saves the image.用卷积锐化并重新保存图像。

Here is the code:这是代码:

#!/usr/local/bin/python3
import sys
import pyvips

im = pyvips.Image.new_from_file(sys.argv[1], access='sequential')
im = im.crop(100, 100, im.width - 200, im.height - 200)
im = im.reduce(1.0 / 0.9, 1.0 / 0.9, kernel='linear')
mask = pyvips.Image.new_from_array([[-1, -1,  -1], 
                                    [-1,  16, -1], 
                                    [-1, -1,  -1]], scale=8)
im = im.conv(mask, precision='integer')
im.write_to_file("result.png")

The result is 16-bit like the input image:结果与输入图像一样为 16 位:

identify result.png
result.png PNG 360x360 360x360+0+0 16-bit sRGB 2900B 0.000u 0:00.000

As you can see it is still 16-bit, and trimming 100px off each side results in 600px becoming 400px and then the 10% reduction makes that into 360px.如您所见,它仍然是 16 位,每边修剪 100 像素会导致 600 像素变为 400 像素,然后减少 10% 使其变为 360 像素。


Option 4 - Convert to TIFF and use PyLibTiff选项 4 - 转换为 TIFF 并使用 PyLibTiff

A fourth option, if the number of files is an issue, might be to convert your images to TIFF with ImageMagick第四个选项,如果文件数量是一个问题,可能是使用ImageMagick将您的图像转换为 TIFF

convert input.png output.tif

and they retain their 16-bit resolution, and you process them with PyLibTiff as shown here .他们保留自己的16位分辨率,你PyLibTiff处理它们如图所示这里


Option 5 - Multi-image TIFF processed as ImageSequence选项 5 - 多图像 TIFF 处理为 ImageSequence

A fifth option, could be to split your PNG files into their constituent channel and store them as a multi-image TIFF, ie with Red as the first image in the sequence, green as the second and blue as the third.第五个选项可能是将您的 PNG 文件拆分为它们的组成通道并将它们存储为多图像 TIFF,即红色作为序列中的第一个图像,绿色作为第二个图像,蓝色作为第三个图像。 This means there is no increase in he number of files and also you can store more than 3 channels per file - you mentioned 5 channels somewhere in your comments:这意味着文件数量不会增加,而且每个文件可以存储 3 个以上的频道 - 您在评论中提到了 5 个频道:

convert input.png -separate multiimage.tif

Check there are now 3 images, each 16-bit, but all in the same, single file:检查现在有 3 个图像,每个 16 位,但都在同一个文件中:

identify multiimage.tif
multiimage.tif[0] TIFF 600x600 600x600+0+0 16-bit Grayscale Gray 10870B 0.000u 0:00.000
multiimage.tif[1] TIFF 600x600 600x600+0+0 16-bit Grayscale Gray 10870B 0.000u 0:00.000
multiimage.tif[2] TIFF 600x600 600x600+0+0 16-bit Grayscale Gray 10870B 0.000u 0:00.000

Then process them as an image sequence:然后将它们作为图像序列处理:

from PIL import Image, ImageSequence

im = Image.open("multiimage.tif")

index = 1
for frame in ImageSequence.Iterator(im):
    print(index)
    index = index + 1

I had the same problem and I found out that imageio can do the job:我遇到了同样的问题,我发现 imageio 可以完成这项工作:

img = imageio.imread('path/to/img', format='PNG-FI')

With this option you can read and write multi-channel 16-bit png images (by default imageio uses PNG-PIL as format for reading png files).使用此选项,您可以读取和写入多通道 16 位 png 图像(默认情况下 imageio 使用PNG-PIL作为读取 png 文件的格式)。 This works for png images, but changing the format can probably help when dealing with other image types ( here a full list of available imageio formats).这适用于 png 图像,但在处理其他图像类型时更改format可能会有所帮助(这里是可用 imageio 格式的完整列表)。

To use this format you may need to install the FreeImage plugin as shown in the documentation .要使用这种格式,您可能需要安装 FreeImage 插件,如文档中所示。

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

相关问题 Python:读写 TIFF 16 位、三通道、彩色图像 - Python: Read and write TIFF 16 bit , three channel , colour images 支持多渠道订阅者的Python可观察实现 - Python observable implementation that supports multi-channel subscribers 在 Pytorch 中使用 BCEWithLogitsLoss 的多通道 2D 掩码权重 - Multi-channel, 2D mask weights using BCEWithLogitsLoss in Pytorch 如何用多通道一维对象训练神经网络? - How to train neural networks with multi-channel 1D objects? 将多声道PyAudio转换为NumPy数组 - Convert multi-channel PyAudio into NumPy array 从多通道图像中提取通道名称 - extract channel names from a multi-channel image 使用 OpenCV 和 Numpy 从另一个图像中提取的像素坐标创建多通道图像 - Create a multi-channel image from pixel coordinates extracted from another image with OpenCV and Numpy 如何使用 python 读取单通道 32 位整数图像? - How can I read single-channel 32-bit integer images with python? 如何在python中使用opencv提取绿色通道? - How to extract green channel using opencv in python? 使用 Tensorflow 对象检测 API(或其他)为多通道图像提供更快的 RCNN - Faster RCNN for multi-channel images with Tensorflow Object Detection API (or others)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM