如何将 OpenCV (cv2) 图像(BGR 和 BGRA)转换为 pygame.Surface 对象 [英] How do I convert an OpenCV (cv2) image (BGR and BGRA) to a pygame.Surface object

查看:67
本文介绍了如何将 OpenCV (cv2) 图像(BGR 和 BGRA)转换为 pygame.Surface 对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从

import os导入pygame导入 cv2将 numpy 导入为 npdef cv2ImageToSurface(cv2Image):如果 cv2Image.dtype.name == 'uint16':cv2Image = (cv2Image/256).astype('uint8')大小 = cv2Image.shape[1::-1]如果 len(cv2Image.shape) == 2:cv2Image = np.repeat(cv2Image.reshape(size[1], size[0], 1), 3,axis = 2)格式 = 'RGB'别的:格式 = 'RGBA' 如果 cv2Image.shape[2] == 4 else 'RGB'cv2Image[:, :, [0, 2]] = cv2Image[:, :, [2, 0]]表面 = pygame.image.frombuffer(cv2Image.flatten(), size, format)返回surface.convert_alpha() if format == 'RGBA' else surface.convert()pygame.init()窗口 = pygame.display.set_mode((400, 400))时钟 = 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)运行 = 真运行时:时钟滴答(60)对于 pygame.event.get() 中的事件:如果 event.type == pygame.QUIT:运行 = 错误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()

I created images from OpenCV/opencv-python (numpy.array) and I want to convert them to a pygame.Surface object:

def cv2ImageToSurface(cv2Image):

    pygameSurface = # ? create from "cv2Image"

    return pygameSurface 

surface = cv2ImageToSurface(cv2Image)

Some of the images have 3 channels (BGR) and some of the images also have an alpha channel (BGRA). What do I have to do in cv2ImageToSurface to convert images with one of the formats into a pygame.Surface object?

解决方案

The shape attribute of a numpy.array is the number of elements in each dimension. The first element is the height, the second the width and the third the number of channels.
A pygame.Surface can be generated by pygame.image.frombuffer. The 1st argument can be a numpy.array and the 2nd argument is the format (RGB or RGBA).

Get the size (widht, height) for the pygame.Surface object by slicing:

size = cv2Image.shape[1::-1]

Determine the target format for the pygame.Surface object, depending on the third channel:

format = 'RGBA' if cv2Image.shape[2] == 4 else 'RGB'

Since the source format is BGR or BGRA, but the target format is RGB or RGBA, the red and blue channels have to be swapped:

cv2Image[:, :, [0, 2]] = cv2Image[:, :, [2, 0]]

In the case of a grayscale image, the shape of the array must be changed using 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)

With his data the pygame.Surface object can be generated by pygame.image.frombuffer:

surface = pygame.image.frombuffer(cv2Image.flatten(), size, format)

To ensure that the image has the same pixel format as the display Surface and for optimal performance, the Surface should be converted with either convert or convert_alpha:

surface = surface.convert_alpha() if format == 'RGBA' else surface.convert()

Complete function 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()

Minimal example:

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 (cv2) 图像(BGR 和 BGRA)转换为 pygame.Surface 对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆