Python、cv2.imshow()、树莓派和黑屏问题

3

目前正在尝试编写带有GUI的代码,可以切换图像处理的开关。理想情况下,该代码将允许打开/关闭窗口视图、实时图像处理(相当基础)以及控制外部板子。

我遇到的问题与cv2.imshow()函数有关。几个月前,我通过从picamera转换到cv2来提高处理速度,这样我就可以执行更复杂的计算,如背景减除,而不必一直调用python。使用bcm2835-v4l2包,我能够直接从picamera中使用cv2获取图像。

快进6个月,当我试图更新代码时,发现cv2.imshow()函数不再正确显示。我认为这可能是与bcm2835-v4l2有关的问题,但使用matplotlib进行测试表明连接良好。看起来似乎与cv2.imshow()有关,至少我猜是这样。

实际上,我正在使用threading模块创建一个单独的线程进行图像捕获,我想知道这是否可能是罪魁祸首。虽然我不这么认为,因为输入命令时......

import cv2
camera = cv2.VideoCapture(0)
grabbed,frame = camera.read()
cv2.imshow(frame)

生成相同的黑屏

下面是我正在使用的代码(在RPI3上),一些图像显示了错误和预期的内容。

至于我的系统详细信息,请参考以下内容

Raspberry pi3
raspi stretch
python 3.5.1
opencv 3.4.1

代码

import cv2
from threading import Thread
import time
import numpy as np
from tkinter import Button, Label, mainloop, Tk, RIGHT

class GPIOControllersystem:
    def __init__(self,OutPinOne=22, OutPinTwo=27,Objsize=30,src=0):
        self.Objectsize = Objsize

        # Build GUI controller
        self.TK = Tk()                                                          # Place TK GUI class into self

        # Variables
        self.STSP = 0
        self.ShutdownVar = 0
        self.Abut = []
        self.Bbut = []
        self.Cbut = []
        self.Dbut = []

        # setup pi camera for aquisition
        self.resolution = (640,480)
        self.framerate = 60

        # Video capture parameters
        (w,h) = self.resolution
        self.bytesPerFrame = w * h

        self.Camera = cv2.VideoCapture(src)
        self.fgbg = cv2.createBackgroundSubtractorMOG2()

    def Testpins(self):
        while True:
            grabbed,frame = self.Camera.read()
            frame = self.fgbg.apply(frame)

            if self.ShutdownVar ==1:
                break
            if self.STSP == 1:
                pic1, pic2 = map(np.copy,(frame,frame))
                pic1[pic1 > 126] = 255
                pic2[pic2 <250] = 0
                frame = pic1
            elif self.STSP ==1:
                time.sleep(1)
            cv2.imshow("Window",frame)
        cv2.destroyAllWindows()

    def MProcessing(self):
        Thread(target=self.Testpins,args=()).start()
        return self

    def BuildGUI(self):
        self.Abut = Button(self.TK,text = "Start/Stop System",command = self.CallbackSTSP)
        self.Bbut = Button(self.TK,text = "Change Pump Speed",command = self.CallbackShutdown)
        self.Cbut = Button(self.TK,text = "Shutdown System",command = self.callbackPumpSpeed)
        self.Dbut = Button(self.TK,text = "Start System",command = self.MProcessing)

        self.Abut.pack(padx=5,pady=10,side=RIGHT)
        self.Bbut.pack(padx=5,pady=10,side=RIGHT)
        self.Cbut.pack(padx=5,pady=10,side=RIGHT)
        self.Dbut.pack(padx=5,pady=10,side=RIGHT)
        Label(self.TK, text="Controller").pack(padx=5, pady=10, side=RIGHT)
        mainloop()

    def CallbackSTSP(self):
        if self.STSP == 1:
            self.STSP = 0
            print("stop")
        elif self.STSP == 0:
            self.STSP = 1
            print("start")

    def CallbackShutdown(self):
        self.ShutdownVar = 1

    def callbackPumpSpeed(self):
        pass

if __name__ == "__main__":
    GPIOControllersystem().BuildGUI()

使用matplotlib.pyplot.imshow(),我可以看到树莓派相机和opencv之间的连接是通过bcm2835-v4l2连接工作的。 使用系统捕获的帧图像,但使用matplotlib绘制 然而,在使用opencv.imshow()时,窗口会显示一个黑色方框,没有任何内容显示。 输入图像描述 更新:在测试中,我发现当我执行以下任务时。
import cv2
import matplotlib

camera = cv2.VideoCapture(0)
grab,frame = camera.read()
matplotlib.pyplot.imshow(frame)

grab,frame = camera.read()
matplotlib.pyplot.imshow(frame)

更新问题已解决,与主要问题无关。这是一个缓冲问题。似乎与cv2.imshow()没有任何相关性。


你检查过 frame 的 VideoCapture 是否实际返回图像数据了吗(跳过处理)?我猜如果你进一步最小化你的代码([mcve]),它将有助于你追踪根本原因。祝你好运! - handle
1
也许你需要在 cv2.imshow("Window",frame) 后面加上 cv2.waitKey(0)。希望这样能够解决问题。 - Ghantey
你好,我尝试将cv2.waitKey(0)加入代码中,但它并没有解决问题。我要看看这是否与Spyder有关(因为我使用Spyder进行编程和编辑)。 - Hojo.Timberwolf
猜猜我是怎么解决的?我在cv2.imshow('Window",frame)后面加上了cv2.waitKey(1)。经过查阅资料,cv2.waitKey()命令是显示图像所必需的。问题得到了解决。 - Hojo.Timberwolf
1个回答

0
在树莓派上进行编程,你应该使用以下代码: from picamera import PiCamera
请查看pyimagesearch获取更多信息。

这些是我最初设置树莓派并将opencv链接到python时使用的指南。非常有帮助的指南。尽管pyimagesearch的大多数示例都使用picamera模块,但据我所读,这可能会消耗大量处理能力,特别是当我计划进行实时处理时。我读到通过在cv2中保持所有采集,可以减少所需的处理能力,因此我选择了使用bcm2835-v4l2模块直接连接相机的cv2。 - Hojo.Timberwolf
有趣。我也在同一条路上。从过去的经验来看,黑色Imshow与初始化失败有关。你尝试将它保存为jpeg或avi了吗? - user3732793
在处理代码时,我收到了这个错误VIDEOIO ERROR: V4L2: Pixel format of incoming image is unsupported by OpenCV。我正在研究它,但很奇怪,因为V4L2最初是由opencv支持的。 - Hojo.Timberwolf
好的,祝你好运……如果你找到了答案并且想知道为什么其他人没有发现它,那将会很有趣。 - user3732793

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