如何使用 kivy 为移动应用程序制作相机小部件

Posted

技术标签:

【中文标题】如何使用 kivy 为移动应用程序制作相机小部件【英文标题】:how to make camera widget for mobile apps with kivy 【发布时间】:2021-11-01 08:17:33 【问题描述】:

我正在尝试在我的应用程序中添加一个摄像头,我希望摄像头处于全屏模式,并且我希望它在移动设备上是垂直的而不是水平的。我希望相机在单击按钮捕获后停止捕获图像。我试图做到这一点,这是我的代码,但它不起作用

camera_widget = '''
MDBoxLayout:
    rows:2
    Camera:
        orientation: 'vertical'
        id: camera
        size:app.screen.size
        resolution:(720, 480)
        Rotate:
            origin:self.center
            angle:-90'''
def menue_arabic_camera(self,*args):
    self.screen.clear_widgets()
    return_back = MDFlatButton(text=self.ar_text("العودة للخلف"),
                                 pos_hint='center_x': .5, 'center_y': .02,
                                 on_press=self.selection_load_cam_ar,
                                 font_name='DROIDKUFI-REGULAR.TTF')
    self.screen.add_widget(return_back)
    self.SHEET = Builder.load_string(camera_widget)
    self.screen.add_widget(self.SHEET)
    CAPTURE = MDFlatButton(text="Capture",
                                 pos_hint='center_x': .5, 'center_y': .05,
                                 on_press=self.capture)
def capture(self,*args):
        camera = self.SHEET.ids['camera']
        camera.play = not camera.play
        self.save_img()
        name = "User_sheet"
        camera.export_to_png("IMG_.png".format(name))

【问题讨论】:

【参考方案1】:

您可以使用着色器指令以及带有摄像头 java 类的 pyjnius 模块,该类具有新的实现功能,包括来自设备的纹理(如果您使用的是 android 设备),如果您使用的是 PC,则此示例可能无法运行,因为它使用带有python、jbsidis的android类:

from jnius import autoclass, PythonJavaClass, java_method
Camera = autoclass('android.hardware.Camera')
SurfaceTexture = autoclass('android.graphics.SurfaceTexture')

GL_TEXTURE_EXTERNAL_OES = 36197


class CameraPreviewjbsidis(Image):
    play = BooleanProperty(False)

    resolution = ListProperty([640, 480])

    _camera = None
    _previewCallback = None
    _previewTexture = None

    secondary_texture = None

    def __init__(self, **kwargs):
        self.canvas = RenderContext()
        super(CameraPreviewjbsidis, self).__init__(**kwargs)
        self.bind(size=self.size_changed)

        # (2)
        self.canvas.shader.fs = '''
            #extension GL_OES_EGL_image_external : require
            #ifdef GL_ES
                precision highp float;
            #endif

            /* Outputs from the vertex shader */
            varying vec4 frag_color;
            varying vec2 tex_coord0;

            /* uniform texture samplers */
            uniform sampler2D texture0;
            uniform samplerExternalOES texture1;

            void main()
            
                gl_FragColor = texture2D(texture1, tex_coord0);
            
        '''
        # This is needed for the default vertex shader.
        self.canvas['projection_mat'] = Window.render_context['projection_mat']

        with self.canvas.before:
            # (4)
            Callback(self.draw_callback)
        with self.canvas:
            # (3)
            BindTexture(texture=self.secondary_texture, index=1)
        self.canvas['secondary_texture'] = 1

        # (1)
        tex_id = kivy.graphics.opengl.glGenTextures(1)[0]
        kivy.graphics.opengl.glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex_id)
        width, height = self.resolution
        self.secondary_texture = Texture(width=width, height=height, target=GL_TEXTURE_EXTERNAL_OES, texid=int(tex_id), colorfmt='rgba')
        # (6)
        self._camera = Camera.open()
        self._previewTexture = SurfaceTexture(int(tex_id))
        self._camera.setPreviewTexture(self._previewTexture)

    def draw_callback(self, instr):
        if self._previewTexture:
            self._previewTexture.updateTexImage()

    def config_camera(self, surface):
        self._camera.setPreviewTexture(surface)

    def update_canvas(self, dt):
        self.canvas.ask_update()

    def size_changed(self, *largs):
        pass


    def on_play(self, instance, value):
        if not self._camera:
            return
        if value:
            self._camera.startPreview()

            # (5)
            Clock.schedule_interval(self.update_canvas, 1.0/30)
        else:
            Clock.unschedule(self.update_canvas)
            self._camera.stopPreview()

【讨论】:

如果代码格式不正确,可以在这里查看完整代码:groups.google.com/g/kivy-users/c/hiyAJqjhFjo

以上是关于如何使用 kivy 为移动应用程序制作相机小部件的主要内容,如果未能解决你的问题,请参考以下文章

如何清除 kivy 中的小部件?

Kivy 如何访问子小部件中的小部件

如何传递一个值来初始化 Kivy 中的屏幕小部件?

我如何使用 Kivy (Python) 相机

在 Kivy 中使用 RecycleView 的自定义小部件的对齐问题

Kivy (KivyMD) 中的按钮和小部件大小