如何将 OpenCV (cv2) 图像(BGR 和 BGRA)转换为 pygame.Surface 对象
How do I convert an OpenCV (cv2) image (BGR and BGRA) to a pygame.Surface object
我从 OpenCV/opencv-python (numpy.array
) and I want to convert them to a pygame.Surface
对象创建图像:
def cv2ImageToSurface(cv2Image):
pygameSurface = # ? create from "cv2Image"
return pygameSurface
surface = cv2ImageToSurface(cv2Image)
一些图像有 3 个通道 (BGR),一些图像也有一个 alpha 通道 (BGRA)。在 cv2ImageToSurface
中我需要做什么才能将其中一种格式的图像转换为 pygame.Surface
对象?
numpy.array
的 shape
属性是每个维度中的元素数。第一个元素是高度,第二个元素是宽度,第三个元素是通道数。
一个pygame.Surface
can be generated by pygame.image.frombuffer
。第一个参数可以是 numpy.array
,第二个参数是格式(RGB
或 RGBA
)。
通过切片获取pygame.Surface
对象的大小(宽度、高度):
size = cv2Image.shape[1::-1]
根据第三个通道确定pygame.Surface
对象的目标格式:
format = 'RGBA' if cv2Image.shape[2] == 4 else 'RGB'
由于源格式为BGR或BGRA,但目标格式为RGB或RGBA,必须交换红色和蓝色通道:
cv2Image[:, :, [0, 2]] = cv2Image[:, :, [2, 0]]
在灰度图像的情况下,必须使用 numpy.reshape
and the gray channel must be expanded to a red-green and blue color channel using numpy.repeat
更改数组的形状:
cv2Image = np.repeat(cv2Image.reshape(size[1], size[0], 1), 3, axis = 2)
根据他的数据,pygame.Surface
对象可以通过 pygame.image.frombuffer
:
生成
surface = pygame.image.frombuffer(cv2Image.flatten(), size, format)
为确保图像具有与显示器 Surface 相同的像素格式并获得最佳性能,应将 Surface 转换为convert
or convert_alpha
:
surface = surface.convert_alpha() if format == 'RGBA' else surface.convert()
完整功能cv2ImageToSurface
:
def cv2ImageToSurface(cv2Image):
if cv2Image.dtype.name == 'uint16':
cv2Image = (cv2Image / 256).astype('uint8')
size = cv2Image.shape[1::-1]
if len(cv2Image.shape) == 2:
cv2Image = np.repeat(cv2Image.reshape(size[1], size[0], 1), 3, axis = 2)
format = 'RGB'
else:
format = 'RGBA' if cv2Image.shape[2] == 4 else 'RGB'
cv2Image[:, :, [0, 2]] = cv2Image[:, :, [2, 0]]
surface = pygame.image.frombuffer(cv2Image.flatten(), size, format)
return surface.convert_alpha() if format == 'RGBA' else surface.convert()
最小示例:
import os
import pygame
import cv2
import numpy as np
def cv2ImageToSurface(cv2Image):
if cv2Image.dtype.name == 'uint16':
cv2Image = (cv2Image / 256).astype('uint8')
size = cv2Image.shape[1::-1]
if len(cv2Image.shape) == 2:
cv2Image = np.repeat(cv2Image.reshape(size[1], size[0], 1), 3, axis = 2)
format = 'RGB'
else:
format = 'RGBA' if cv2Image.shape[2] == 4 else 'RGB'
cv2Image[:, :, [0, 2]] = cv2Image[:, :, [2, 0]]
surface = pygame.image.frombuffer(cv2Image.flatten(), size, format)
return surface.convert_alpha() if format == 'RGBA' else surface.convert()
pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
cv2Image1 = cv2.imread('woodtiles.jpg', cv2.IMREAD_GRAYSCALE)
cv2Image2 = cv2.imread('woodtiles.jpg', cv2.IMREAD_UNCHANGED)
cv2Image3 = cv2.imread('Apple1-256.png', cv2.IMREAD_UNCHANGED)
pygameSurface1 = cv2ImageToSurface(cv2Image1)
pygameSurface2 = cv2ImageToSurface(cv2Image2)
pygameSurface3 = cv2ImageToSurface(cv2Image3)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.fill(0)
window.blit(pygameSurface1, pygameSurface1.get_rect(topleft = window.get_rect().inflate(-10, -10).topleft))
window.blit(pygameSurface2, pygameSurface2.get_rect(center = window.get_rect().center))
window.blit(pygameSurface3, pygameSurface3.get_rect(bottomright = window.get_rect().inflate(-10, -10).bottomright))
pygame.display.flip()
pygame.quit()
我从 OpenCV/opencv-python (numpy.array
) and I want to convert them to a pygame.Surface
对象创建图像:
def cv2ImageToSurface(cv2Image):
pygameSurface = # ? create from "cv2Image"
return pygameSurface
surface = cv2ImageToSurface(cv2Image)
一些图像有 3 个通道 (BGR),一些图像也有一个 alpha 通道 (BGRA)。在 cv2ImageToSurface
中我需要做什么才能将其中一种格式的图像转换为 pygame.Surface
对象?
numpy.array
的 shape
属性是每个维度中的元素数。第一个元素是高度,第二个元素是宽度,第三个元素是通道数。
一个pygame.Surface
can be generated by pygame.image.frombuffer
。第一个参数可以是 numpy.array
,第二个参数是格式(RGB
或 RGBA
)。
通过切片获取pygame.Surface
对象的大小(宽度、高度):
size = cv2Image.shape[1::-1]
根据第三个通道确定pygame.Surface
对象的目标格式:
format = 'RGBA' if cv2Image.shape[2] == 4 else 'RGB'
由于源格式为BGR或BGRA,但目标格式为RGB或RGBA,必须交换红色和蓝色通道:
cv2Image[:, :, [0, 2]] = cv2Image[:, :, [2, 0]]
在灰度图像的情况下,必须使用 numpy.reshape
and the gray channel must be expanded to a red-green and blue color channel using numpy.repeat
更改数组的形状:
cv2Image = np.repeat(cv2Image.reshape(size[1], size[0], 1), 3, axis = 2)
根据他的数据,pygame.Surface
对象可以通过 pygame.image.frombuffer
:
surface = pygame.image.frombuffer(cv2Image.flatten(), size, format)
为确保图像具有与显示器 Surface 相同的像素格式并获得最佳性能,应将 Surface 转换为convert
or convert_alpha
:
surface = surface.convert_alpha() if format == 'RGBA' else surface.convert()
完整功能cv2ImageToSurface
:
def cv2ImageToSurface(cv2Image):
if cv2Image.dtype.name == 'uint16':
cv2Image = (cv2Image / 256).astype('uint8')
size = cv2Image.shape[1::-1]
if len(cv2Image.shape) == 2:
cv2Image = np.repeat(cv2Image.reshape(size[1], size[0], 1), 3, axis = 2)
format = 'RGB'
else:
format = 'RGBA' if cv2Image.shape[2] == 4 else 'RGB'
cv2Image[:, :, [0, 2]] = cv2Image[:, :, [2, 0]]
surface = pygame.image.frombuffer(cv2Image.flatten(), size, format)
return surface.convert_alpha() if format == 'RGBA' else surface.convert()
最小示例:
import os
import pygame
import cv2
import numpy as np
def cv2ImageToSurface(cv2Image):
if cv2Image.dtype.name == 'uint16':
cv2Image = (cv2Image / 256).astype('uint8')
size = cv2Image.shape[1::-1]
if len(cv2Image.shape) == 2:
cv2Image = np.repeat(cv2Image.reshape(size[1], size[0], 1), 3, axis = 2)
format = 'RGB'
else:
format = 'RGBA' if cv2Image.shape[2] == 4 else 'RGB'
cv2Image[:, :, [0, 2]] = cv2Image[:, :, [2, 0]]
surface = pygame.image.frombuffer(cv2Image.flatten(), size, format)
return surface.convert_alpha() if format == 'RGBA' else surface.convert()
pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
cv2Image1 = cv2.imread('woodtiles.jpg', cv2.IMREAD_GRAYSCALE)
cv2Image2 = cv2.imread('woodtiles.jpg', cv2.IMREAD_UNCHANGED)
cv2Image3 = cv2.imread('Apple1-256.png', cv2.IMREAD_UNCHANGED)
pygameSurface1 = cv2ImageToSurface(cv2Image1)
pygameSurface2 = cv2ImageToSurface(cv2Image2)
pygameSurface3 = cv2ImageToSurface(cv2Image3)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.fill(0)
window.blit(pygameSurface1, pygameSurface1.get_rect(topleft = window.get_rect().inflate(-10, -10).topleft))
window.blit(pygameSurface2, pygameSurface2.get_rect(center = window.get_rect().center))
window.blit(pygameSurface3, pygameSurface3.get_rect(bottomright = window.get_rect().inflate(-10, -10).bottomright))
pygame.display.flip()
pygame.quit()