Pi Camera черные полосы в видео подаче - PullRequest
0 голосов
/ 09 марта 2019

В настоящее время я запускаю этот код с помощью Thonny на Raspberry Pi 3. Это приложение, которое помещает прямую трансляцию кадров Pi Camera на холст Tkinter. Затем пользователь может нажать кнопку «Захват», чтобы захватить кадр и сохранить его. Кнопки «Touch to Charge» и «Touch to Retrieve» просто переключаются между тем, чтобы сделать cancas видимым / невидимым. Это намного больше, чем сейчас, но сейчас все, что меня интересует, это почему эти черные полосы появляются на ленте. Спасибо!

GUI layout without video feed canvas visible

GUI layout with video feed canvas and black bars

another picture of the black bars

Вот мой код

import tkinter
import cv2
import PIL.Image, PIL.ImageTk
import time

state = 0           # state of canvas
inUse = 0           # make inUse = 1 at the end

class App:

    global state
    global inUse



    def __init__(self, window, window_title, video_source=0):
        self.window = window
        self.window.title(window_title)
        self.video_source = video_source

        # open video source (by default this will try to open the computer webcam)
        self.vid = MyVideoCapture(self.video_source)

        # Create a canvas that can fit the above video source size
       # self.canvas = tkinter.Canvas(window, width = self.vid.width, height = self.vid.height)

        self.canvas = tkinter.Canvas(window, width=2000, height=2000)

        # Button that lets the user take a snapshot
        self.btn_snapshot=tkinter.Button(window, text="Snapshot", width=35, command=self.snapshot)

        self.btn_state=tkinter.Button(window, text="Enable/Disable", width=35, command=self.closeWindow)

        # use lambda with command if you need to use anything
        self.chargeBT=tkinter.Button(window, text="Touch to Charge", width=25, height=3, command=self.chargeAction)
        self.retrieveBT=tkinter.Button(window, text="Touch to Retrieve", width=25, height=3, command=self.chargeAction)

        self.btn_snapshot.pack(anchor=tkinter.W)
        self.btn_state.pack(anchor=tkinter.W)
        self.chargeBT.place(relx=0.4, rely=0.8)
        self.retrieveBT.place(relx=0.7, rely=0.8)
        self.canvas.pack(anchor=tkinter.CENTER)

        self.canvas.pack_forget()


        # After it is called once, the update method will be automatically called every delay milliseconds
        self.delay = 15
        self.update()

        self.window.geometry("800x480")
        self.window.mainloop()

    def snapshot(self):
        # Get a frame from the video source
        ret, frame = self.vid.get_frame()

        if ret:
            cv2.imwrite("frame-" + time.strftime("%d-%m-%Y-%H-%M-%S") + ".jpg", cv2.cvtColor(frame, cv2.COLOR_RGB2BGR))

    def closeWindow(self):
        global state

        if state == 0:
            self.canvas.pack()
            state = 1

        else:
            self.canvas.pack_forget()
            state = 0

        #self.window.destroy()

    def update(self):
        # Get a frame from the video source
        ret, frame = self.vid.get_frame()

        if ret:
            frame = cv2.flip(frame,1)

            self.photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(frame))
            self.canvas.create_image(0, 0, image = self.photo, anchor = tkinter.NW)

        self.window.after(self.delay, self.update)

    def chargeAction(self):
        global inUse

        if inUse == 0:
            print("Im in!!!")
            self.btn_state.configure(text="YOYOYO")
            self.canvas.pack(anchor=tkinter.CENTER)
            inUse = 1

        else:
            print("Sorry this locker is in use")
            self.canvas.pack_forget()
            inUse = 0



class MyVideoCapture:
    def __init__(self, video_source=0):
        # Open the video source
        self.vid = cv2.VideoCapture(video_source)

        rval, frame = self.vid.read()

        self.vid.set(3, 200)
        self.vid.set(4, 200)

        """ change resolution
        cap.set(3,1280)
        cap.set(4,1024)

        """

        if not self.vid.isOpened():
            raise ValueError("Unable to open video source", video_source)

        # Get video source width and height
        self.width = self.vid.get(cv2.CAP_PROP_FRAME_WIDTH)
        self.height = self.vid.get(cv2.CAP_PROP_FRAME_HEIGHT)

    def get_frame(self):
        if self.vid.isOpened():
            ret, frame = self.vid.read()
            if ret:
                # Return a boolean success flag and the current frame converted to BGR
                return (ret, cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
            else:
                return (ret, None)
        else:
            return (ret, None)

    # Release the video source when the object is destroyed
    def __del__(self):
        if self.vid.isOpened():
            self.vid.release()

# Create a window and pass it to the Application object
App(tkinter.Tk(), "Tkinter and OpenCV")
...