Перейти к содержимому
Compvision.ru
lngvar

Минимальный проект поиска по шаблону

Recommended Posts

Заранее прошу прощения за такой простой вопрос.

Перевожу на visual c++ 2010  свой проект с AHK.

Уперся в проблему поиска картинки на экране.

В AHK есть элементарная функция  imagesearch которая возвращает x,y  первого нахождения заданного шаблона и позволяет задать вариативность.

Крайне важна скорость поиска. 

Можете подсказать как на opencv  сделать подобное, без излишних затрат процессорного времени ?

Поиск без масштабирования, без вращения,   разве что очень небольшая вариативность оттенков цвета.

Шаблоны - прямоугольники 10-50 пикселей  по сторонам максимум.

Выборка со всего экрана или с его части .

 

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

А простого поиска к сожалению найти не смог.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

я видел подобное, но там идет довольно серьезное распознавание.

А мне нужен всего лишь поиск картинки  с небольшой вариативностью в оттенках . С ответом да\нет.

Без поиска наиболее подходящего, потому что все упирается в скорость исполнения.

Может у opencv нет ответа на такие примитивы  ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Это ты называешь серьезным распознаванием? Насмешил ))

Картинки покажи. Есть более простые логическое И, ИЛИ и исключающее ИЛИ. Возможно, MorphologyEx+TopHat с маской. Предложил бы классификатор, но ты называешь matching сложным. Всякое можно придумать, в зависимости от задачи. Но все это не очень-то робастно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Давайте я попробую яснее определить свои потребности и свои трудности в распознавании.

Только заранее прошу извинить за мою шкалу легко-трудно.

 

Все 3 картинки это сильно увеличенный шрифт.

1. Вот это элементарный фрагмент, который autohotkey находит за 15-20 мс.

t1.png.694beee0e77284d9a39002cc1172aa79.png

____________________________

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

Но я уверен что средствами opencv это легко будет сделать. И я думаю я справлюсь сам.

t22.png.c15daf829611f37f25be5fbb74b0e38a.png

____________________________

3. Третий фрагмент имеет более или менее выраженные и постоянные  шумы, которые при определенной вариативности оттенков  поиска позволяет его

довольно точно и быстро находить. Время поиска примерно 30-50 мс в зависимости от указанной вариативности оттенков.  ( опять же в автохоткее)

t3.png.dfdba54d037cfe3b386899d4f86c49ed.png

__________________________

 

Вот я прошу подсказать, первый и третий вариант есть возможность реализовать средствами opencv с сопоставимой скоростью ?

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

 

Извиняюсь за логотип клиптунета.  Конечно же в настоящих файлах он не присутствует

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Все три примера довольно тривиальны, по времени обработки на нормальном железе (в смысле не четвертый пентиум, а что то помоложе) и с таким размером файла 5мс максимум.  Это средствами opencv.

Но я бы сперва попробовал tesseract.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
38 минут назад, iskees сказал:

Все три примера довольно тривиальны, по времени обработки на нормальном железе (в смысле не четвертый пентиум, а что то помоложе) и с таким размером файла 5мс максимум.  Это средствами opencv.

Но я бы сперва попробовал tesseract.

опять я неточно пояснил свою потребность.

Мне не надо ничего распознавать, мне надо найти заранее заготовленные картинки, и получить x,y   их на экране.

а tesseract, как я понял, это OCR , идет работа по распознанию, поправьте меня если ошибаюсь.

Тем более что текст я привел для наглядности, сложного и простого случая. А еще у меня заготовленны картинки 10х10 точек.

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

И максимально быстрый для первого варианта.

Я почитал какие вы задачи решаете тут на форуме, и мне очень неудобно задавать такие нубские вопросы.

Просто мне на данный момент нет возможности углубляться в opencv, но проект мой остановился на перепутье -

смогу ли я найти способ на с++ найти достойную замену imagesearch или нет.

p.s но тессеракт конечно заинтриговал,  как вариант получения незапланированного текста на экране .

p.s  Фактически я хочу завернуть метод opencv по поиску картинки в виде ...

imgsearch ( int &x, int &y,  int x1, int y1,int x2, int y2,  int variation, char* namefile)  

для совместимости.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Если картинки не сдвинуты по осям относительно друг друга, то самый простой и быстрый вариант это использовать логические операции. Тот же XOR, а после смотреть количество белых пикселей countNonZero (если совпали, то их будет мало). Бинаризировать только сперва обе картинки надо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

и это в контексте поиска картинки на экране ?

Ваш способ по-моему подходит просто для сравнения двух картинок, а не поиска.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
11 час назад, lngvar сказал:

и это в контексте поиска картинки на экране ?

Ваш способ по-моему подходит просто для сравнения двух картинок, а не поиска.

Для поиска добавьте скользящее окно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Есть какие то примеры для подобного ? Может кто-то навскидку привести ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Мне кажется, что надо начать с элементарного, MatchTemplate. Там никакого распознавания не происходит, работает быстро. Пусть это будет точка, от которой можно отталкиваться по скорости работы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

окей. Две картинки

 all.thumb.jpg.9ba9ca7996f38749768094bfe5e57775.jpg      1920х1080

need.jpg.a6a83604562e0802c355c80165616f0e.jpg                                 20х20

следующим кодом ищу второе на первом.

#include "stdafx.h"
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include "time.h"

IplImage* image = 0;
IplImage* templ = 0;

int _tmain(int argc, _TCHAR* argv[])
{
	char* filename = "c:/dir/all.jpg";
	image = cvLoadImage(filename,1);
	char* filename2 = "c:/dir/need.jpg";
	templ = cvLoadImage(filename2,1);
	IplImage *res = cvCreateImage( cvSize( (image->width-templ->width+1), (image->height-templ->height+1)), IPL_DEPTH_32F, 1 );
	double    minval, maxval;
	CvPoint    minloc, maxloc;
	
     // ------------------------------------------------------------------------------------------------------
  clock_t t=clock();
	for(int z=1;z<=100;z++)
	{
	cvMatchTemplate(image, templ, res, CV_TM_SQDIFF);
	}
	t=clock()-t;
    t=(double)t/CLOCKS_PER_SEC;//t время в секундах )
	std::cout<<t<<" sec"<<std::endl;
    // --------------------------------------------------------------------------------------------------------
    cvMinMaxLoc(res, &minval, &maxval, &minloc, &maxloc, 0);
    cvRectangle(image, cvPoint(minloc.x, minloc.y), cvPoint(minloc.x+templ->width-1, minloc.y+templ->height-1), CV_RGB(255, 0, 0), 1, 8);
	cvShowImage("Match", image);
	cvWaitKey(0);
	cvReleaseImage( &image );
	cvReleaseImage( &templ );
	cvReleaseImage( &res );
	cvDestroyAllWindows(); 
	return 0;
}

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

Потому что на моем core i5 это занимает неприличные  35 секунды за 100 итераций. ( загрузка проца 24% )

350 мс на подготовленный поиск и это без учета cvMinMaxLoc это очень долго.

Может есть вариант это сделать какой то другой библиотекой ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Понятно. Тогда MatchTemplate просто делает не то, что требуется: ищет не первое вхождение (видимо, по какому-то порогу), а карту всех вхождений. Отсюда и низкая скорость.

Честно говоря, я не уверен, что подходящая функция в OpenCV есть. Но и реализация не должна быть сложно, разве нет?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

это очень печально, были большие надежды на opencv

А то на всех форумах на вопросы про быстрый поиск все умно кивают в сторону opencv,  хотя не имеют не малейшего представления о нем.

Теперь по крайней мере я знаю что это качественный поиск, но не быстрый.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ммм, он и правда быстрый, просто у тебя задача по-другому формулируется.

Мне, например, интересно, что значит "первое нахождение заданного шаблона". Там же куча метрик, совпадение пиксель-в-пиксель в реальных приложениях явно не возможно. В смысле, чтобы значение каждого пикселя совпало и метрика стала нулевой. Также понятно, что минимум врядли будет находиться в одной точке. Скорее всего, будет что-то похожее на параболоид - если визуализировать результат работы сравнения в 3D. И тут вопрос, насколько он пологий. Если сильно пологий, то не исключено, что результат ложный. То есть мало получить значение метрики ниже какого-то порога, надо ещё и проанализировать окрестность, чтобы убедиться в том, что минимум настоящий. У меня был опыт в нахождении таких штук: надо было определиться куда сместились блоки по 16х16 пикселей. Такие блоки на границах объектов, на чистом небе, на регулярных структурах (окна дома вдалеке) давали совершенно неожиданные результаты. Приходилось выдумывать сложные метрики и анализ.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ну смотри, если есть время обсудить это... На самом деле это не фотографии.

Это экран в Д3Д. Есть спрайтовые фигуры, текст. Все это заключено в небольшие прямоугольники и сохранены в bmp.

Если бы не размытость и сглаживание, можно было бы обычной логикой сравнивать. Поэтому нужна небольшая вариативность.

Я подбираю минимальный параметр разброса оттенков и первое удачное попадание - это и есть искомый вариант.

Уже нашел и подключил imagesearchdll.dll  работающий по такому принципу, но иногда попадаются задачи которые ему не по зубам.

Вот и я просил помощи, что если бы opencv мог решать эффективно такие простые примитивы. Теперь мне придется пользоваться двумя инструментами, разделяя задачи на  скорость и качество.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Можно более формально описать задачу и оставить один работающий способ. При вызове того же matchTemplate указывается метрика, по которой сравнение происходит. Запусти его на всех твоих возможных данных и посмотри итоговые значения, при которых всё находится правильно. Ещё можно посмотреть на результаты в малой окрестности. Так можно определиться с минимальнылм порогом и понять, что это именно он.

Далее уже самому написать цикл, в котором пробегаться по всей картинке и сравнивать. Причём можно сравнивать не весь кусочек целиком, а делать быстрый выход, если мы превысим порог по метрике на первых пикселях. То есть решать именно твою задачу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

написал красиво, надо углубляться.

Я думал что есть готовые решения в таком объемном продукте, а все 6 стандартных методов поиска не подходят при своем сложности.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×