Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > быстрое сравнение изображений


Автор: loginrl103 25.2.2009, 21:02
Имеется с десяток битмапов (примерно 80 х 80) и большой изображение (1000 х 1000). Надо за минимальное время найти все битмапы на изображении; на изображении битмапы могут быть повёрнуты.

Хотелось бы узнать какие библиотеки способны такое сделать (быстро), и можно код. smile

ps. гугл выдал кучу ссылок на обработку изображений, но какие реально быстро работают из них не узнать(

Автор: GoldFinch 25.2.2009, 21:41
корелляцию посчитай в окне 80х80

Автор: Курсант 25.2.2009, 21:42
Есть у меня что то похожее, но на Делфи, битмапы не повернутые, и еще учитывается прозрачность фона искомого битмапа (то есть там где у искомого битмапа белый цвет на большом битмапе может быть любая точка). Писал давно, точно как работает не помню, можете попробовать разобраться сами... Насчет скорости не уверен я - для 80-ти то битмапов это в любом случае не меньше минуты будет... Что касается повернутости битмапов - попробуйте поискать сначала неповернутые, потом поверните искомые битмапы и поищите их, и так три раза... Разумеется битмапы должны быть повернуты на угол кратный 90 градусов...

Программка охотилась за меня на монстров в онлайн игре, искала их на экране по подписи под ними и щелкала мышкой в монстра, то есть нападала на него... В общем может чем нить будет полезно Вам... Ваша задача - заменить загрузку изображения с экрана загрузкой из файла, убрать учет прозрачности фона и изменить размерности массивов... Учтите также, что при x>1000-80 и y > 1000 - 80 искать битмап бесполезно, потому что он не поместится на большом битмапе - выйдет за рамки...

Код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtDlgs, StdCtrls, ExtCtrls, Math;

type
  TForm1 = class(TForm)
    Button2: TButton;
    Button3: TButton;
    OpenPictureDialog1: TOpenPictureDialog;
    Image1: TImage;
    Edit1: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Timer1: TTimer;
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  pict, element : TBitmap;
  emassiv : array [0..2000,0..2] of integer;
  pmassiv : array [0..749,0..179] of integer;
  len, srez : integer;
  p : TPoint;

implementation

{$R *.dfm}


procedure combat; // эта процедура запускается только в режиме боя, рандомно выбирает удар. Вам не нужна...
var max, min, kick : integer;
label e;
begin
   Form1.Caption := 'Режим боя включен';
   if pict.Canvas.Pixels [443,345]=156 then Form1.Close;
   if pict.Canvas.Pixels [443,345]=38243 then begin
      Form1.Timer1.Interval := StrToInt (Form1.Edit1.Text) * 1000+RandomRange(500,6000);
      SetCursorPos(780,110);
      Sleep (400);
      SetCursorPos(780,115);
      sleep (1000);
      mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
      sleep (400);
      mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
      sleep (400);
      Form1.Caption := 'Восстанавливаемся 30 секунд';
      goto e;
   end;
   if pict.Canvas.Pixels [412,377]=14976811 then begin
      Form1.Caption := 'Наношу удар';
      max := 89;
      min := 60;
      if pict.Canvas.Pixels [433,351]=154 then max := 129;
      if pict.Canvas.Pixels [434,443]=147 then min := 30;
      kick := randomrange(min, max) div 30;
      if kick = 1 then begin
         SetCursorPos(434,443);
         mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
         sleep (50);
         mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
      end;
      if kick = 2 then begin
         SetCursorPos(458,398);
         mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
         sleep (50);
         mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
      end;
      if kick = 3 then begin
         SetCursorPos(433,351);
         mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
         sleep (50);
         mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
      end;
   end;
e: ;
end;

function search (ys : integer) : boolean; // функция ищет битмап на битмапе, и записывает в p координаты монстра (не битмапа, монстр 
//выше искомого битмапа)...
var i, j, ind, dx, dy, k, l, uje : integer;
label yes, ok;
begin
   search := false;
   for i:=249 to 998 do
      for j:= ys to ys+176 do
         pmassiv[i-249,j-ys] := pict.Canvas.Pixels[i,j];
   for i:=0 to 749 - element.Width do
      for j:= 0 to 179 - element.height do begin
         dx := 0;
         dy := 0;
         ind := 0;
yes:     if emassiv[ind,2]=pmassiv[i+dx,j+dy] then begin
            ind := ind+1;
            dx := emassiv[ind,0]-emassiv[0,0];
            dy := emassiv[ind,1]-emassiv[0,1];
            if ind<len then goto yes;
            search := true;
            uje := i + (element.Width div 2);
            p.x := uje + 249;
            p.y := ys + j + srez - 8;
            Form1.Caption:='Объект найден, нападаю';
            goto ok;
          end;
       end;
ok:    ;
end;

procedure hunt (ys : integer); // Это процедура охоты, когда режим боя не включен.
begin
   if search(ys)= true then begin // Если подпись найдена то делаем двойной щелчок мышью в монстра...
      SetCursorPos(p.X,p.Y); 
      mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
      sleep (50);
      mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
      sleep (50);
      mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
      sleep (50);
      mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
   end
   else form1.Caption := 'Цель не найдена, перемещаюсь';
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
   pict := TBitmap.Create;
   element := TBitmap.Create;
   pict.Width := Screen.Width;
   pict.Height := Screen.Height;
end;

procedure TForm1.Button2Click(Sender: TObject); // Здесь кажется выбираем искомую подпись (из картинки в bmp.файле)
var i, j, k : integer;
label yes, no, ready;
begin
   k := 0;
   if openPictureDialog1.Execute = true then begin
      Image1.Picture.LoadFromFile(OpenPictureDialog1.Filename);
      element.LoadFromFile (OpenPictureDialog1.Filename);
      for i := 0 to element.Width - 1 do
         for j := 0 to element.Height - 1 do
            if element.Canvas.Pixels[i,j]<>16777215 then begin
               emassiv[k,0]:=i;
               emassiv[k,1]:=j;
               emassiv[k,2]:= element.Canvas.Pixels[i,j];
               k:=k+1;
            end;
      len := k;
      srez := 0;
      for i := 0 to len - 1 do
        if emassiv[i,1]-emassiv[0,1]<srez then srez := emassiv[0,1] - emassiv[i,1]
   end;
end;

procedure TForm1.Button3Click(Sender: TObject); // Активизация охотника;
begin
   Timer1.Enabled := true;
   Form1.Caption := 'Охочусь';
end;

procedure TForm1.Timer1Timer(Sender: TObject); // Это обработчик таймера. Ищет каждую секунду монстра и нападает
label s, e;
begin
   Timer1.Interval := 1000+RandomRange(200,1000);
   BitBlt(pict.Canvas.Handle, 0,0, Screen.Width, Screen.Height, GetDC(0), 0,0,SRCCOPY);
   if pict.Canvas.Pixels[265,175] <> 11201023 then goto s; // если не режим боя то охотимся
   combat; // а если режим боя, то бьемся,
   goto e; // и обходим режим охоты, потому что у нас не режим охоты а режим боя...
s: hunt (261);
e: SetCursorPos(780,500);
end;

end.

Автор: loginrl103 26.2.2009, 07:42
Есть ещё такой вариант - разбиваем большое изображение на n квадратов, для каждого из них считаем какие-то средние величины (цвета, полутона, что там ещё), тоже заранее проделываем для битмапов, затем каждый квадрат сравниваем по нескольким просчитанным значениям (+/- несколько %) с этими параметрами для битмапов..Хм...что скажите? Конкретные величины и результаты работы с ними хотелось бы услышать).

Автор: Курсант 26.2.2009, 16:49
loginrl103, не прокатит. и с корелляцией тоже имхо не прокатит... Тебе алгоритм поиска нужен, что то вроде алгоритма Кнутта-Морриса-Пратта... Говорю же, выдергивай себе процедуры из того кода который я тебе дал, там похожий по смыслу алгоритм поиска реализован, адаптируй под себя, и используй.. Хочешь - исходные битмапы крути, хочешь - алгоритм оптимизируй...

Автор: GoldFinch 26.2.2009, 17:26
все зависит от того какие картинки, общими методами такие задачи не решаются

Автор: andrew_121 26.2.2009, 18:27
Цитата(GoldFinch @ 26.2.2009,  17:26)
все зависит от того какие картинки, общими методами такие задачи не решаются

солидарен!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)