Наблюдение за табло. Часть 2. Удаленное управление камерой
В этой части мы научимся работать с камерой телефона. Скрипт на питоне, который делает снимки и копирует их на компьютер.
Содержание цикла
- Часть 1. Вступление: идея и план работы
- Часть 2. Удаленное управление камерой
- Часть 3. Поиск красного и обрезка
Как я уже писал в первой части, изначально планировал написать приложение для телефона – прям apk – чтобы поставить и оно делало что надо. Но в процессе оказалось, что для одиночного снимка камерой телефона надо самому (!) человеку нажимать, чтобы получить фото. Вообще, можно обойти и делать серию снимков автоматом, но это будет надо много кода.
А что если зайти с другой стороны? Все равно телефон постоянно будет подключен к ноутбуку – пусть ноутбук питоном и adb и управлять им? Понятно, дав сначала все необходимые разрешения в режимах разработчика и режиме отладки?
Да, оказывается это возможно и не так уж сложно. После нескольких попыток и версий родился скрипт, который через определенный промежуток времени делает снимки и копирует их на ноутбук. Код прокомментирован
import subprocess
import time
import os
from datetime import datetime
# ===== НАСТРОЙКИ =====
ADB_PATH = r"C:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe"
INTERVAL = 60 # секунд между снимками
OUTPUT_DIR = r"C:\job\cv\foto" # папка для фото
# ====================
def check_adb():
"""Проверка доступности ADB"""
try:
result = subprocess.run([ADB_PATH, "devices"], capture_output=True, text=True)
if "device" not in result.stdout:
print("Устройство не найдено! Проверьте подключение телефона.")
return False
return True
except:
print("ADB не найден! Проверьте путь к ADB.")
return False
def cmd(command):
"""Выполнение ADB команды (исправлено для Windows)"""
try:
# Разбиваем команду на части для избежания проблем с кавычками
parts = command.split()
if parts[0] == 'shell':
# Для shell команд используем особый подход
shell_cmd = ' '.join(parts[1:])
result = subprocess.run([ADB_PATH, "shell", shell_cmd],
capture_output=True, text=True)
return result
else:
result = subprocess.run([ADB_PATH] + parts,
capture_output=True, text=True)
return result
except Exception as e:
print(f"Ошибка выполнения команды: {e}")
return None
def ensure_dir():
"""Создание папки для фото"""
try:
os.makedirs(OUTPUT_DIR, exist_ok=True)
print(f"Фото будут сохраняться в: {OUTPUT_DIR}")
return True
except Exception as e:
print(f"Ошибка создания папки: {e}")
return False
def count_photos():
"""Подсчет количества фото в папке Camera"""
result = cmd("shell ls /sdcard/DCIM/Camera/ | grep -c '.jpg'")
if result and result.stdout:
return result.stdout.strip()
return "0"
def get_latest_photo():
"""Получение пути к последнему фото"""
# Используем ls с сортировкой по времени
result = cmd("shell ls -t /sdcard/DCIM/Camera/*.jpg 2>/dev/null | head -1")
if result and result.stdout.strip():
return result.stdout.strip()
return None
print("? Автоматическая съемка запущена")
print(f"Интервал: {INTERVAL} сек")
print(f"Папка сохранения: {OUTPUT_DIR}")
print("Для остановки нажмите Ctrl+C")
print("-" * 40)
# Проверяем ADB и создаем папку
if not check_adb():
exit(1)
if not ensure_dir():
exit(1)
# Проверяем доступность папки Camera
test_result = cmd("shell ls /sdcard/DCIM/Camera/")
if test_result and test_result.returncode == 0:
print("Доступ к папке Camera есть")
# Показываем список фото
print("Фото на телефоне:")
print(test_result.stdout)
else:
print("Не удается получить доступ к папке Camera!")
exit(1)
photo_num = 1
last_photo_count = 0
try:
while True:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
print(f"\n[{timestamp}] Снимок #{photo_num}")
# Получаем количество фото ДО съемки
before_count = count_photos()
print(f"? Фото в папке до съемки: {before_count}")
# Разблокировка экрана
print("Разблокировка...")
cmd("shell input keyevent 26") # Включение
time.sleep(1)
cmd("shell input swipe 300 1000 300 300") # Свайп вверх
time.sleep(2)
# Запуск камеры
print("Запуск камеры...")
cmd("shell am start -a android.media.action.STILL_IMAGE_CAMERA")
time.sleep(3)
# Съемка
print("Съемка...")
cmd("shell input keyevent 27") # Затвор
time.sleep(4) # Ждем сохранения
# Закрываем камеру (несколькими способами)
print("Закрытие камеры...")
cmd("shell input keyevent 4") # Назад
time.sleep(1)
cmd("shell input keyevent 4") # Еще раз назад
time.sleep(1)
# Принудительно останавливаем приложение камеры
cmd("shell am force-stop com.android.camera2")
time.sleep(1)
# Блокировка экрана
print("Блокировка...")
cmd("shell input keyevent 26")
# Ждем обновления галереи
time.sleep(2)
# Получаем количество фото ПОСЛЕ съемки
after_count = count_photos()
print(f"Фото в папке после съемки: {after_count}")
# Ищем новое фото
print("Поиск нового фото...")
# Получаем последнее фото
latest_photo = get_latest_photo()
if latest_photo:
print(f"Найдено фото: {latest_photo}")
# Копируем на компьютер
local_path = os.path.join(OUTPUT_DIR, f"photo_{timestamp}.jpg")
# Используем pull с правильными путями
pull_cmd = [ADB_PATH, "pull", latest_photo, local_path]
result = subprocess.run(pull_cmd, capture_output=True, text=True)
if result.returncode == 0 and os.path.exists(local_path):
file_size = os.path.getsize(local_path) / 1024
print(f"Сохранено: {local_path} ({file_size:.1f} KB)")
photo_num += 1
last_photo_count = int(after_count) if after_count.isdigit() else 0
else:
print("Ошибка при копировании")
print(f"Ошибка: {result.stderr}")
else:
print("Не найдено фото в папке Camera")
# Статистика
print(f"? Всего снимков: {photo_num-1}")
# Ожидание
if photo_num > 1:
print(f"⏳ Ожидание {INTERVAL} сек до следующего снимка...")
for i in range(INTERVAL, 0, -1):
print(f"\r⏳ Следующий снимок через {i:3d} сек...", end='', flush=True)
time.sleep(1)
print()
else:
# Если первый снимок не удался, ждем меньше
time.sleep(10)
except KeyboardInterrupt:
print("\n\n Остановлено пользователем")
print(f"Всего сделано снимков: {photo_num-1}")
print(f"Фото сохранены в: {OUTPUT_DIR}")
# Показываем сохраненные фото
if photo_num > 1:
print("\nСохраненные файлы:")
for f in os.listdir(OUTPUT_DIR):
if f.endswith('.jpg'):
print(f" - {f}")
Получилось:

Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.
Программы на заказ
Отзывы
Контакты