You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
IoT-For-Beginners/translations/ru/5-retail/lessons/2-check-stock-device/single-board-computer-count...

14 KiB

Подсчет товаров с вашего IoT-устройства - Виртуальное IoT-оборудование и Raspberry Pi

Сочетание предсказаний и их ограничивающих рамок можно использовать для подсчета товаров на изображении.

Отображение ограничивающих рамок

В качестве полезного шага отладки вы можете не только вывести ограничивающие рамки в консоль, но и нарисовать их на изображении, которое сохраняется на диск при захвате изображения.

Задача - вывести ограничивающие рамки

  1. Убедитесь, что проект stock-counter открыт в VS Code, и виртуальная среда активирована, если вы используете виртуальное IoT-устройство.

  2. Измените оператор print в цикле for на следующий, чтобы вывести ограничивающие рамки в консоль:

    print(f'{prediction.tag_name}:\t{prediction.probability * 100:.2f}%\t{prediction.bounding_box}')
    
  3. Запустите приложение с камерой, направленной на товары на полке. Ограничивающие рамки будут выведены в консоль с указанием значений left, top, width и height в диапазоне от 0 до 1.

    pi@raspberrypi:~/stock-counter $ python3 app.py 
    tomato paste:   33.42%  {'additional_properties': {}, 'left': 0.3455171, 'top': 0.09916268, 'width': 0.14175442, 'height': 0.29405564}
    tomato paste:   34.41%  {'additional_properties': {}, 'left': 0.48283678, 'top': 0.10242918, 'width': 0.11782813, 'height': 0.27467814}
    tomato paste:   31.25%  {'additional_properties': {}, 'left': 0.4923783, 'top': 0.35007596, 'width': 0.13668466, 'height': 0.28304994}
    tomato paste:   31.05%  {'additional_properties': {}, 'left': 0.36416405, 'top': 0.37494493, 'width': 0.14024884, 'height': 0.26880276}
    

Задача - нарисовать ограничивающие рамки на изображении

  1. Пакет Pip Pillow можно использовать для рисования на изображениях. Установите его с помощью следующей команды:

    pip3 install pillow
    

    Если вы используете виртуальное IoT-устройство, убедитесь, что команда выполняется внутри активированной виртуальной среды.

  2. Добавьте следующий оператор импорта в начало файла app.py:

    from PIL import Image, ImageDraw, ImageColor
    

    Это импортирует код, необходимый для редактирования изображения.

  3. Добавьте следующий код в конец файла app.py:

    with Image.open('image.jpg') as im:
        draw = ImageDraw.Draw(im)
    
        for prediction in predictions:
            scale_left = prediction.bounding_box.left
            scale_top = prediction.bounding_box.top
            scale_right = prediction.bounding_box.left + prediction.bounding_box.width
            scale_bottom = prediction.bounding_box.top + prediction.bounding_box.height
    
            left = scale_left * im.width
            top = scale_top * im.height
            right = scale_right * im.width
            bottom = scale_bottom * im.height
    
            draw.rectangle([left, top, right, bottom], outline=ImageColor.getrgb('red'), width=2)
    
        im.save('image.jpg')
    

    Этот код открывает ранее сохраненное изображение для редактирования. Затем он проходит по предсказаниям, получая ограничивающие рамки, и вычисляет координаты нижнего правого угла, используя значения ограничивающих рамок от 0 до 1. Эти значения преобразуются в координаты изображения путем умножения на соответствующее измерение изображения. Например, если значение left равно 0.5 для изображения шириной 600 пикселей, оно преобразуется в 300 (0.5 x 600 = 300).

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

  4. Запустите приложение с камерой, направленной на товары на полке. Вы увидите файл image.jpg в обозревателе VS Code и сможете выбрать его, чтобы увидеть ограничивающие рамки.

    4 банки томатной пасты с ограничивающими рамками вокруг каждой банки

Подсчет товаров

На изображении выше ограничивающие рамки слегка перекрываются. Если бы это перекрытие было значительно больше, рамки могли бы указывать на один и тот же объект. Чтобы правильно подсчитать объекты, необходимо игнорировать рамки с существенным перекрытием.

Задача - подсчет товаров с учетом перекрытия

  1. Пакет Pip Shapely можно использовать для вычисления пересечения. Если вы используете Raspberry Pi, сначала необходимо установить библиотеку-зависимость:

    sudo apt install libgeos-dev
    
  2. Установите пакет Shapely через Pip:

    pip3 install shapely
    

    Если вы используете виртуальное IoT-устройство, убедитесь, что команда выполняется внутри активированной виртуальной среды.

  3. Добавьте следующий оператор импорта в начало файла app.py:

    from shapely.geometry import Polygon
    

    Это импортирует код, необходимый для создания полигонов для вычисления перекрытия.

  4. Над кодом, который рисует ограничивающие рамки, добавьте следующий код:

    overlap_threshold = 0.20
    

    Это определяет процент перекрытия, допустимый перед тем, как ограничивающие рамки будут считаться принадлежащими одному объекту. Значение 0.20 задает 20% перекрытия.

  5. Чтобы вычислить перекрытие с использованием Shapely, ограничивающие рамки нужно преобразовать в полигоны Shapely. Добавьте следующую функцию для этого:

    def create_polygon(prediction):
        scale_left = prediction.bounding_box.left
        scale_top = prediction.bounding_box.top
        scale_right = prediction.bounding_box.left + prediction.bounding_box.width
        scale_bottom = prediction.bounding_box.top + prediction.bounding_box.height
    
        return Polygon([(scale_left, scale_top), (scale_right, scale_top), (scale_right, scale_bottom), (scale_left, scale_bottom)])
    

    Эта функция создает полигон, используя ограничивающую рамку предсказания.

  6. Логика удаления перекрывающихся объектов включает сравнение всех ограничивающих рамок. Если у какой-либо пары предсказаний рамки перекрываются больше, чем допустимый порог, одно из предсказаний удаляется. Чтобы сравнить все предсказания, вы сравниваете предсказание 1 с 2, 3, 4 и т.д., затем 2 с 3, 4 и т.д. Следующий код выполняет это:

    to_delete = []
    
    for i in range(0, len(predictions)):
        polygon_1 = create_polygon(predictions[i])
    
        for j in range(i+1, len(predictions)):
            polygon_2 = create_polygon(predictions[j])
            overlap = polygon_1.intersection(polygon_2).area
    
            smallest_area = min(polygon_1.area, polygon_2.area)
    
            if overlap > (overlap_threshold * smallest_area):
                to_delete.append(predictions[i])
                break
    
    for d in to_delete:
        predictions.remove(d)
    
    print(f'Counted {len(predictions)} stock items')
    

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

    Как только предсказание помечено для удаления, его больше не нужно проверять, поэтому внутренний цикл прерывается, чтобы проверить следующее предсказание. Нельзя удалять элементы из списка во время его итерации, поэтому рамки, перекрывающиеся больше допустимого порога, добавляются в список to_delete, а затем удаляются в конце.

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

    💁 Это очень простой способ удаления перекрытий, при котором удаляется первое из двух перекрывающихся предсказаний. Для производственного кода вы могли бы добавить больше логики, например, учитывать перекрытия между несколькими объектами или случаи, когда одна рамка полностью содержится в другой.

  7. Запустите приложение с камерой, направленной на товары на полке. Вывод покажет количество ограничивающих рамок без перекрытий, превышающих порог. Попробуйте изменить значение overlap_threshold, чтобы увидеть, как предсказания игнорируются.

💁 Этот код можно найти в папке code-count/pi или code-count/virtual-iot-device.

😀 Ваше приложение для подсчета товаров успешно завершено!


Отказ от ответственности:
Этот документ был переведен с помощью сервиса автоматического перевода Co-op Translator. Несмотря на наши усилия обеспечить точность, автоматические переводы могут содержать ошибки или неточности. Оригинальный документ на его исходном языке следует считать авторитетным источником. Для получения критически важной информации рекомендуется профессиональный перевод человеком. Мы не несем ответственности за любые недоразумения или неправильные интерпретации, возникшие в результате использования данного перевода.