Jump to content
Compvision.ru
lngvar

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

Recommended Posts

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

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

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

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

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

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

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

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

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

 

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

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

Share this post


Link to post
Share on other sites

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

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

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

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

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

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

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

 

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

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

t1.png.694beee0e77284d9a39002cc1172aa79.png

____________________________

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

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

t22.png.c15daf829611f37f25be5fbb74b0e38a.png

____________________________

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

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

t3.png.dfdba54d037cfe3b386899d4f86c49ed.png

__________________________

 

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

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

 

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

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites
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)  

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites
11 час назад, lngvar сказал:

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

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

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

 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 это очень долго.

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

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

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

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

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

 

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

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

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

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

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

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

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

 

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Recently Browsing   0 members

    No registered users viewing this page.

×