我要:
load_texture_2d
方法从图像中打开纹理。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)
谢谢你。它可以工作,但是我必须使用转换颜色
cv2.COLOR_BGR2RGB
并删除,np.flip
以得到具有正确颜色和旋转度的输出图像。我应该修改您的答案以解决此问题吗?我看到了@correctsyntax。这取决于源映像和系统。谢谢你。别客气。