Numpy用于RAW图像导入的dtype=uint10、uint12、uint14的解决方法:

huangapple go评论67阅读模式
英文:

Numpy workaround for dtype=uint10, uint12, uint14 for RAW image import

问题

将16位无符号原始(图像)数据导入Python很简单:

data = numpy.fromfile( source_file, dtype=numpy.uint16 )
data = numpy.asarray( data )

但我还必须导入10、12和14位无符号整数数据,以便将这些数据编码为专有的图像格式。该格式简单地接受带有唯一标头的16位或32位整数数组。NumPy没有实现10、12和14位数据类型。

当我将10、12或14位RAW在ImageJ中以16位无符号图像(这是ImageJ中最小的可用无符号位深度)打开时,它看起来很奇怪,但像素都位于正确的位置。这是错误的位深度,所以我不感到惊讶。

然而,如果我在ImageJ中使用小端字节顺序打开RAW,那么10位图像在ImageJ中会完美地显示为16位无符号图像。所以我在Python中尝试了这个:

image_bitness = numpy.uint16
image_bitness = numpy.dtype( image_bitness ).newbyteorder( '<' )
data = numpy.fromfile( source_file, dtype=image_bitness )
data = numpy.asarray( data )

在Python中将字节顺序切换为小端没有效果。当我在Python中进行图像转换成新格式,然后在ImageJ中打开这个新图像时,图像仍然看起来很奇怪。

我已经为16位和32位无符号RAW实施了相同的文件转换,它完美地工作。

所以总结一下:

  • 对于10、12或14位无符号数据类型,实际的解决方法尚不清楚

  • 不确定如何将10位转换为16位,特别是如果我必须假定16位来调用numpy.fromfile( source_file, dtype=numpy.uint16 )以最初获取数据数组(请参见附录)

  • 不确定为什么ImageJ的小端显示图像是正确的。将小端图像视为大端图像可能会彻底破坏图像。也许我弄错了。

  • 不确定为什么在Python中交换字节顺序没有与ImageJ相同的效果

示例10位图像

在ImageJ中没有"little endian"显示时,像素显示不正确。在Python中转换为新文件格式的图像如下所示:
Numpy用于RAW图像导入的dtype=uint10、uint12、uint14的解决方法:
在ImageJ中有"little endian"显示时,像素显示正确:
Numpy用于RAW图像导入的dtype=uint10、uint12、uint14的解决方法:

附录:用于获取16位的二进制的填充

我认为可以用0来填充我的二进制数,然后转换回十进制整数。我尝试了这个:

data = numpy.fromfile( source_file, dtype=numpy.uint16 ) #仍然适用于10位图像?
for i in data:
      data[i] = int( bin( data[i] )[2:].zfill(16), 2 )
data = numpy.asarray( data ) 

这将0000001011转换为0000000000001011作为字符串,然后将该字符串转换回十进制整数。

然而,当我在转换后在ImageJ中打开我的图像时,它仍然看起来很奇怪。我假设这是因为00000010110000000000001011以及1011仍然是相同的数字。如何强制分配更多内存?

我还尝试通过交换字节来交换字节顺序:

for i in data:
      data[i] = int( bin( data[i] )[2:].zfill(16)[::-1], 2 )

这将使我的字符串变成0001变成1000。结果是相同的。在ImageJ中仍然是一个奇怪的图像。

英文:

Importing 16-bit unsigned raw (image) data into python is simple:

data = numpy.fromfile( source_file, dtype=numpy.uint16 )
data = numpy.asarray( data )

But I must also import 10, 12, and 14-bit unsigned integer data so I can encode those data into a proprietary image format. The format simply accepts an array of 16 or 32-bit integers with a unique header. Numpy has no implementation for 10, 12, and 14-bit data types.

When I open 10, 12, or 14-bit RAW in ImageJ as a 16-bit unsigned image (this is the smallest available unsigned bit depth for ImageJ), it looks funny, but the pixels are all in the correct location. This is the wrong bit depth, so I'm not surprised.

However, if I open the RAW in ImageJ with little endian byte order, the 10-bit image displays perfectly as a 16-bit unsigned image inside ImageJ. So I try this in Python:

image_bitness = numpy.uint16
image_bitness = numpy.dtype( image_bitness ).newbyteorder( &#39;&lt;&#39; )
data = numpy.fromfile( source_file, dtype=image_bitness )
data = numpy.asarray( data )

Swapping the byte order to little endian has no effect in python. The image still looks funny when I conduct the image conversion in python into the new format, then open this new image in ImageJ.

I have implemented this same file conversion for 16 and 32-bit unsigned RAW and it works perfectly.

So to summarize:

  • An actual work-around for 10, 12, or 14-bit unsigned data types is the issue

  • Not sure how best to convert from 10 to 16-bit generally, especially if I must assume 16-bit to call numpy.fromfile( source_file, dtype=numpy.uint16 ) to get an array of data initially (see Appendix)

  • Not sure why ImageJ little endian displays the image correctly. Viewing a little endian image as big endian should probably scramble the image entirely. Maybe I'm mistaken.

  • Not sure why swapping byte order in Python does not have the same effect as ImageJ

Example 10-bit images

Incorrectly displayed pixels without "little endian" in ImageJ. Images converted in Python into new file format look like this:
Numpy用于RAW图像导入的dtype=uint10、uint12、uint14的解决方法:
Correctly displayed pixels with "little endian" in ImageJ:
Numpy用于RAW图像导入的dtype=uint10、uint12、uint14的解决方法:

Appendix: Padding base-2 binary to get 16-bits

I thought I could pad out my base-2 binary number with 0s, then convert back to base-10 integer. I tried this:

data = numpy.fromfile( source_file, dtype=numpy.uint16 ) #still compiles for 10-bit image?    
for i in data:
      data[i] = int( bin( data[i] )[2:].zfill(16), 2 )
data = numpy.asarray( data ) 

This converts 0000001011 to 0000000000001011 as a string, then converts that string back to a base-10 integer.

However - when I open my image in ImageJ after the conversion, it still looks funky. I'm assuming this is because 0000001011 and 0000000000001011 and 1011 are still the same number. How do I basically enforce greater memory allocation?

I also tried to swap the byte order by literally swapping the bytes:

for i in data:
      data[i] = int( bin( data[i] )[2:].zfill(16)[::-1], 2 )

This will transpose my string so 0001 becomes 1000. The result is the same. Still a funny-looking image in ImageJ.

答案1

得分: 0

import cv2
import numpy as np

# 定义参数
w, h, bytesPerPixel = 1392, 1040, 2

# 加载图像
data = np.fromfile('10bit_1392x1040_10Frames.raw', dtype=np.uint16, offset=0, count=w*h).reshape((h, w)) << 6

# 保存
cv2.imwrite('result.png', data)

如果您的数据是12位将左移位从6更改为4如果是14位将左移位从6更改为2

如果要获取第N帧请将偏移量更改为 `N * w * h * bytesPerPixel`,因为它是以字节而不是样本来衡量的
英文:

It's as simple as this:

import cv2
import numpy as np

# Define parameters
w, h, bytesPerPixel = 1392, 1040, 2

#&#160;Load image
data = np.fromfile(&#39;10bit_1392x1040_10Frames.raw&#39;, dtype=np.uint16, offset=0, count=w*h).reshape((h,w)) &lt;&lt; 6

#&#160;Save
cv2.imwrite(&#39;result.png&#39;, data)

If your data is 12-bit, change the left-shift from 6 to 4. If 14-bit, change the left-shift from 6 to 2.

If you want the Nth frame, change the offset to N * w * h * bytesPerPixel because it is measured in bytes not samples.

huangapple
  • 本文由 发表于 2023年2月24日 06:16:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/75550881.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定