admin管理员组

文章数量:1124791

I'm dealing with an app that allows the use of the webcam. To interact with the camera, I used the open-cv python package. I developed a simple Flet app with a button to start /stop capturing frames from the webcam that are displayed into a container.

import flet as ft
import cv2
import base64

class WebcamManager():
    def __init__(self):
        super().__init__()
        self.webcam = None
                 
    def initialize(self):
        try:
            self.webcam = cv2.VideoCapture(index=0, apiPreference=cv2.CAP_DSHOW)
            if not self.webcam.isOpened():
                print("Cannot open camera")
                exit()
            else:    
                # Set new capture properties
                ret = self.webcam.set(cv2.CAP_PROP_FRAME_WIDTH, value=1280.0)
                ret = self.webcam.set(cv2.CAP_PROP_FRAME_HEIGHT, value=720.0) 

                print("webcam.isOpened(): ", self.webcam.isOpened())
        except Exception as e:
            print(e)



    # THIS VERSION OF CAPTURING UPDATING THE CONTAINER CAUSES INTERMITTENT VIDEO  
    # def capture_from_webcam(self, container: ft.Container):
    #     while True:
    #         ret, frame = self.webcam.read()
    #         if ret:
    #             frame = cv2.resize(frame,(854,480))
    #             _, img_arr = cv2.imencode('.png', frame)
    #             img_b64 = base64.b64encode(img_arr)
    #             container.content = ft.Image(src_base64 = img_b64.decode("utf-8"))
    #             container.update()


    
    def capture_from_webcam(self, ftImg: ft.Image):
        while True:
            ret, frame = self.webcam.read()
            if ret:
                frame = cv2.resize(frame,(854,480))
                _, img_arr = cv2.imencode('.png', frame)
                img_b64 = base64.b64encode(img_arr)
                ftImg.src_base64 = img_b64.decode("utf-8")
                ftImg.update()

    def dispose(self):
        try:
            self.webcam.release()
            print("webcam.isOpened(): ", self.webcam.isOpened()) 
        except Exception as e:
            print(e)


def main(page: ft.Page):        
    def button_play_clicked(e):
        if e.control.data: # case: running -> not running
            button_play.data = False
            button_play.icon = ft.icons.CAMERA
            button_play.tooltip="Turn on webcam" 

            camManager.dispose()       
            cont.content = None
        else:# case: not running -> running
            button_play.data = True
            button_play.icon = ft.icons.CAMERA_OUTLINED
            button_play.tooltip="Turn off webcam"   

            camManager.initialize()


            # THIS VERSION OF CAPTURING UPDATING THE CONTAINER CAUSES INTERMITTENT VIDEO
            # camManager.capture_from_webcam(container=cont)  


            camManager.capture_from_webcam(ftImg = img)    

        page.update()
        

    camManager = WebcamManager()   

    img = ft.Image(src_base64=None)
    cont = ft.Container(border=ft.border.all(3, ft.colors.RED), width=854, height=480, 
                        content = img,
    ) #width = 854, height = 480
    button_play = ft.IconButton(icon=ft.icons.CAMERA, icon_size=46, on_click=button_play_clicked, 
                                data = False, tooltip="Turn on webcam")

    page.add(ft.Column(
        controls=[cont, button_play], 
        horizontal_alignment = "center", 
        alignment = "center", )    
    )
    page.window_maximized = True
    page.scroll = ft.ScrollMode.AUTO
    page.horizontal_alignment = "center"
    page.vertical_alignment = "center"
    page.update()

ft.app(target=main, assets_dir="assets")

PROBLEM 1

In a previous version, the capturing method took in input the container and updated it (commented method). Surprisingly to me, the video was intermitting. So, I decided to modify this method giving an image as input,

img = ft.Image(src_base64=None)

and passing this image to the container. However, the image so defined (line 86) gave me this error displayed into the container: Image must have either "src" or "src_base64" specified

PROBLEM 2

Moreover, once the button is clicked, the capturing is fluent, but after a stop and a subsequent restart, I got this exception:

Future exception was never retrieved
future: <Future finished exception=AssertionError('Control must be added to the page first.')>
Traceback (most recent call last):
  File "c:\Users\idoec\miniconda3\Lib\concurrent\futures\thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\idoec\Desktop\FLET\WebcamApp\main.py", line 79, in button_play_clicked
    camManager.capture_from_webcam(ftImg = img)
  File "C:\Users\idoec\Desktop\FLET\WebcamApp\main.py", line 44, in capture_from_webcam
    ftImg.update()
  File "c:\Users\idoec\miniconda3\Lib\site-packages\flet_core\control.py", line 286, in update
    assert self.__page, "Control must be added to the page first."
AssertionError: Control must be added to the page first.
AssertionError: Control must be added to the page first.
Future exception was never retrieved
future: <Future finished exception=AssertionError('Control must be added to the page first.')>
Traceback (most recent call last):
  File "c:\Users\idoec\miniconda3\Lib\concurrent\futures\thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\idoec\Desktop\FLET\WebcamApp\main.py", line 79, in button_play_clicked
    camManager.capture_from_webcam(ftImg = img)
  File "C:\Users\idoec\Desktop\FLET\WebcamApp\main.py", line 44, in capture_from_webcam
    ftImg.update()
  File "c:\Users\idoec\miniconda3\Lib\site-packages\flet_core\control.py", line 286, in update
    assert self.__page, "Control must be added to the page first."
AssertionError: Control must be added to the page first.

In other terms: CLICK #1: OK CLICK #2: OK CLICK #3: Exception

Does anyone has hints to prevent the error and to avoid the exception? Thank you.

本文标签: pythonCapture the webcam frame into a Flet app flet image reported an error and an exceptionStack Overflow