Страницы

Поиск по вопросам

среда, 27 ноября 2019 г.

Распознавание знака бесконечности

#python #opencv


Как можно распознать знак бесконечности (именно его) на фото или видео?

Буду признателен, если приведете код к ответу.

UPD:
Объясните, как, например, с помощью контурного анализа понять, есть ли на фотографии
знак бесконечности. Пример ниже (в центре может быть полное соединение, человека может
быть видно - он может держать лист, цвет не важен).


    


Ответы

Ответ 1



OpenCV предоставляет множество инструментов для распознавания образов, в том числе и посредством контурного анализа. В третьей версии фреймворка практически всё, что касается сравнения контуров было выделено в отдельный модуль с говорящим названием Shape Distance and Matching. Автор вопроса не уточнил, с какими фигурами (наборами фигур) будет сравниваться знак бесконечности, и отметил лишь, что интерес представляет только факт похожести кандидата искомому объекту. Очевидно, что само по себе понятие "бесконечность" машине ничего не скажет, а потому придётся предложить ей некий образ в виде эталона. Пусть этот образ будет выглядеть так (файл model1.jpg): Между тем, чтобы убедиться, что раскрытый далее метод позволяет различать и другие фигуры, добавим к эталонной модели ещё несколько различных изображений (файлы model2.jpg, model3.jpg и model4.jpg соответственно): На самом деле все изображения одинакового размера и приведены в уменьшенном виде лишь с целью экономии места на странице. Начнём с выделения объекта, изображение которого предоставил автор вопроса: cv::Mat tst_src_mat = cv::imread("test.jpg", cv::IMREAD_GRAYSCALE); if(tst_src_mat.empty()) return; cv::Mat tst_bin_mat; cv::threshold(tst_src_mat, tst_bin_mat, 0, 255 , cv::THRESH_OTSU | cv::THRESH_BINARY_INV); После проведения бинаризации окажется, что помимо объекта интереса на изображении в левом нижнем углу присутствует и артефакт: Можно от него избавиться посредством простого и в чём-то философского подхода - не обращать внимания, оставив в поле зрения лишь тот контур, что наоборот - представляет интерес. Это можно сделать, например, ориентируясь на максимальную площадь и соответствующий индекс в векторе: std::vector > tst_cs; cv::findContours(tst_bin_mat.clone(), tst_cs , cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); int ci = -1; double max_area = 0.; for(int i = 0, n = tst_cs.size(); i < n; ++i) { const double area = cv::contourArea(tst_cs.at(i)); if(area > max_area) {max_area = area; ci = i;} } if(ci == -1) return; Далее следует нюанс, который подразумевает, что любые сравниваемые контуры должны иметь одинаковое количество точек в своём составе. Разумеется, что различные фигуры таковому правилу обычно следовать не будут, а значит придётся "на ручнике" им в этом помочь, просто добавив необходимое количество точек, но только с теми координатами, что и так уже имеются в фигуре: const int num_pts = 300; for(int i = tst_cs.at(ci).size()-1, d = 0; i < num_pts; ++i) tst_cs[ci].push_back(tst_cs[ci][d++]); Константа num_pts - это произвольное число. Оно в принципе зависит от того, с какой сложностью фигур предстоит работа. В идеале оно должно быть равно максимальному количеству точек у самого э-э-э... многоточечного контура из сравниваемых. Пожалуй, настало время перейти к ранее рассмотренным эталону и изображениям сильно отличающихся от тестового фигур: // Герой настоящей статьи, который собственно // и будет производить сравнение контуров. cv::Ptr sc = cv::createShapeContextDistanceExtractor(); for(int i = 0; i < 4; ++i) { std::string fname = std::string("model") + std::to_string(i+1) + std::string(".jpg"); cv::Mat src_mat = cv::imread(fname, cv::IMREAD_GRAYSCALE); if(src_mat.empty()) return -1; cv::Mat bin_mat; cv::threshold(src_mat, bin_mat, 0, 255 , cv::THRESH_OTSU | cv::THRESH_BINARY_INV); std::vector > cs; cv::findContours(bin_mat.clone(), cs , cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); for(int i = cs.at(0).size()-1, d = 0; i < num_pts; ++i) cs[0].push_back(cs[0][d++]); std::cout << fname << " - " << sc->computeDistance(tst_cs[ci], cs[0]) << std::endl; } Результатом работы кода окажутся такие значения: model1.jpg - 2.84489 model2.jpg - 112.033 model3.jpg - 32.8308 model4.jpg - 524.659 Изображение model1.jpg содержит знак бесконечности, а соответственно имеет и наименьшую дистанцию различия с тестовой фигурой. Изображения со знаком "собаки" (model2.jpg) и "серпа с молотом" (model4.jpg) в виду очевидных различий завершают список непохожести. Но кто бы мог подумать, что "бэтмену" (model3.jpg) здесь достанется второе место. А впрочем, если приглядеться, вполне возможно уловить общие с бесконечностью черты.

Ответ 2



Данный ответ устарел и соответствует вопросу в его изначальной версии. Как обучают детей алфавиту? Показывают картинки в букваре, произносят соответствующие им звуки. Как затем дети начинают распознавать символы букв, встречая их не в букваре? Очевидно, что на этот момент времени они уже достаточно затратили ресурсов, чтобы запомнить практически все возможные особенности форм начертания этих самых символов. Как шимпанзе обнаруживает бананы? Наверное в большей мере потому, что ей в своё время показали его, выделив в качестве самостоятельного и очень вкусного объекта. Любимая, я тебя поведу к самому краю Вселенной! Я подарю тебе эту звезду, светом нетленным будет она озарять нам путь в бесконечность... На что надеялась Любимая, принимая предложение двигать в бесконечность? Вероятнее всего, что заложенные ранее ассоциации позволили ей понять, что это будет как минимум приятное путешествие. А что же машина? А у машины нет того опыта, что получают ребёнок, шимпанзе и Любимая. С машиной придётся работать, чтобы она могла начать различать бесконечность, нарисованную на бумаге в виде знака, бесконечность бананового чревоугодия и бесконечность пути под светом нетленным. Заценив масштаб трагедии, сколько сделано и сколько всего ещё нужно сделать, разработчики (некоторые уже на Седьмой день) начинают понимать, что необходимо срочно сужать поле деятельности, ограничив творческий потенциал локальными изменениями. Кто-то выбирает набор изображений с конкретным начертанием символа бесконечности на определённом фоне, чтобы иметь возможность работать с контурами. Кто-то выбирает видеоряд, но всё с теми же конкретизирующими выборку условиями. В любом случае, творец более не ограничивает себя стремлением объять необъятное, а если даже и спросит у соседей, ковыряющихся в своих мирах, помощи, то максимально конкретизирует вопрос, предложив им на рассмотрение пару примеров собственного виденья предмета. И все довольны.

Ответ 3



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

Комментариев нет:

Отправить комментарий