Как создать изображение и отобразить его на следующей странице

#android #python-3.x #kivy #android-camera #kivy-language

#Android #python-3.x #kivy #android-камера #kivy-язык

Вопрос:

Добрый день, я написал простую программу для камеры, используя Python и Kivy, но я просто не могу сделать снимок. Вам нужно сделать снимок «ScreenThree» (сохранить его в памяти телефона) и отобразить полученное изображение на «ScreenFour».

Я использую kivy.uix.camera для отображения камеры, kivymd и kv для создания интерфейса. android.разрешения: ИНТЕРНЕТ, КАМЕРА, WRITE_EXTERNAL_STORAGE,READ_EXTERNAL_STORAGE

 from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.camera import Camera
from kivymd.theming import ThemeManager

import time

Builder.load_string("""
#:import MDFillRoundFlatButton kivymd.button.MDFillRoundFlatButton
#:import MDIconButton kivymd.button.MDIconButton
<ScreenOne@Screen>:
    canvas:
        Color:
            rgb: [.30,.50,.99]
        Rectangle:
            pos: self.pos
            size: self.size
    FloatLayout:
        MDFillRoundFlatButton:
            color: [1,1,1,1]
            text: "Перейти к созданию фото"
            pos_hint: {'center_x':.50, 'center_y':.50}
            on_press:
                root.manager.transition.direction = 'up'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_two'

<ScreenTwo@Screen>:
    canvas:
        Color:
            rgb: [.30,.50,.99]
        Rectangle:
            pos: self.pos
            size: self.size
    FloatLayout:
        MDFillRoundFlatButton:
            color: [1,1,1,1]
            text: "Выбрать фон"
            pos_hint: {'center_x':.50, 'center_y':.10}
            on_press:
                root.manager.transition.direction = 'up'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_three'
        MDIconButton:
            icon: 'chevron-double-right'
            pos_hint: {'center_x':.95, 'center_y':.10}
            on_press:
                root.manager.transition.direction = 'down'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_one'

<ScreenThree@Screen>:
    id: entry
    canvas:
        Color:
            rgb: [.30,.50,.99]
        Rectangle:
            pos: self.pos
            size: self.size
    FloatLayout:
        Camera:
            id: camera
            index: 0
            resolution: (1280,720)
            play: True  
        MDFillRoundFlatButton:
            text: "take photo"
            pos_hint: {'center_x': 0.50, 'center_y': .10}
            on_press:
                root.capture()   #TAKE PHOTO
                root.manager.transition.direction = 'up'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_four'    
        MDIconButton:
            icon: 'chevron-double-right'
            pos_hint: {'center_x':.95, 'center_y':.10}
            on_press:
                root.manager.transition.direction = 'down'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_two'

<ScreenFour@Screen>:
    canvas:
        Color:
            rgb: [.30,.50,.99]
        Rectangle:
            pos: self.pos
            size: self.size
    FloatLayout:
# HERE I NEED TO DISPLAY THE IMAGE
        MDIconButton:
            icon: 'chevron-double-right'
            pos_hint: {'center_x':.95, 'center_y':.10}
            on_press:
                root.manager.transition.direction = 'down'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_three'
""")


class ScreenOne(Screen):
    pass


class ScreenTwo(Screen):
    theme_cls = ThemeManager()
    theme_cls.primary_palette = 'Blue'
    main_widget = None

class ScreenThree(Screen):
    theme_cls = ThemeManager()
    theme_cls.primary_palette = 'Blue'
    main_widget = None

    def capture(self):
        camera = self.ids['camera']
        timestr = time.strftime("%Y%m%d_%H%M%S")
        photo = camera.export_to_png("IMG_{}.png".format(timestr))
        print("Captured")



class ScreenFour(Screen):
    pass


screen_manager = ScreenManager()


screen_manager.add_widget(ScreenOne(name="screen_one"))
screen_manager.add_widget(ScreenTwo(name="screen_two"))
screen_manager.add_widget(ScreenThree(name="screen_three"))
screen_manager.add_widget(ScreenFour(name="screen_four"))


class Interface(App):

    def build(self):
        return screen_manager

sample_app = Interface()
sample_app.run()
  

Подскажите, пожалуйста, как я могу изменить код, чтобы выполнить задачу.

Ошибка

Сделайте снимок
Белый экран

 04-08 21:15:19.925   796 13801 E mm-camera: <STATS_AF ><ERROR> 959: af_spd_detect_process: ERROR! SPOT_LIGHT_FLAG =0!!! :AEC_grid = 256, BG_grid = 3072, ave luma = 0
04-08 21:15:19.933   835   902 W SurfaceFlinger: EventThread: dropping event (7673796e) for connection 0x7b332278c0
04-08 21:15:19.949   835   902 W SurfaceFlinger: EventThread: dropping event (7673796e) for connection 0x7b332278c0
04-08 21:15:19.959   796 13801 E mm-camera: <STATS_AF ><ERROR> 959: af_spd_detect_process: ERROR! SPOT_LIGHT_FLAG =0!!! :AEC_grid = 256, BG_grid = 3072, ave luma = 0
04-08 21:15:19.966   835   902 W SurfaceFlinger: EventThread: dropping event (7673796e) for connection 0x7b332278c0
04-08 21:15:19.983   835   902 W SurfaceFlinger: EventThread: dropping event (7673796e) for connection 0x7b332278c0
04-08 21:15:19.992   796 13801 E mm-camera: <STATS_AF ><ERROR> 959: af_spd_detect_process: ERROR! SPOT_LIGHT_FLAG =0!!! :AEC_grid = 256, BG_grid = 3072, ave luma = 0
04-08 21:15:19.999   835   902 W SurfaceFlinger: EventThread: dropping event (7673796e) for connection 0x7b332278c0
  

Ошибка 2

 04-09 08:27:25.140   796  6243 E mm-camera: <STATS_AF ><ERROR> 959: af_spd_detect_process: ERROR! SPOT_LIGHT_FLAG =0!!! :AEC_grid = 256, BG_grid = 3072, ave luma = 0
04-09 08:27:25.146   835   902 W SurfaceFlinger: EventThread: dropping event (7673796e) for connection 0x7b32a54420
04-09 08:27:25.146  6164  6198 I python  : Captured
04-09 08:27:25.147  6164  6198 I python  : [ERROR  ] [Image       ] Error reading file IMG_20190409_082724.png
04-09 08:27:25.162   835   902 W SurfaceFlinger: EventThread: dropping event (7673796e) for connection 0x7b32a54420
04-09 08:27:25.175   796  6243 E mm-camera: <STATS_AF ><ERROR> 959: af_spd_detect_process: ERROR! SPOT_LIGHT_FLAG =0!!! :AEC_grid = 256, BG_grid = 3072, ave luma = 0
04-09 08:27:25.179   835   902 W SurfaceFlinger: EventThread: dropping event (7673796e) for connection 0x7b32a54420
  

Ответ №1:

Доступ к фото

Ссылайтесь на фотографию, используя следующее:

 class ScreenFour(Screen):

    def on_pre_enter(self, *args):
        self.ids.img.source = self.manager.ids.entry.photo
  

Решение

Примечание

 <class-name@widget>: 
  

Это динамический класс. При использовании динамического класса нет необходимости в определении класса в скрипте Python.

файл kv

  • Измените все динамические классы на правило класса, удалив все @Screen .
  • Добавьте правило класса, <ScreenManagement>:
  • Создайте экземпляр всех экранов как дочернего элемента правила класса, <ScreenManagement>:
  • Добавить id: entry в созданный дочерний элемент ScreenThree:
  • Создание экземпляра Image: как дочернего FloatLayout: элемента правила класса, <ScreenFour>:
  • Добавить id: img в созданный дочерний элемент, Image:

Фрагменты

 #:import MDIconButton kivymd.button.MDIconButton

<ScreenManagement>:
    ScreenOne:
        name: "screen_one"
    ScreenTwo:
        name: "screen_two"
    ScreenThree:
        id: entry
        name: "screen_three"
    ScreenFour:
        name: "screen_four"
...

<ScreenFour>:
    canvas:
        Color:
            rgb: [.30,.50,.99]
        Rectangle:
            pos: self.pos
            size: self.size

    FloatLayout:
        Image:
            id: img
  

Py-файл

  • Добавить оператор импорта, from os.path import dirname
  • Добавить оператор импорта, from kivy.properties import StringProperty
  • Добавить class ScreenManagement()
  • Удалите все ссылки на screen_manager
  • Объявите атрибут класса photo = StringProperty('') в разделе class ScreenThree()
  • Инициализировать атрибут класса, self.photo = f"{dirname(__file__)}/IMG_{time.strftime('%Y%m%d_%H%M%S')}.png"
  • Реализовать метод on_pre_enter() для отображения фотографии.

Фрагменты

 from os.path import dirname
from kivy.properties import StringProperty
...
class ScreenThree(Screen):
    photo = StringProperty('')

    def capture(self):
        camera = self.ids['camera']
        self.photo = f"{dirname(__file__)}/IMG_{time.strftime('%Y%m%d_%H%M%S')}.png"
        camera.export_to_png(self.photo)
        print("Captured")


class ScreenFour(Screen):

    def on_pre_enter(self, *args):
        self.ids.img.source = self.manager.ids.entry.photo


class ScreenManagement(ScreenManager):
    pass


class Interface(App):

    def build(self):
        return ScreenManagement()
  

Пример

main.py

 from os.path import dirname
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivymd.theming import ThemeManager
from kivy.properties import StringProperty

import time

Builder.load_string("""
#:import MDFillRoundFlatButton kivymd.button.MDFillRoundFlatButton
#:import MDIconButton kivymd.button.MDIconButton

<ScreenManagement>:
    ScreenOne:
        name: "screen_one"
    ScreenTwo:
        name: "screen_two"
    ScreenThree:
        name: "screen_three"
        id: entry
    ScreenFour:
        name: "screen_four"

<ScreenOne>:
    canvas:
        Color:
            rgb: [.30,.50,.99]
        Rectangle:
            pos: self.pos
            size: self.size
    FloatLayout:
        MDFillRoundFlatButton:
            color: [1,1,1,1]
            text: "Перейти к созданию фото"
            pos_hint: {'center_x':.50, 'center_y':.50}
            on_press:
                root.manager.transition.direction = 'up'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_two'

<ScreenTwo>:
    canvas:
        Color:
            rgb: [.30,.50,.99]
        Rectangle:
            pos: self.pos
            size: self.size
    FloatLayout:
        MDFillRoundFlatButton:
            color: [1,1,1,1]
            text: "Выбрать фон"
            pos_hint: {'center_x':.50, 'center_y':.10}
            on_press:
                root.manager.transition.direction = 'up'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_three'
        MDIconButton:
            icon: 'chevron-double-right'
            pos_hint: {'center_x':.95, 'center_y':.10}
            on_press:
                root.manager.transition.direction = 'down'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_one'

<ScreenThree>:
    id: entry
    canvas:
        Color:
            rgb: [.30,.50,.99]
        Rectangle:
            pos: self.pos
            size: self.size
    FloatLayout:
        Camera:
            id: camera
            index: 0
            resolution: (1280,720)
            play: True  
        MDFillRoundFlatButton:
            text: "take photo"
            pos_hint: {'center_x': 0.50, 'center_y': .10}
            on_press:
                root.capture()   #TAKE PHOTO
                root.manager.transition.direction = 'up'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_four'    
        MDIconButton:
            icon: 'chevron-double-right'
            pos_hint: {'center_x':.95, 'center_y':.10}
            on_press:
                root.manager.transition.direction = 'down'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_two'

<ScreenFour>:
    canvas:
        Color:
            rgb: [.30,.50,.99]
        Rectangle:
            pos: self.pos
            size: self.size
    FloatLayout:
        Image:
            id: img

        MDIconButton:
            icon: 'chevron-double-right'
            pos_hint: {'center_x':.95, 'center_y':.10}
            on_press:
                root.manager.transition.direction = 'down'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_three'
""")


class ScreenOne(Screen):
    pass


class ScreenTwo(Screen):
    theme_cls = ThemeManager()
    theme_cls.primary_palette = 'Blue'
    main_widget = None


class ScreenThree(Screen):
    theme_cls = ThemeManager()
    theme_cls.primary_palette = 'Blue'
    main_widget = None
    photo = StringProperty('')

    def capture(self):
        camera = self.ids['camera']
        self.photo = f"{dirname(__file__)}/IMG_{time.strftime('%Y%m%d_%H%M%S')}.png"
        camera.export_to_png(self.photo)
        print("Captured")


class ScreenFour(Screen):

    def on_pre_enter(self, *args):
        self.ids.img.source = self.manager.ids.entry.photo


class ScreenManagement(ScreenManager):
    pass


class Interface(App):

    def build(self):
        return ScreenManagement()


sample_app = Interface()
sample_app.run()
  

Вывод

Фото

Комментарии:

1. Привет, та же проблема, после белого экрана «сделать снимок», как это исправить?

2. Добавьте оператор импорта from os.path import dirname и префикс имени файла фотографии dirname(__file__) , например self.photo = f"{dirname(__file__)}/IMG_{time.strftime('%Y%m%d_%H%M%S')}.png"

3. Ошибка осталась, все еще белый экран после нажатия кнопки «сделать снимок» и в журнале: «python: [ОШИБКА] [Изображение] Ошибка чтения файла /IMG_20190409_192950.png»

4. Можете ли вы найти и просмотреть этот файл на своем телефоне, используя галерею или фотографии?

5. Нет, я пытался его найти, оно не отображается в галерее, и я не смог найти каталог, в котором оно находится.

Ответ №2:

 from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.camera import Camera
from kivymd.theming import ThemeManager

import time

filename = ''
screenfour = ''

Builder.load_string("""
#:import MDFillRoundFlatButton kivymd.button.MDFillRoundFlatButton
#:import MDIconButton kivymd.button.MDIconButton
<ScreenOne@Screen>:
    canvas:
        Color:
            rgb: [.30,.50,.99]
        Rectangle:
            pos: self.pos
            size: self.size
    FloatLayout:
        MDFillRoundFlatButton:
            color: [1,1,1,1]
            text: "Перейти к созданию фото"
            pos_hint: {'center_x':.50, 'center_y':.50}
            on_press:
                root.manager.transition.direction = 'up'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_two'

<ScreenTwo@Screen>:
    canvas:
        Color:
            rgb: [.30,.50,.99]
        Rectangle:
            pos: self.pos
            size: self.size
    FloatLayout:
        MDFillRoundFlatButton:
            color: [1,1,1,1]
            text: "Выбрать фон"
            pos_hint: {'center_x':.50, 'center_y':.10}
            on_press:
                root.manager.transition.direction = 'up'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_three'
        MDIconButton:
            icon: 'chevron-double-right'
            pos_hint: {'center_x':.95, 'center_y':.10}
            on_press:
                root.manager.transition.direction = 'down'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_one'

<ScreenThree@Screen>:
    id: entry
    canvas:
        Color:
            rgb: [.30,.50,.99]
        Rectangle:
            pos: self.pos
            size: self.size
    FloatLayout:
        Camera:
            id: camera
            index: 0
            resolution: (1280,720)
            play: True
        MDFillRoundFlatButton:
            text: "take photo"
            pos_hint: {'center_x': 0.50, 'center_y': .10}
            on_press:
                root.capture()   #TAKE PHOTO
                root.manager.transition.direction = 'up'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_four'
        MDIconButton:
            icon: 'chevron-double-right'
            pos_hint: {'center_x':.95, 'center_y':.10}
            on_press:
                root.manager.transition.direction = 'down'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_two'

<ScreenFour@Screen>:
    canvas:
        Color:
            rgb: [.30,.50,.99]
        Rectangle:
            pos: self.pos
            size: self.size
    FloatLayout:
        Image:
            size: root.width, root.height
            source: ''
            id: imageWid
        MDIconButton:
            icon: 'chevron-double-right'
            pos_hint: {'center_x':.95, 'center_y':.10}
            on_press:
                root.manager.transition.direction = 'down'
                root.manager.transition.duration = 1
                root.manager.current = 'screen_three'
""")


class ScreenOne(Screen):
    pass


class ScreenTwo(Screen):
    theme_cls = ThemeManager()
    theme_cls.primary_palette = 'Blue'
    main_widget = None

class ScreenThree(Screen):
    theme_cls = ThemeManager()
    theme_cls.primary_palette = 'Blue'
    main_widget = None

    def capture(self):
        camera = self.ids['camera']
        timestr = time.strftime("%Y%m%d_%H%M%S")
        photo = camera.export_to_png("IMG_{}.png".format(timestr))
        global filename, screenfour
        filename = "IMG_{}.png".format(timestr)
        print("Captured")
        screenfour.update()

class ScreenFour(Screen):
    def __init__(self, **kwargs):
        super(ScreenFour, self).__init__(**kwargs)
        global screenfour
        screenfour = self

    def update(self, *args):
        global filename
        imageWidget = self.ids['imageWid']
        imageWidget.source = filename

screen_manager = ScreenManager()

screen_manager.add_widget(ScreenOne(name="screen_one"))
screen_manager.add_widget(ScreenTwo(name="screen_two"))
screen_manager.add_widget(ScreenThree(name="screen_three"))
screen_manager.add_widget(ScreenFour(name="screen_four"))

class Interface(App):

    def build(self):
        return screen_manager

sample_app = Interface()
sample_app.run()
  

Вы должны создать global переменную для сохранения имени файла изображения, а затем Image виджета в вашем screenfour Screen , где вы обновите источник виджета изображения до имени файла сделанного вами снимка. Не стесняйтесь обращаться ко мне, если возникнут какие-либо проблемы

Комментарии:

1. Спасибо за ответ. Я проверил ваш код, и у меня возникла проблема. Приложение запускается, и когда я нажимаю кнопку «Сделать снимок», оно переходит на следующую страницу, и она полностью белая. В журнале приложений все время одна и та же ошибка. Я дополнил вопрос.