#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. Спасибо за ответ. Я проверил ваш код, и у меня возникла проблема. Приложение запускается, и когда я нажимаю кнопку «Сделать снимок», оно переходит на следующую страницу, и она полностью белая. В журнале приложений все время одна и та же ошибка. Я дополнил вопрос.