Модераторы: Snowy, Alexeis, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Сравнение изображений, не все так просто и обычно 
:(
    Опции темы
xaOz
Дата 19.9.2005, 13:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 19.9.2005

Репутация: нет
Всего: нет



Ситуация такая - есть скриншот экрана (Картинка1), и маленькая картинка например 20 на 20 пикс (Картинка2), как можно быстро определить, что на Картинке1 есть Картинка2?
PM MAIL   Вверх
Snowy
Дата 19.9.2005, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 18
Всего: 484



Уменьшить и сравнить попиксельно.
Если уменьшение проводилось по тому же алгоритму, то совпадет.
Если нет, то нужно проверять с учетом допустимой погрешности (экскриментальным путем).
PM MAIL   Вверх
xaOz
Дата 19.9.2005, 14:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 19.9.2005

Репутация: нет
Всего: нет



Имелось ввиду найти на Картинке1 - Картинку 2, где Картинка 2 может быть элементом Картинки 1




PM MAIL   Вверх
Snowy
Дата 20.9.2005, 11:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 18
Всего: 484



Быстро никак. Только перебором.
Естественно, если прерывать перебор при первом несовпадении, то будет не так медленно.
Ускорить можно диагональным сравнением.
Но это все с учетом, что скриншот и картинка не испорчены джпегом.

PM MAIL   Вверх
xaOz
Дата 20.9.2005, 12:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 19.9.2005

Репутация: нет
Всего: нет



Вот наваял, не подскажете как ускорить можно?

Код

function CompareImages(A, B : TBitmap): Boolean;
var
  i, j : integer;
  p1, p2 : PARGB;
begin
  Result:=False;

  for i := 0 to A.Height - 1 do begin
    p1 := A.ScanLine[i];
    p2 := B.ScanLine[i];
    for j := 0 to A.Width - 1 do begin
      if not ((p1[j].r = p2[j].r) and (p1[j].g = p2[j].g) and (p1[j].b = p2[j].b)) then exit;
    end;
  end;

  Result := True;
end;

function SearchImage(A, B : TBitmap): Boolean;
var
  x, y: Integer;
  Rect1, Rect2: TRect;
  C: TBitmap;
begin
  Result := True;

  try
    C :=  TBitmap.Create;
    C.Assign(B);

    Rect1.Left := 0;
    Rect1.Top := 0;
    Rect1.Right := B.Width - 1;
    Rect1.Bottom := B.Height - 1;

    for y := 0 to A.Height - B.Height do
      for x := 0 to A.Width - B.Width do begin

         Rect2.Left := x;
         Rect2.Top := y;
         Rect2.Right := B.Width - 1 + x;
         Rect2.Bottom := B.Height - 1 + y;

         C.Canvas.CopyRect(Rect1, A.Canvas, Rect2);

         if CompareImages(B, C) then Exit;
      end;

    Result := False;

  finally
    C.Free;
  end;
end;


PM MAIL   Вверх
Snowy
Дата 20.9.2005, 13:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 18
Всего: 484



1. Создать два array[0..x,0..y] or dword; Прописать в них 4-байтные цвета каждой картинки. Обращение к массивам будет быстрее и можно будет сразу сравнивать цвета целиком, а не по составляющим.
2. Если речь идет и скриншотах, то быстрое отсеивание можно реализовать при сканировании главной диагонали, т.к. окна располагаются прямоугольно, то повторение вертикальных и горизонтальных пикселей происходит довольно часто, а вот диагональных нет. Если уж диагональ полностью совпала, то только тогда проводить полное сравнение.
3. Все написать в одной процедуре. Тогда не потребуется подготавливать данные для процедуры сравнения - сразу брать смещение по циклу.
PM MAIL   Вверх
xaOz
Дата 20.9.2005, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 19.9.2005

Репутация: нет
Всего: нет



Цитата
1. Создать два array[0..x,0..y] or dword; Прописать в них 4-байтные цвета каждой картинки. Обращение к массивам будет быстрее и можно будет сразу сравнивать цвета целиком, а не по составляющим.
2. Если речь идет и скриншотах, то быстрое отсеивание можно реализовать при сканировании главной диагонали, т.к. окна располагаются прямоугольно, то повторение вертикальных и горизонтальных пикселей происходит довольно часто, а вот диагональных нет. Если уж диагональ полностью совпала, то только тогда проводить полное сравнение.
3. Все написать в одной процедуре. Тогда не потребуется подготавливать данные для процедуры сравнения - сразу брать смещение по циклу.


Насчет одной процедуры что то никак дойти не могу как это сделать в одной smile ScanLine эти мозги уже поломал думая как объеденить
PM MAIL   Вверх
Snowy
Дата 20.9.2005, 15:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 18
Всего: 484



Для начала создай два массива, чтобы использовать их, а не сканлайны.
А объеденить просто - все, что у тебя написано внутри функции, запихни внутрь бегина.
Заведи флаг выхода. Вместо Exit, используй break. Замени третий for на while.
PM MAIL   Вверх
xaOz
Дата 21.9.2005, 08:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 19.9.2005

Репутация: нет
Всего: нет



После долгих мучений и напряжения серого вещества у меня получилась довольно быстрая фунция, при размере Картинки 1 - 1024 758, а в второй - 100 20, скорость меньше 1 сек:

Код

function SearchImage(A, B : TBitmap): Boolean;
var
  i, j, x, y: integer;
  p1, p2: PARGB;
  Stop: Bool;
begin
  Result := True;

  for y := 0 to A.Height - B.Height do
    for x := 0 to A.Width - B.Width do begin
      Stop := False;

      for i := 0 to B.Height - 1 do begin
        p1 := A.ScanLine[i + y];
        p2 := B.ScanLine[i];
        for j := 0 to B.Width - 1 do
          if not ((p1[j + x].r = p2[j].r) and (p1[j + x].g = p2[j].g) and (p1[j + x].b = p2[j].b)) then begin
            Stop := True;
            Break;
          end;
        if Stop then Break;
      end;

      if not Stop then Exit;
  end;

  Result := False;
end;


PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Звук, графика и видео"
Girder
Snowy
Alexeis

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делится вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • По вопросам разработки игр стоит заглянуть сюда

FAQ раздела лежит здесь!


Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Girder, Snowy.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Звук, графика и видео | Следующая тема »


 




[ Время генерации скрипта: 0.4568 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.