Рубрики
Без рубрики

Докереное применение веб-камеры на основе колба

В этом руководстве мы будем: создание веб-приложения на основе Flask для фотографирования, используя … Tagged с Docker, Python, колбой.

В этом руководстве мы будем:

  • Создание веб-приложения на основе Flask для фотографирования с использованием OpenCV ;
  • Доменение этого приложения ; тогда
  • Создание многофункционального приложения с Docker Compose для захвата и хранения фотографий Отказ

Создание нашего приложения веб-камеры

Во-первых, мы будем использовать Колбу , легкая веб-каркас, чтобы быстро настроить веб-приложение. Это приложение также будет использовать OpenCV для фотографирования.

Для этой части учебника мы дадим краткий обзор, поскольку мы действительно сосредоточены на аспекте докеревания этого приложения, но весь код можно найти на GitHub:

Carlosemv/Camera-App

Есть две основные страницы для приложения, индекс , где вы можете сделать снимок, а захват , где вы можете увидеть захваченную картинку и скачать его или по электронной почте вам или кому-то еще.

Итак, мы определяем маршруты Для каждой из этих страниц, которые будут представлять соответствующие шаблоны:

# route for index (picture-taking) page
@app.route('/index/')
def index():
    return render_template('index.html')

# route for capturing picture
@app.route('/capture/')
def capture():
    camera = get_camera()
    stamp = camera.capture()
    return redirect(url_for('show_capture', timestamp=stamp))

# route for showing captured picture
@app.route('/capture/image/', methods=['POST', 'GET'])
def show_capture(timestamp):
    path = stamp_file(timestamp)
    ...
    return render_template('capture.html',
        stamp=timestamp, path=path, email_msg=email_msg)

Обратите внимание, что мы опускаем код, который обрабатывает отправку электронной почты, который будет Пост Запрос на тот же маршрут, что и для отображения захваченного изображения (реализована show_capture ).

Помимо этих функций, критическая часть нашего кода является той, которая получает корм для камеры:

def get_camera():
    global camera
    if not camera:
        camera = Camera()

    return camera

def gen(camera):
    while True:
        frame = camera.get_feed()
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')

@app.route('/video_feed/')
def video_feed():
    camera = get_camera()
    return Response(gen(camera),
        mimetype='multipart/x-mixed-replace; boundary=frame')

Так что камера – это класс, который мы создали, и которые мы получим через минуту. get_camera Наследует то, что в основном является синглтон, лениво загружают один экземпляр камеры при необходимости.

Video_feed Используется маршрут внутри показатель , в index.html Шаблон, как ссылка изображения:

video feed

Итак, Video_feed Возвращает объект ответа, содержащий итератор, который непрерывно генерирует кадры из нашей камеры, а соответствующий миметип Multipart/X-смешанный замена , что позволяет нам постоянно заменять один кадр с помощью следующего.

Ген Это генераторная функция, которая постоянно получает кадру камеры (двоичное изображение JPEG) и возвращает двоичные данные, содержащие это изображение, а также необходимые заголовки.

Теперь, как для класса камеры: он в основном создает объект VideoCapture OpenCV и придает кадрам по мере необходимости, также захватывая конкретный кадр при запросе. Захват подразумевает сохранение изображения локально (временно, по крайней мере) и возвращает временную метку, который служит уникальным идентификатором.

class Camera(object):
    CAPTURES_DIR = "static/captures/"
    def __init__(self):
        self.video = cv.VideoCapture(0)

    def get_frame(self):
        success, frame = self.video.read()
        ...  
        return frame

    def get_feed(self):
        frame = self.get_frame()
        if frame is not None:
            ret, jpeg = cv.imencode('.jpg', frame)
            return jpeg.tobytes()

    def capture(self):
        frame = self.get_frame()
        timestamp = strftime("%d-%m-%Y-%Hh%Mm%Ss", localtime())
        filename = Camera.CAPTURES_DIR + timestamp +".jpg"
        if not cv.imwrite(filename, frame):
            raise RuntimeError("Unable to capture image "+timestamp)
        return timestamp

Теперь мы можем запустить этот код с Python Web.py Отказ Обратите внимание, что он работает на режиме отладки на localhost: 8080. . Которые могут быть изменены несколькими способами, такими как редактирование линии ниже на Главная , но обязательно проверить Флэкские документы Больше подробностей.

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, debug=True)

Ниже мы видим, какова наша страница для захвата изображений и страница просмотра захвата:

Докереное приложение нашего камеры

При строительстве нашего DockerFile мы начнем с базы Linux (Ubuntu, в данном случае) вместо того, чтобы использовать прямую среду Python, так как она немного более гибкая, и делает зависимостью. Но у вас всегда есть возможность построить вместо этого изображения Python. Это сделано в первой строке: Из Убунту: 18.04 Отказ

Теперь мы встроили некоторые метаданные на наш образ с Этикетка Инструкция. В этом случае мы просто определяем сопровождающую проекта, как так: МЕТКА (Это, конечно, шаблон, который должен быть заменен на вашу собственную информацию).

Теперь мы попадаем в настройку нашей пользовательской среды. Сначала мы обновляем и устанавливаем необходимые пакеты:

RUN apt-get update -y && apt-get install -y build-essential cmake \
libsm6 libxext6 libxrender-dev \
python3 python3-pip python3-dev

libsm6 libxext6 libxrender-dev Последовательность пакетов важна для правильной установки OpenCV позже. Обратите внимание, что мы будем использовать Python 3 и Pip в качестве менеджера пакета.

Далее есть Workdir/app. . Это создает каталог в root, и устанавливает его в качестве рабочего каталога для любых следующих команд. Сначала скопируем файл наших требований, прежде чем любой исходный код, с помощью Скопируйте ./requirement.txt./приложение/требования .txt Отказ Мы делаем это, чтобы воспользоваться преимуществами системы кеша на основе слоев докера.

Наконец, инструкция Запустите PIP3 Установить -R требования. Atxt Устанавливает все наши зависимости (Flask and Opencv), и мы готовы запускать наше приложение. Обратите внимание, что нам не нужно указывать весь путь к файлу требований, так как он уже находится в нашем рабочем каталоге.

Итак, поскольку наш контейнер будет работать как исполняемый файл (в отличие от оболочки), мы определяем нашу точку входа: Въездная точка ["Python3"] Затем запустите наше приложение с CMD [«Web.py»] Отказ Ниже мы можем просмотреть весь докер.

FROM ubuntu:18.04
LABEL maintainer="me@mail.com"

RUN apt-get update -y && apt-get install -y build-essential cmake \
libsm6 libxext6 libxrender-dev \
python3 python3-pip python3-dev

COPY ./requirements.txt /app/requirements.txt
WORKDIR /app
RUN pip3 install -r requirements.txt

COPY . /app
ENTRYPOINT ["python3"]
CMD ["web.py"]

Бег Docker Build -t Camera-App. Теперь создаст наше изображение с именем Camera-App. Затем мы можем создать от него контейнер со следующей командой: Docker Run -d --name Cam --device/dev/video0 -p 8080: 8080 Camera-App Отказ

  • -d или --detach делает контейнер бежать на заднем плане.
  • --device/dev/video0 Добавляет устройство от хоста, в этом случае камера, к контейнеру.
  • -P 8080: 8080 , для --publish , опубликует или отобразит порт контейнера (тот, кто на правой стороне толстой кишки) в порт на хосте (слева).

Хранение фото с Docker-Compose

Теперь у нас есть наше веб-приложение Flask, работая с Docker. Но снятые изображения не сохраняются и не легко доступны, находясь во временном объеме, созданном Docker.

Таким образом, мы будем использовать самосоведочный сервер хранения файлов с помощью Web-интерфейса, который называется dropypy:

Silverwind/капля

** Архив ** Самоустановленное хранение файлов

Мы используем DARMPY, потому что она очень легкий, имеет простой веб-интерфейс и имеет очень простую настройку, поскольку она обеспечивает готов к использованию документа Docker. Но имейте в виду, что другой тип сервера для хранения изображения также можно использовать с Docker, и будет иметь очень похожую установку.

DARMPY будет работать как отдельный контейнер из одного приложения нашего приложения камеры. Но эти два контейнера могут быть легко организованы вместе, благодаря Docker Compose.

Наш файл Docker-Compose (который является файлом данных YAML) будет иметь две важные части: Объемы и Услуги Отказ В Объемы мы создаем громкость под названием захватывает , который будет хранить наши захваченные изображения и передаваться между двумя контейнерами.

В Услуги Мы настраиваем наши два сервиса, которые заберут наши два изображения: Camera-App, и Drobpy. В файле ниже мы можем видеть, что эти два сервиса имеют некоторые вещи общего. Для обоих, Мы определяем

  • Container_Name , название контейнера, как только он создается;
  • изображение изображение, которое будет использоваться для создания контейнера;
  • Порты , аналогично Флаг обсуждался ранее, будет сопоставлять необходимые порты для Localhost; и
  • Объемы Установит объем, который мы создали ( Captures ) в каталог, где изображения сохраняются в контейнере приложений Camera, а также в каталог хранения файлов в контейнере для Drobpy.

Эта последняя инструкция делает его таким, что, по сути, изображения загружаются в Drobpy, как только они будут захвачены нашей камерой приложение. Помимо этих общих полей, мы все еще должны сопоставить наше устройство камеры от хоста в контейнер приложений камеры, как у нас раньше, на Устройства Отказ

version: '3'
volumes:
  captures:
services:
  droppy:
    container_name: droppy
    image: silverwind/droppy
    ports:
      - '127.0.0.1:8989:8989'
    volumes:
      - captures:/files
  camera-app:
    container_name: cam
    image: camera-app
    ports:
      - '127.0.0.1:8080:8080'
    devices:
      - '/dev/video0:/dev/video0'
    volumes:
      - captures:/app/static/captures

Запуск этой настройки с Docker-Compose up Теперь мы можем получить доступ к нашей камере на localhost: 8080 и наш карточный сервер Image на localhost: 8989 Отказ Любое изображение, сделанное в приложении камеры, появится на Shavy Server, как мы видим ниже.

Когда вы закончите, обязательно используйте Флаг при запуске докер-состав Если вы хотите очистить объем, который мы создали, содержащие все захваченные изображения. Docker Compose делает интегральные приложения, такие как это очень простым, поэтому имейте удовольствие, настройку этой настройки для ваших собственных нужд или запуска свои собственные контейнеры!

Оригинал: “https://dev.to/carlosemv/dockerizing-a-flask-based-web-camera-application-469m”