首页 > 解决方案 > 相机视频和使用 Python Kivy 拍照

问题描述

我正在使用屏幕管理器,并希望在访问 ScreenThree 时显示相机图像。我希望使用 cv2 相机代码。单击按钮后,我希望捕获一张图片,然后使用该图像执行代码。到目前为止,我在互联网上找到了一个线程版本,可以很好地显示相机输入。通过单击按钮捕获图片正在挫败我的努力。

Screen3 包含一个放置视频的地方和一个执行代码拍照的按钮。

<ScreenThree>:
    name: "screenthree"
    FloatLayout:
        Image:
            id: vid    #Vido image
            pos_hint: {'x':0.0, 'y':0.2}
            size_hint: 1.0, 0.8
        Image:
            source: "clue.png" # Decorative image
            size_hint:(0.20,0.20)
            pos_hint: {"x":0.05,"y":0.75}
        Button:
            text: "Click to scan"
            background_color : 0, 0, 1, 1
            size_hint: 0.2,0.05
            pos_hint: {"x":0.25,"y":0.85}
            on_press: root.takepic()
        Button:
            text: "Go to next screen"      # Screen4
            background_color : 1, 0, 1, 1
            size_hint: 0.2,0.05
            pos_hint: {"x":0.45,"y":0.85}
            on_press:
                root.manager.transition.direction = 'left'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_four'

线程代码是(我不知道隐藏窗口是关于什么的);

class ScreenApp(App):
    def build(self):
        threading.Thread(target=self.doit, daemon=True).start()
        self.new_screen = ScreenThree()
        return screen_manager

    def doit(self):
        self.do_vid = True
        cv2.namedWindow('Hidden', cv2.WINDOW_NORMAL | cv2.WINDOW_FREERATIO)
        cv2.resizeWindow('Hidden', 0, 0)
        cam=cv2.VideoCapture('/dev/video0', cv2.CAP_V4L)

        while (self.do_vid):
            ret, frame = cam.read()
            Clock.schedule_once(partial(self.display_frame, frame))
            cv2.imshow('Hidden', frame)
            cv2.waitKey(1)
        cam.release()
        cv2.destroyAllWindows()

    def display_frame(self, frame, dt):
        texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt='bgr')
        texture.blit_buffer(frame.tobytes(order=None), colorfmt='bgr', bufferfmt='ubyte')
        texture.flip_vertical()

        self.root.get_screen('screen_three').ids.vid.texture = texture

我将捕获图像的代码放在 ScreenThree 类中。单击按钮会转移到 takepic() 方法,但无法读取图像,尝试写入空图像时会崩溃。/dev/video0 上的摄像头仍由线程代码持有。如何访问相机以捕捉照片,或者如何提示线程例程为我拍照。

class ScreenThree(Screen):
    def takepic(self):
        cap = cv2.VideoCapture('/dev/video0', cv2.CAP_V4L)

        # set dimensions
        cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
        cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)

        # take frame
        ret, frame = cap.read()
        # write frame to file
        cv2.imwrite('image.jpg', frame)
        # release camera
        cap.release()

标签: pythonmultithreadingimagecamerakivy

解决方案


由于您的线程已经从相机捕获帧,您可以只使用已捕获的当前帧,如下所示:

def doit(self):
    self.do_vid = True
    self.frame = None  # add reference to the current frame
    cv2.namedWindow('Hidden', cv2.WINDOW_NORMAL | cv2.WINDOW_FREERATIO)
    cv2.resizeWindow('Hidden', 0, 0)
    cam=cv2.VideoCapture('/dev/video0', cv2.CAP_V4L)

    while (self.do_vid):
        ret, self.frame = cam.read()  # save the current frame
        Clock.schedule_once(partial(self.display_frame, self.frame))
        cv2.imshow('Hidden', self.frame)
        cv2.waitKey(1)
    cam.release()
    cv2.destroyAllWindows()

在方法中使用当前帧takepic()

class ScreenThree(Screen):
    def takepic(self):
        # get current frame
        frame = App.get_running_app().frame
        # write frame to file
        cv2.imwrite('image.jpg', frame)

推荐阅读