python - 进出 ModernGL 缓冲区的 Numpy 数组(使用 cv2 打开和保存)
问题描述
我想要:
- 通过 cv2而不是 ModernGL 的
load_texture_2d
方法从图像中打开纹理。 - 通过 cv2 而不是 Pillow保存生成的图像(在
write
方法中)。
我目前有以下代码:
from pathlib import Path
from array import array
import cv2
import numpy as np
from PIL import Image
import moderngl
import moderngl_window
class ImageProcessing(moderngl_window.WindowConfig):
window_size = 3840 // 2, 2160 // 2
resource_dir = Path(__file__).parent.resolve()
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.image_processing = ImageTransformer(self.ctx, self.window_size)
# Not working:
#img = cv2.imread("test6.png")
#self.texture = img.astype('f4')
self.texture = self.load_texture_2d("test6.png")
def render(self, time, frame_time):
# View in Window
self.image_processing.render(self.texture, target=self.ctx.screen)
# Headless
self.image_processing.render(self.texture)
self.image_processing.write("output.png")
class ImageTransformer:
def __init__(self, ctx, size, program=None):
self.ctx = ctx
self.size = size
self.program = None
self.fbo = self.ctx.framebuffer(
color_attachments=[self.ctx.texture(self.size, 4)]
)
# Create some default program if needed
if not program:
self.program = self.ctx.program(
vertex_shader="""
#version 330
in vec2 in_position;
in vec2 in_uv;
out vec2 uv;
void main() {
gl_Position = vec4(in_position, 0.0, 1.0);
uv = in_uv;
}
""",
fragment_shader = """
#version 330
uniform sampler2D image;
in vec2 uv;
out vec4 out_color;
void main() {
vec4 color = texture(image, uv);
// do something with color here
out_color = vec4(color.r, 0, 0, color.a);
}
""",
)
# Fullscreen quad in NDC
self.vertices = self.ctx.buffer(
array(
'f',
[
# Triangle strip creating a fullscreen quad
# x, y, u, v
-1, 1, 0, 1, # upper left
-1, -1, 0, 0, # lower left
1, 1, 1, 1, # upper right
1, -1, 1, 0, # lower right
]
)
)
self.quad = self.ctx.vertex_array(
self.program,
[
(self.vertices, '2f 2f', 'in_position', 'in_uv'),
]
)
def render(self, texture, target=None):
if target:
target.use()
else:
self.fbo.use()
texture.use(0)
self.quad.render(mode=moderngl.TRIANGLE_STRIP)
def write(self, name):
# This doesn't work:
raw = self.fbo.read(components=4, dtype='f4')
buf = np.frombuffer(raw, dtype='f4')
cv2.imwrite("OUTPUT_IMAGE.png", buf)
# But this does:
## image = Image.frombytes("RGBA", self.fbo.size, self.fbo.read())
## image = image.transpose(Image.FLIP_TOP_BOTTOM)
## image.save(name, format="png")
if __name__ == "__main__":
ImageProcessing.run()
目前,当代码按原样运行时,不会保存任何图像。窗口只是挂起,没有任何反应。我不确定我的代码是否有问题或数据类型是否错误。
枕头代码(如果您取消注释)可以保存它,但请注意:虽然我可以从 Pillow 转换为 numpy 数组,但我不希望在我的用例中这样做。
澄清:窗口加载并显示图像结果很好,但没有在write
方法中正确保存。
解决方案
您的应用程序中缺少 som 代码
该方法load_texture_2d
创建一个moderngl.Texture
对象。因此,该方法加载文件,创建纹理对象并将纹理图像从 CPU 加载到 GPU。
cv2.imread
只需将图像文件加载到 NumPy 数组,但它不会创建moderngl.Texture
对象。
您必须moderngl.Texture
从 NumPy 数组生成一个对象:
img = cv2.imread("test6.png")
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # optional
img = np.flip(img, 0).copy(order='C') # optional
self.texture = self.ctx.texture(img.shape[1::-1], img.shape[2], img)
在将缓冲区写入图像之前,您必须reshape
根据图像格式创建 NumPy 数组。例如:
raw = self.fbo.read(components=4, dtype='f1')
buf = np.frombuffer(raw, dtype='uint8').reshape((*self.fbo.size[1::-1], 4))
cv2.imwrite("OUTPUT_IMAGE.png", buf)
推荐阅读
- android - 如何区分 Android 中的主要和次要配置文件?
- google-search - 结构化数据中 Google 的 SearchAction - 来自 youtube.com VS 搜索 ebay.com 的结果
- haproxy - 带有 https 后端和 SNI 的 HAProxy
- matlab - 如何制作相应调整其大小的动态 GUI
- c++ - 如何使用二维数组计算和存储来自其他数组的值的频率?
- python - 为什么我的程序打印“这是一个素数”。两次?
- angular - 反应式表单,在 ngOnChanges 不更改模板后禁用表单控制
- python - 无法修复 StaleElementReferenceException(未附加到文档的元素)
- arduino - 如何将浮点数分成十六进制数组元素
- java - 需要多线程处理一个单一的请求并等待应答