假設我有一個 RGB 影像,每個像素存盤在原始記憶體緩沖區中 3 個位元組。在numpy我能夠ndarray使用以下代碼從這樣的原始緩沖區創建一個:
import ctypes
import numpy as np
# ...
shp = (image.height, image.width, 3)
ptr = ctypes.cast(image.ptr, ctypes.POINTER(ctypes.c_ubyte))
arr = np.ctypeslib.as_array(ptr, shape=shp)
image.ptr指向已分配緩沖區的實際本機指標在哪里。這似乎適用于微不足道的步幅/行大小,但很常見的是找到行大小可能大于實際需要的位圖記憶體布局。例如,Windows GDI PixelFormat24bppRGB位圖的行大小是可以使用公式計算的最接近 4 的倍數4 * (3 * width 3) / 4)。如何修改上述代碼以創建ndarray正確訪問此類自定義位圖記憶體布局的代碼?
uj5u.com熱心網友回復:
您可以使用np.lib.stride_tricks.as_strided. 這是一個跳過基于 RGBA 的(H,W,4)影像陣列的 alpha 通道的示例:
# Create the example image raw array
arr = np.arange(16).astype(np.uint8).reshape(4,4)
print(arr)
print(arr.strides)
# Create a view so to skip some items (possibly to support padding)
arrView = np.lib.stride_tricks.as_strided(arr, shape=(4, 3), strides=(4, 1))
print(arrView)
print(arrView.strides)
結果是:
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
(4, 1)
[[ 0 1 2]
[ 4 5 6]
[ 8 9 10]
[12 13 14]]
(4, 1)
正如檔案所述,必須非常小心地使用此功能(如果使用不當,請做好崩潰的準備)。
uj5u.com熱心網友回復:
@JeromeRichard的答案是正確的。在這里,它遵循一個片段,該片段完全模擬了我的問題中的用例,即 24bpp 跨步 rgb 位圖:
import ctypes
import numpy as np
width = 50
height = 50
rowsize = 4 * int((3 * 50 3) / 4)
rgb_buff_size = rowsize * height
# Prepare a test byte array and access the native pointer
# https://stackoverflow.com/a/73640146/213871
test_rgb_buff = np.arange(rgb_buff_size).astype(np.uint8).reshape(1, rgb_buff_size)
buff_ptr = test_rgb_buff.ctypes.data
# Create the view from the pointer
rgb_buff_view = np.ctypeslib.as_array(ctypes.cast(buff_ptr, ctypes.POINTER(ctypes.c_ubyte)), shape=(1, rgb_buff_size))
# Create the 3 channel strided view
rgb_strided_view = np.lib.stride_tricks.as_strided(rgb_buff_view, shape=(width, height, 3), strides=(rowsize, 3, 1))
print("type: " str(rgb_strided_view.dtype))
print("shape: " str(rgb_strided_view.shape))
print("strides: " str(rgb_strided_view.strides))
這將列印以下內容:
type: uint8
shape: (50, 50, 3)
strides: (152, 3, 1)
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/519699.html
