在Pygame表面内显示cv2.VideoCapture图像

8
我正在尝试使用opencv(cv2)将网络摄像头的视频流传输到pygame表面对象中。问题在于颜色显示不正确。我认为这是类型转换的问题,但我很难理解pygame表面文档以知道它所期望的内容。
以下代码演示了我的问题。
import pygame
from pygame.locals import *
import cv2
import numpy

color=False#True#False
camera_index = 0
camera=cv2.VideoCapture(camera_index)
camera.set(3,640)
camera.set(4,480)

#This shows an image the way it should be
cv2.namedWindow("w1",cv2.CV_WINDOW_AUTOSIZE)
retval,frame=camera.read()
if not color:
    frame=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
cv2.flip(frame,1,frame)#mirror the image
cv2.imshow("w1",frame)

#This shows an image weirdly...
screen_width, screen_height = 640, 480
screen=pygame.display.set_mode((screen_width,screen_height))

def getCamFrame(color,camera):
    retval,frame=camera.read()
    if not color:
        frame=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
    frame=numpy.rot90(frame)
    frame=pygame.surfarray.make_surface(frame) #I think the color error lies in this line?
    return frame

def blitCamFrame(frame,screen):
    screen.blit(frame,(0,0))
    return screen

screen.fill(0) #set pygame screen to black
frame=getCamFrame(color,camera)
screen=blitCamFrame(frame,screen)
pygame.display.flip()

running=True
while running:
    for event in pygame.event.get(): #process events since last loop cycle
        if event.type == KEYDOWN:
            running=False
pygame.quit()
cv2.destroyAllWindows()

我的最终目标是创建一个小型的照片亭应用程序,为明年的DIY婚礼提供服务。我对编程很陌生,但我设法把它拼凑在一起了。我还试图使用VideoCapture来实现这个目标,但输出的PIL也无法与surface对象配合使用。我想使用pygame surface,这样我就可以添加动画和叠加倒计时文本、边框等元素。
更新:问题在于cv2函数camera.read()返回一个BGR图像,而pygame.surfarray期望一个RGB图像。这个问题可以通过以下代码解决:
frame=cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)

此外,当转换为灰度图像时,以下代码有效:
frame=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
frame=cv2.cvtColor(frame,cv2.COLOR_GRAY2RGB)

因此,函数getCamFrame现在应该是这样的:
def getCamFrame(color,camera):
    retval,frame=camera.read()
    frame=cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
    if not color:
        frame=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
        frame=cv2.cvtColor(frame,cv2.COLOR_GRAY2RGB)
    frame=numpy.rot90(frame)
    frame=pygame.surfarray.make_surface(frame)
return frame

3
我本打算进来回答你的问题,因为它被列为未解答的问题。最好把你的解决方案发布并接受为自我回答,而不是将其放在问题中。 - KobeJohn
你应该接受我的答案,因为它解决了你的颜色问题。而不是更新你的问题与解决方案。 - Transformer
9年太晚了。 - chai
3个回答

2
没有,颜色错误在这里。
frame=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)

所以对于普通屏幕颜色,您只需将其更改为:
frame=cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)

这对我有用,就行了


1
我尝试了你的代码,但只得到了一张图片而不是电影,所以我复制了。
frame=getCamFrame(color,camera)
screen=blitCamFrame(frame,screen)
pygame.display.flip()

将其放入while循环后,它可以工作,但是视频被翻转了。为了解决这个问题,在getcamFrame函数中,我添加了cv2.flip(frame,1,frame) # mirror the image,然后再加上frame=numpy.rot90(frame),现在一切都正常了。

对于糟糕的英语表示抱歉。


0

这对我有用

要在您的代码中进行适应...

windowSurface = screen  #or use directly variable screen

    # convert windowSurface to cv2 ------------------------------------
    view = pygame.surfarray.array3d(windowSurface)
    #  convert from (width, height, channel) to (height, width, channel)
    view = view.transpose([1, 0, 2])
    #  convert from rgb to bgr
    img_bgr = cv2.cvtColor(view, cv2.COLOR_RGB2BGR)
    cv2.imshow('windowname',img_bgr)
    cv2.waitKey(10)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接