当前位置: 首页 > 面试题库 >

具有16位图像数据的Image.frombuffer

范飞翰
2023-03-14
问题内容

如果我的窗口处于32位色深模式,那么下面的代码将从窗口中获取漂亮的PIL图像:

def image_grab_native(window):
    hwnd = win32gui.GetDesktopWindow()

    left, top, right, bot = get_rect(window)
    w = right - left
    h = bot - top

    hwndDC = win32gui.GetWindowDC(hwnd)
    mfcDC  = win32ui.CreateDCFromHandle(hwndDC)
    saveDC = mfcDC.CreateCompatibleDC()

    saveBitMap = win32ui.CreateBitmap()
    saveBitMap.CreateCompatibleBitmap(mfcDC, w, h)

    saveDC.SelectObject(saveBitMap)
    saveDC.BitBlt((0, 0), (w, h),  mfcDC,  (left, top),  win32con.SRCCOPY)

    bmpinfo = saveBitMap.GetInfo()
    bmpstr = saveBitMap.GetBitmapBits(True)

    im = Image.frombuffer(
        'RGB',
        (bmpinfo['bmWidth'], bmpinfo['bmHeight']),
        bmpstr, 'raw', 'BGRX', 0, 1)

    win32gui.DeleteObject(saveBitMap.GetHandle())
    saveDC.DeleteDC()
    mfcDC.DeleteDC()
    win32gui.ReleaseDC(hwnd, hwndDC)

    return im

但是,以16位模式运行时,出现错误:

>>> image_grab_native(win)
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    image_grab_native(win)
  File "C:\claudiu\bumhunter\finderbot\ezpoker\utils\win32.py", line 204, in image_grab_native
    bmpstr, 'raw', 'BGRX', 0, 1)
  File "c:\python25\lib\site-packages\PIL\Image.py", line 1808, in frombuffer
    return apply(fromstring, (mode, size, data, decoder_name, args))
  File "c:\python25\lib\site-packages\PIL\Image.py", line 1747, in fromstring
    im.fromstring(data, decoder_name, args)
  File "c:\python25\lib\site-packages\PIL\Image.py", line 575, in fromstring
    raise ValueError("not enough image data")
ValueError: not enough image data

我应该如何形成frombuffer以16位模式工作的电话?另外,如何使该函数在任何位深度模式下都能工作,而不必说必须将其作为参数传递呢?

更新:从这个问题中,我了解到我必须对第二个模式参数使用“ BGR; 16”而不是“
BGRX”。它可以拍出正确的照片,无论是否指定步幅。问题是像素值在某些值上略有偏离:

x   y native           ImageGrab
280 0  (213, 210, 205) (214, 211, 206)
280 20 (156, 153, 156) (156, 154, 156)
280 40 (213, 210, 205) (214, 211, 206)
300 0  (213, 210, 205) (214, 211, 206)

只是从同一窗口获取的值样本。屏幕截图看起来和肉眼是一样的,但是我必须做一些像素操作。.我也想完全使用本机方法的原因是它速度更快,并且在带有双监视器的虚拟机中运行时表现更好。
(是的,我知道是非常随机的复杂问题)。


问题答案:

对于stride参数,您需要提供以字节为单位的行大小。您的像素均为16位,因此您可能会天真地假设stride = 2*bmpinfo['bmWidth'];不幸的是,Windows添加了填充以使步幅达到32位的偶数倍。这意味着您必须将其舍入到4的下一个最高倍数stride = (stride + 3) / 4) * 4

该文档没有提到16位原始格式,因此您必须检查Unpack.c模块以查看可用的格式。

您会注意到的最后一件事是Windows喜欢将其位图倒置。

编辑:
您最后的小问题很容易解释-从16位到24位的转换没有精确定义,并且两次不同转换之间的一对一差异是完全正常的。转换完数据后,调整数据并不难,因为我确信差异基于值是恒定的。



 类似资料:
  • 我得到了一个字节数组,存储了一个已经解构的DICOM文件中的16位像素数据。我现在需要做的是以某种方式将像素数据转换/导出为TIFF文件格式。我使用imageio-tiff-3.3.2.jar插件来处理tiff转换/头数据。但是现在我需要将该图像数据数组打包到原始图像维度的BufferedImage中,以便将其导出到TIFF。但是BufferedImage似乎不支持16位图像。有没有办法解决这个问

  • 当我以tiff格式打开一个16位图像时,它会以黑色图像的形式打开。16位tiff图像仅在程序ImageJ中打开;但是,它不会在预览中打开。我想知道我现在的选择是什么,以一种不降低分辨率的更简单的方式查看格式,而不是打开ImageJ查看它。我是否应该将其转换为8位格式,但当格式从16位减少到8位时,是否会丢失数据?另外,我正在考虑将tiff图像转换为jpeg,但这会导致分辨率降低吗?

  • 我是第一次使用openCV。我正在使用openCV3和XCode对其进行编码。我想创建一个16位的灰度图像,但我想我有的数据是这样定义的,4000是像素值为白色和0为黑色。我在int类型的数组中有这些像素的信息。如何创建Mat并将数组中的值分配给Mat?

  • 我想提取一个BufferedImage的矩形。 Javadoc提出了getSubImage(x,y,w,h)和getData(矩形)。 getData很酷,但我不想只需要光栅。我希望子图像作为BufferedImage对象,但我还需要它的数据数组的修改版本,但javadoc说 public BufferedImage getSubimage(int x,int y,int w,int h):返回由

  • 下面的Docker图像有什么不同? null 哪个尺寸更小,可以在Spring Boot项目中使用?

  • 我搜索过类似的问题,但没有找到解决方案。我有16位灰度图像,我正在尝试将它们放入keras ImageDataGenerator中。当使用诸如:flow_from_dataframe之类的函数时,它会生成所有具有相同像素值的图像(不正确)。 我尝试使用keras preprocess_输入,通过自定义预处理函数将其重新缩放到[0,1],再缩放到[-1,1],但这些都不起作用。我还在ImageDat