Распознавание образов opencv. Пишем скрипт для поиска книг на изображениях с помощью Python и OpenCV. Сопоставление с шаблоном
Важнейшими источниками информации о внешнем мире для робота являются его оптические датчики и камеры. После получения изображения необходима его обработка для анализа обстановки или принятия решения. Как я говорил ранее, компьютерное зрение объединяет множество методов работы с изображениями. При функционировании робота предполагается, что видеоинформация с камер обрабатывается какой-либо программой, запущенной на контроллере. Чтобы не писать код с нуля, можно воспользоваться готовыми программными решениями. На текущий момент существует множество готовых библиотек компьютерного зрения:
- Matrox Imaging Library
- Camellia Library
- Open eVision
- HALCON
- libCVD
- OpenCV
- и т.д…
- поиск и распознавание конкретного объекта,
- поиск объектов одной категории (без распознавания),
- только распознавание объекта (уже готовое изображение с ним).
- Гистограмма направленных градиентов HOG(Histogram of Oriented Gradients) — может применяться для обнаружения пешеходов
- Алгоритм Виолы-Джонса — применяется для поиска лиц
- Алгоритм обнаружения признаков SIFT (Scale Invariant Feature Transform)
- Алгоритм обнаружения признаков SURF (Speeded Up Robust Features)
- http://opencv.org/ — Основной сайт проекта
- http://opencv.willowgarage.com/wiki/ — Старый сайт проекта с документацией по старым версиям
В этой статье использован C++ интерфейс, FREAK и детектирование множества объектов. Надежность детектирования объектов с помощью FREAK ниже, чем SURF, однако его работа намного быстрее, что позволяет использовать алгоритм на мобильных и встроенных системах. Пример работы представлен на рисунке:
Рассмотрим исходный код, который позволяет этого достигнуть. Код приведен полностью для желающих быстро вставить его в свой проект.
#include
Для любых особенностей в OpenCV необходимо инициализировать класс SurfFeatureDetector. Первое действие после различных инициализаций – это детектирование особенностей detector.detect для эталонного изображения и изображения сцены. После чего для каждого изображения по результатам работы детектора вычисляются FREAK особенности: extractor.compute.
Сравнение схожести особенностей осуществляется с помощью matcher.match.
Далее присутствует цикл с формированием точек из особенностей для обоих изображений. На основании точек вычисляется гомография изображений findHomography. Положение и поворот объекта вычисляется с помощью функции perspectiveTransform. Ну а затем – вывод на изображение.
Эталонное изображение:
Изображение сцены:
Результат представлен вначале.
Однако здесь возникает вопрос, как рассчитывать оптимальный порог особенностей: SurfFeatureDetector detector(1000);. Ответ – экспериментально. Некоторую информацию по данному вопросу вы можете получить .
Предположим, что у нас на изображении несколько объектов:
Результат работы программы будет следующий:
Естественно, что такая ситуация не устраивает. Для того, чтобы детектировать все объекты, необходимо разделить изображение на несколько частей. Однако здесь следует помнить, что если изображение разделить на непересекающиеся блоки (пример изображение 100x100 разделить на 4 блока по 50x50), то может возникнуть ситуация, когда объект будет частично находиться в нескольких блоках и не будет детектирован. Для избегания этого необходимо делать пересекающиеся блоки, что несколько замедлит работу, но улучшит качество (пример изображение 100x100 разделить на 9 блоков по 50x50 так, как показано в примере). Пример программы детектирующий множество объектов ниже:
#include
Результат работы следующий:
Видно, что все объекты детектированы. Причем некоторые дважды (из-за того, что попали в два блока).
При решении задач компьютерного зрения не обойтись без использования специализированного софта. Хочу познакомить вас с таким - OpenCV - библиотека с открытым исходном кодом на C++. Обладает набором инструментов для оцифровки изображений, последующей обработки через численные алгоритмы или нейросеть.
Базовые алгоритмы обработки изображений: интерпретации изображений, калибровки камеры по эталону, устранение оптических искажений, определение сходства, анализ перемещения объекта, определение формы объекта и слежение за объектом, 3D-реконструкция, сегментация объекта, распознавание жестов.
Скачать библиотеку можно на официальном сайте http://sourceforge.net/projects/opencvlibrary/
Структура библиотеки OpenCV
cxcore - ядро
* содержит базовые структуры данных и алгоритмы:
- базовые операции над многомерными числовыми массивами
- матричная алгебра, математические ф-ции, генераторы случайных чисел
- Запись/восстановление структур данных в/из XML
- базовые функции 2D графики
CV - модуль обработки изображений и компьютерного зрения
- базовые операции над изображениями (фильтрация, геометрические преобразования, преобразование цветовых пространств и т. д.)
- анализ изображений (выбор отличительных признаков, морфология, поиск контуров, гистограммы)
- анализ движения, слежение за объектами
- обнаружение объектов, в частности лиц
- калибровка камер, элементы восстановления пространственной структуры
Highgui - модуль для ввода/вывода изображений и видео, создания пользовательского интерфейса
- захват видео с камер и из видео файлов, чтение/запись статических изображений.
- функции для организации простого UI (все демо приложения используют HighGUI)
Cvaux - экспериментальные и устаревшие функции
- пространств. зрение: стерео калибрация, само калибрация
- поиск стерео-соответствия, клики в графах
- нахождение и описание черт лица
CvCam - захват видео
- позволяет осуществлять захват видео с цифровых видео-камер (поддержка прекращена и в последних версиях этот модуль отсутствует)
Установка OpenCV под Linux
После скачивания последней версии OpenCV с сайта разработчика http://sourceforge.net/projects/opencvlibrary/ нужно распаковать архив и выполнить сборку через CMake версии 2.6 или выше.
Установка CMake выполняется стандартно:
Sudo apt-get install cmake
Для отображения окон OpenCV потребуется установить библиотеки GTK+ 2.x и libgtk2.0-dev
Apt-get install libgtk2.0-dev
Собираем библиотеку:
Tar -xjf OpenCV-2.2.0.tar.bz2 cd OpenCV-2.2.0 cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ./ make make install
Для тестирования установленной библиотеки можно собрать примеры и что-нибудь запустить:
Cd samples/c/ chmod +x build_all.sh ./build_all.sh ./delaunay
Если вместо тестовой картинки вы увидите ошибку "error while loading shared libraries: libopencv_core.so.2.2: cannot open shared object file: No such file or directory", то это значит, что программа не может найти библиотеки. Нужно явно указать путь до них:
$ export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
Если после этого опять ошибка:
OpenCV Error: Unspecified error (The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Carbon support. If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script) in cvNamedWindow, file /usr/src/OpenCV-2.2.0/modules/highgui/src/window.cpp, line 274
terminate called after throwing an instance of "cv::Exception" what(): /usr/src/OpenCV-2.2.0/modules/highgui/src/window.cpp:274: error: (-2) The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Carbon support. If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script in function cvNamedWindow
Значит вы забыли установить GTK+ 2.x: libgtk2.0-dev. Запустите установку (см. выше).
Когда установка завершена заголовочные файлы будут доступны в дирректории /usr/local/include/opencv , а библиотечные файлы лежат в /usr/local/lib
Соберем программу с OpenCV:
test.cpp
//
// for testing
//
// robocraft.ru
//
#include
Makefile
CC:= g++ CFLAGS:= -I/usr/local/include/opencv -L/usr/local/lib OBJECTS:= LIBRARIES:= -lopencv_core -lopencv_imgproc -lopencv_highgui .PHONY: all clean all: test test: $(CC) $(CFLAGS) -o test test.cpp $(LIBRARIES) clean: rm -f *.o
Запуск сборки коммандой make.
Hello World!
OpenCV установлен и готов к работе. Напишем свое первое приложение Hello World!
#include
Загрузка изображения
Данный пример будет основой всех ваших программ на OpenCV. Мы загрузим в среду изображение из файла Image0.jpg
#include
Поддерживаемые типы форматов изображений:
- Windows bitmaps - BMP, DIB
- JPEG files - JPEG, JPG, JPE
- Portable Network Graphics - PNG
- Portable image format - PBM, PGM, PPM
- Sun rasters - SR, RAS
- TIFF files - TIFF, TIF
Для обращения к изображению можно делать такие вызовы:
Image->nChannels // число каналов картинки (RGB, хотя в OpenCV - BGR) (1-4) image->depth // глубина в битах image->width // ширина картинки в пикселях image->height // высота картинки в пикселях image->imageSize // память занимаемая картинкой (==image->height*image->widthStep) image->widthStep // расстояние между соседними по вертикали точками изображения (число байт в одной строчке картинки - может потребоваться для самостоятельного обхода всех пикселей изображения)
Загрузка видео
Загрузка видео не на много сложнее, чем загрузка изображения за тем исключением, что будет цикл, который перебирает кадры.
Задержка между кадрами задана в 33 миллисекунды т.к. такая задержка позволяет обрабатывать видеопоток с стандартной частотой 30 кадров в секунду.
#include
Для захвата видео с камеры нужно немного модифицировать код - вместо функции cvCreateFileCapture() будет использоваться cvCreateCameraCapture(). При нажатии ESC воспроизведение прервется и окно закроется, а при нажатии Enter текущий кадр сохранится в jpg файл.
#include
OpenCV v1.0 показывает и сохраняет картинку минимального разрешения камеры 320x240.
Распознавание объектов по шаблону
Для распознавание областей на исходном изображении по шаблону существует функция cvMatchTemplate(). Функция накладывает шаблон изображения на текущее изображение и согласно выбранному алгоритму выполняет поиск корреляции между ними. Определение границ найденного шаблона на исходном изображении выполняется функцией cvMinMaxLoc, а для нормализации алгоритма поиска cvNormalize().
//
// пример cvMatchTemplate()
// сравнение изображение с шаблоном
//
#include
Из этой статьи вы узнаете, как создать Python-скрипт для подсчёта количества книг на изображении с помощью OpenCV .
Что мы будем делать?
Взглянем на изображение, на котором будем искать книги:
Мы видим, что на изображении находятся четыре книги, а также отвлекающие вещи, такие как кружка кофе, чашка Starbucks, несколько магнитов и конфета.
Наша цель заключается в том, чтобы найти четыре книги на изображении, при этом не определив никакой другой предмет как книгу.
Какие библиотеки нам понадобятся?
Чтобы написать систему для поиска и обнаружения книг на изображениях, мы будем использовать OpenCV для работы с компьютерным зрением и обработки изображений. Нам также необходимо установить NumPy для корректной работы OpenCV. Убедитесь, что у вас установлены эти библиотеки!
Поиск книг на изображениях с помощью Python и OpenCV
Прим. перев. Вы можете заметить, что исходный код в нашей статье отличается от кода в оригинале. Автор, вероятно, использовал установку необходимых библиотек через репозитории. Мы предлагаем использовать pip, что гораздо проще. Во избежание появления ошибок рекомендуем использовать версию кода, приведенную в нашей статье.
Откройте свой любимый редактор кода, создайте новый файл с именем find_books.py и начнем:
# -*- coding: utf-8 -*- # импортируйте необходимые пакеты import numpy as np import cv2 # загрузите изображение, смените цвет на оттенки серого и уменьшите резкость image = cv2.imread("example.jpg") gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) gray = cv2.GaussianBlur(gray, (3, 3), 0) cv2.imwrite("gray.jpg", gray)
Начнем с импорта библиотеки OpenCV. Загрузка изображения с диска обрабатывается функцией cv2.imread . Здесь мы просто загружаем его с диска, а затем преобразуем цветовую гамму из RGB в оттенки серого.
Мы также немного размываем изображение, чтобы уменьшить высокочастотные шумы и повысить точность нашего приложения. После выполнения кода изображение должно выглядеть так:
Мы загрузили изображение с диска, преобразовали его в оттенки серого и немного размыли.
Теперь давайте определим края (т.е. контуры) объектов на изображении:
# распознавание контуров edged = cv2.Canny(gray, 10, 250) cv2.imwrite("edged.jpg", edged)
Теперь наше изображение выглядит следующим образом:
Мы нашли контуры объектов на изображениях. Однако, как вы видите, некоторые из контуров не закрыты - между контурами существуют промежутки. Чтобы убрать промежутки между белыми пикселями изображения, мы применим операцию «закрытия»:
# создайте и примените закрытие kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7)) closed = cv2.morphologyEx(edged, cv2.MORPH_CLOSE, kernel) cv2.imwrite("closed.jpg", closed)
Теперь пробелы в контурах закрыты:
Следующим шагом является фактическое обнаружение контуров объектов на изображении. Для этого мы будем использовать функцию cv2.findContours:
# найдите контуры в изображении и подсчитайте количество книг cnts = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) total = 0
Рассмотрим геометрию книги.
Книга представляет собой прямоугольник. У прямоугольника четыре вершины. Поэтому, если мы рассмотрим контур и обнаружим, что он имеет четыре вершины, то мы можем предположить, что это книга, а не другой предмет на изображении.
Чтобы проверить, является ли контур книгой или нет, нам нужно выполнить цикл по каждому контуру:
# цикл по контурам for c in cnts: # аппроксимируем (сглаживаем) контур peri = cv2.arcLength(c, True) approx = cv2.approxPolyDP(c, 0.02 * peri, True) # если у контура 4 вершины, предполагаем, что это книга if len(approx) == 4: cv2.drawContours(image, , -1, (0, 255, 0), 4) total += 1
Для каждого из контуров мы вычисляем периметр, используя cv2.arcLength , а затем аппроксимируем (сглаживаем) контур, используя cv2.approxPolyDP .
Причина, по которой мы аппроксимируем контур, заключается в том, что он может не быть идеальным прямоугольником. Из-за зашумления и теней на фото вероятность того, что у книги будет ровно 4 вершины, невелика. Аппроксимируя контур, мы решаем эту проблему.
Наконец, мы проверяем, что у аппроксимируемого контура действительно четыре вершины. Если это так, то мы рисуем контур вокруг книги, а затем увеличиваем счётчик общего количества книг.
Завершим этот пример, показывая полученное изображение и количество найденных книг:
# показываем результирующее изображение print("Я нашёл {0} книг на этой картинке".format(total) cv2.imwrite("output.jpg", image))
На данном этапе наше изображение будет выглядеть так:
Подведем итоги
В этой статье вы научились находить книги на изображениях, используя простые методы обработки изображений и компьютерного зрения с помощью Python и OpenCV.
Наш подход состоял в том, чтобы:
- Загрузить изображение с диска и преобразовать его в оттенки серого.
- Немного размыть изображение.
- Применить детектор контуров Canny для обнаружения объектов на изображении.
- Закрыть любые промежутки в контурах.
- Найти контуры объектов на изображении.
- Применить контурную аппроксимацию, чтобы определить, был ли контур прямоугольником и, следовательно, книгой.
Вы можете скачать исходный код скрипта и изображение, которое используется в этой статье.
Ну, в основном вам нужно обнаружить круги . Вы видели cvHoughCircles() ? Разрешено ли вам это использовать?
На этой странице есть хорошая информация о том, как обнаружить вещи с помощью OpenCV . Вас может заинтересовать раздел 2.5 .
Это небольшая демонстрация, которую я только что написал, чтобы обнаружить монеты на этой картинке. Надеюсь, вы можете использовать часть кода в своих интересах.
Вход :
Выходы :
// compiled with: g++ circles.cpp -o circles `pkg-config --cflags --libs opencv`
#include
Обнаружение кругов сильно зависит от параметров cvHoughCircles() . Обратите внимание, что в этой демонстрации я также использовал Canny.
Я должен закодировать детектор объекта (в данном случае шарик) с помощью OpenCV. Проблема в том, что каждый поиск в google возвращает мне что-то с FACE DETECTION. Поэтому мне нужна помощь в том, с чего начать, что использовать и т. Д.
Некоторая информация:
- Мяч не имеет фиксированного цвета, он, вероятно, будет белым, но он может измениться.
- Я должен использовать машинное обучение, не обязательно быть сложным и надежным, предложение KNN (это проще и проще).
- После всего моего поиска я обнаружил, что вычисление гистограммы образцов только для шаров и обучение его ML может быть полезным, но моя главная забота здесь в том, что размер шара может и изменится (ближе и дальше от камеры) и я понятия не имею, что передать ML, чтобы классифицировать для меня, я имею в виду.. я не могу (или я могу?) просто проверить каждый пиксель изображения для каждого возможного размера (от, скажем, от 5x5 до WxH) и надеемся найти положительный результат.
- Там может быть неравномерный фон, например, люди, ткань за мячом и т. Д.
- Как я уже сказал, мне нужно использовать алгоритм ML, что означает отсутствие алгоритмов Хаара или Виолы.
Кроме того, я думал об использовании контуров, чтобы найти круги на изображении Canny"ed, просто нужно найти способ преобразования контура в строку данных для обучения KNN.
Итак... предложения?
Заранее спасибо. ;)