'How can i speed up camera frame rate on display window in python/kivy?

I am trying to make an inventory app (qr/data matrix) where equipment can be added and organized using a QR/data matrix code. When i run the camera the frame rate seems fine but the moment i add any code to decode and extract qr/data matrix information, the frame rate drops badly. Also it seem like it takes more time to load the camera page too. is there a way that this can be solved? Please i am new to python and kivy and this is my first question here too. thank you.

This is the .kv file code

#: import NoTransition kivy.uix.screenmanager.NoTransition

MDFloatLayout:
    md_bg_color: rgba(1, 1, 1, 1)
    ScreenManager:
        id: screen_manager
        transition: NoTransition()
        MDScreen:
            name: "homepage"
            MDFloatingActionButton:
                icon: 'data-matrix-scan'
                md_bg_color: rgba(206, 206, 209, 255)
                pos_hint: {"right": .96,"center_y": .17}
                user_font_size: "27sp"
                on_release:
                    screen_manager.current = "scan"
                    app.scan()


        MDScreen:
            name: "scan"
            on_enter:
                app.scan_code()
                #app.read_code()
            MDFloatLayout:
                orientation: 'vertical'
                md_bg_color: rgba(241, 241, 243, 255)
                MDIconButton:
                    icon: 'chevron-left'
                    pos_hint: {"center_y": .95}
                    on_release:
                        app.release_cam()
                        screen_manager.current = "homepage"
                MDLabel:
                    text: 'Add Item'
                    pos_hint: {"center_x": .9, "center_y": .95}

                MDBoxLayout:
                    orientation: 'vertical'
                    md_bg_color: rgba(241, 241, 243, 255)
                    pos_hint: {"center_x": .5,"center_y": .4}
                    spacing: 15

                    # Camera Widget
                    MDBoxLayout:
                        id: cam_box
                        md_bg_color: rgba(206, 206, 209, 255)
                        #size_hint: .77, .41
                        size_hint: 1, None
                        height: '230dp'
                        #width: '240dp'
                        pos_hint: {"center_x": .5}

                    # Space for ListView
                    MDBoxLayout:
                        pos_hint: {"center_x": .5}
                        md_bg_color: rgba(106, 206, 209, 255)
                        size_hint: 1, .4
                Button:
                    text: "ADD ITEMS"
                    size_hint: .77, .08
                    pos_hint: {"center_x": .5,"center_y": .07}
                    background_color: 0, 0, 0, 0
                    font_name: "MPoppins"
                    font_size: "18sp"
                    color: 1, 1, 1, 1
                    canvas.before:
                        Color:
                            rgb: rgba(255, 170, 23, 255)
                        RoundedRectangle:
                            size: self.size
                            pos: self.pos
                            radius: [12]

        MDScreen:
            name: "saved"
            MDLabel:
                text: "Saved"
                halign: "center"
                font_name: "BPoppins"

        MDScreen:
            name: "create"
            MDLabel:
                text: "Create"
                halign: "center"
                font_name: "BPoppins"

        MDScreen:
            name: "account"
            MDLabel:
                text: "Account"
                halign: "center"
                font_name: "BPoppins"

        MDScreen:
            name: "settings"
            MDLabel:
                text: "Settings"
                halign: "center"
                font_name: "BPoppins"

    NavBar:
        size_hint: 1, .1
        pos_hint: {"center_x": .5, "y": 0}
        elevation: 10
        md_bg_color: 1, 1, 1, 1
        MDGridLayout
            cols: 5
            size_hint_x: 1
            spacing: 10
            pos_hint: {"center_x": .5 , "center_y": .5}
            #md_bg_color: rgba(71,92,119,255)
            MDBoxLayout:
                orientation: 'vertical'
                spacing: 1
                padding: 0, 0, 0, 10
                pos_hint: {"center_x": .5 , "center_y": .5}
                #md_bg_color: rgba(105, 222, 222, 255)
                MDIconButton:
                    id: nav_icon1
                    icon: "home"
                    ripple_scale: 0
                    user_font_size: "30sp"
                    theme_text_color: "Custom"
                    text_color: rgba(71,92,119,255)
                    pos_hint: {"center_x": .5 , "center_y": .5}
                    on_release:
                        screen_manager.current = "homepage"
                        app.change_color(self)
                MDLabel:
                    text: "Home"
                    font_name: "MPoppins"
                    font_size: 10
                    halign: 'center'
                Widget:
                    height: 4
            MDBoxLayout:
                orientation: 'vertical'
                spacing: 1
                padding: 0, 0, 0, 10
                pos_hint: {"center_x": .5 , "center_y": .5}
                MDIconButton:
                    id: nav_icon2
                    icon: "download"
                    ripple_scale: 0
                    user_font_size: "30sp"
                    theme_text_color: "Custom"
                    text_color: rgba(222, 222, 222, 255)
                    pos_hint: {"center_x": .5 , "center_y": .5}
                    on_release:
                        screen_manager.current = "saved"
                        app.change_color(self)
                MDLabel:
                    text: "Download"
                    font_name: "MPoppins"
                    font_size: 10
                    halign: 'center'
                Widget:
                    height: 4
            MDBoxLayout:
                orientation: 'vertical'
                spacing: 1
                padding: 0, 0, 0, 10
                pos_hint: {"center_x": .5 , "center_y": .5}
                MDIconButton:
                    id: nav_icon3
                    icon: "plus-circle-outline"
                    ripple_scale: 0
                    user_font_size: "30sp"
                    theme_text_color: "Custom"
                    text_color: rgba(222, 222, 222, 255)
                    pos_hint: {"center_x": .5 , "center_y": .5}
                    on_release:
                        screen_manager.current = "create"
                        app.change_color(self)
                MDLabel:
                    text: "Create"
                    font_name: "MPoppins"
                    font_size: 10
                    halign: 'center'
                Widget:
                    height: 4
            MDBoxLayout:
                orientation: 'vertical'
                spacing: 1
                padding: 0, 0, 0, 10
                pos_hint: {"center_x": .5 , "center_y": .5}
                MDIconButton:
                    id: nav_icon4
                    icon: "account"
                    ripple_scale: 0
                    user_font_size: "30sp"
                    theme_text_color: "Custom"
                    text_color: rgba(222, 222, 222, 255)
                    pos_hint: {"center_x": .5 , "center_y": .5}
                    on_release:
                        screen_manager.current = "account"
                        app.change_color(self)
                MDLabel:
                    text: "Account"
                    font_name: "MPoppins"
                    font_size: 10
                    halign: 'center'
                Widget:
                    height: 4
            MDBoxLayout:
                orientation: 'vertical'
                spacing: 1
                padding: 0, 0, 0, 10
                pos_hint: {"center_x": .5 , "center_y": .5}
                MDIconButton:
                    id: nav_icon5
                    icon: "cog"
                    ripple_scale: 0
                    user_font_size: "27sp"
                    theme_text_color: "Custom"
                    text_color: rgba(222, 222, 222, 255)
                    pos_hint: {"center_x": .5 , "center_y": .5}
                    on_release:
                        screen_manager.current = "settings"
                        app.change_color(self)
                MDLabel:
                    text: "Settings"
                    font_name: "MPoppins"
                    font_size: 10
                    halign: 'center'
                Widget:
                    height: 4

This is the .py file with the decoding code (under load_video())

from kivy.core.image import Texture
from kivy.utils import rgba
from kivymd.app import MDApp
from kivy.core.text import LabelBase
from kivy.core.window import Window
from kivymd.uix.behaviors import FakeRectangularElevationBehavior
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.floatlayout import MDFloatLayout
from kivy.uix.image import Image
from kivy.clock import Clock
import cv2
from pylibdmtx.pylibdmtx import decode
import time
import winsound
from datetime import datetime

Window.size = (310, 580)


class CamBox(FakeRectangularElevationBehavior, MDFloatLayout):
    pass


class NavBar(FakeRectangularElevationBehavior, MDFloatLayout):
    pass


class Camera(MDApp):

    def scan(self):
        self.image = Image()
        self.root.ids.cam_box.add_widget(self.image)

        self.capture = cv2.VideoCapture(0)
        Clock.schedule_interval(self.load_video, 1.0 / 30.0)

    def load_video(self, *args):
        ret, frame = self.capture.read()
        self.image_frame = frame

        # Data Matrix Decoding Part
        dm_code = decode(self.image_frame)

        for code in dm_code:
            serial = str(code.data.decode('utf-8'))
            print(serial)

        #while dm_code:
        #    print(dm_code)

        # Frame Initialize
        buffer = cv2.flip(frame, 0).tobytes()
        texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt='bgr')
        texture.blit_buffer(buffer, colorfmt='bgr', bufferfmt='ubyte')
        self.image.texture = texture

    #def read_code(self, *args):


    def release_cam(self):
        #self.capture.release()
        self.root.ids.cam_box.remove_widget(self.image)

    def scan_code(self):
        pass


    def change_color(self, instance):
        if instance in self.root.ids.values():
            current_id = list(self.root.ids.keys())[list(self.root.ids.values()).index(instance)]
            for i in range(5):
                if f"nav_icon{i + 1}" == current_id:
                    self.root.ids[f"nav_icon{i + 1}"].text_color = rgba(71, 92, 119, 255)
                else:
                    self.root.ids[f"nav_icon{i + 1}"].text_color = rgba(222, 222, 222, 255)


LabelBase.register(name='BPoppins', fn_regular="C:\\Users\dogig\\PycharmProjects\\Wallpaper App\\Poppins-Bold.otf")
LabelBase.register(name='MPoppins', fn_regular="C:\\Users\dogig\\PycharmProjects\\Wallpaper App\\Poppins-Medium.otf")
LabelBase.register(name='LPoppins', fn_regular="C:\\Users\dogig\\PycharmProjects\\Wallpaper App\\Poppins-Light.otf")
LabelBase.register(name='TPoppins', fn_regular="C:\\Users\dogig\\PycharmProjects\\Wallpaper App\\Poppins-Thin.otf")

Camera().run()

This is the .py file without the decoding code

from kivy.core.image import Texture
from kivy.utils import rgba
from kivymd.app import MDApp
from kivy.core.text import LabelBase
from kivy.core.window import Window
from kivymd.uix.behaviors import FakeRectangularElevationBehavior
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.floatlayout import MDFloatLayout
from kivy.uix.image import Image
from kivy.clock import Clock
import cv2
from pylibdmtx.pylibdmtx import decode
import time
import winsound
from datetime import datetime

Window.size = (310, 580)


class CamBox(FakeRectangularElevationBehavior, MDFloatLayout):
    pass


class NavBar(FakeRectangularElevationBehavior, MDFloatLayout):
    pass


class Camera(MDApp):

    def scan(self):
        self.image = Image()
        self.root.ids.cam_box.add_widget(self.image)

        self.capture = cv2.VideoCapture(0)
        Clock.schedule_interval(self.load_video, 1.0 / 30.0)

    def load_video(self, *args):
        ret, frame = self.capture.read()
        self.image_frame = frame

        

        # Frame Initialize
        buffer = cv2.flip(frame, 0).tobytes()
        texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt='bgr')
        texture.blit_buffer(buffer, colorfmt='bgr', bufferfmt='ubyte')
        self.image.texture = texture

    #def read_code(self, *args):


    def release_cam(self):
        #self.capture.release()
        self.root.ids.cam_box.remove_widget(self.image)

    def scan_code(self):
        pass


    def change_color(self, instance):
        if instance in self.root.ids.values():
            current_id = list(self.root.ids.keys())[list(self.root.ids.values()).index(instance)]
            for i in range(5):
                if f"nav_icon{i + 1}" == current_id:
                    self.root.ids[f"nav_icon{i + 1}"].text_color = rgba(71, 92, 119, 255)
                else:
                    self.root.ids[f"nav_icon{i + 1}"].text_color = rgba(222, 222, 222, 255)


LabelBase.register(name='BPoppins', fn_regular="C:\\Users\dogig\\PycharmProjects\\Wallpaper App\\Poppins-Bold.otf")
LabelBase.register(name='MPoppins', fn_regular="C:\\Users\dogig\\PycharmProjects\\Wallpaper App\\Poppins-Medium.otf")
LabelBase.register(name='LPoppins', fn_regular="C:\\Users\dogig\\PycharmProjects\\Wallpaper App\\Poppins-Light.otf")
LabelBase.register(name='TPoppins', fn_regular="C:\\Users\dogig\\PycharmProjects\\Wallpaper App\\Poppins-Thin.otf")

Camera().run()

click the blue circle to go into scan page



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source