Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Media";
Текущий архив: 2004.05.16;
Скачать: [xml.tar.bz2];

Вниз

как быстро сравнить 2 объекта типа tbitmap   Найти похожие ветки 

 
truntaev   (2003-11-21 10:19) [0]

Мастера, буду весьма признателен за помощь в следующем вопросе.
Как можно сравнить два объекта типа Tbitmap. Сравнение только
на предмет - идентичны ли два рисунка.
Собственно вся проблема сделать это быстро.
Использование ScanLine,  а затем поэлементное сравнение массивов
работает весьма медленно. Может кто-то умеет это делать с
помощью GDI функций...
На всякий случай: ntruntaev@hotbox.ru


 
MBo ©   (2003-11-21 13:32) [1]

Какая необходима скорость?


 
Карелин Артем ©   (2003-11-21 15:52) [2]

g32.org работает ну очень быстро с графикой.


 
miek ©   (2003-11-21 16:45) [3]

Никак. Быстро только кошки родятся, а распознавание образов не фунт изюма.


 
Mihey ©   (2003-11-21 19:50) [4]

>Быстро только кошки родятся, а распознавание образов не фунт изюма.

Зря наругал человека. Он же ясно пишет:

>Сравнение только на предмет - идентичны ли два рисунка.


 
miek ©   (2003-11-21 20:33) [5]

Извиняюсь, если что. Но идентичность понятие тоже ОЧЕНЬ растяжимое. Может быть два битмапа, в которых ни один байт не совпадет, а на вид будут идентичны. Догадались, как, или пример привести? Задача решается только примеами распознавания образов. Кто сумеет сделать быстро и качественно - пускай идет давать зайвку на нобелевку.


 
Mihey ©   (2003-11-21 20:43) [6]

>Догадались, как, или пример привести?

Как? Имеешь ввиду сделать цвет на единичное значение отличающимся?


 
wicked ©   (2003-11-21 21:13) [7]

навскидку, т. е. могуть быть неправильными или недостаточно быстрыми:
1. проксорить с помощью BitBlt, подсчитать количество 0 пикселей...
2. ScanLine + REP CMPSD...


 
Думкин ©   (2003-11-22 05:41) [8]


> [5] miek ©   (21.11.03 20:33)

Этой фразой сказано все:

> Использование ScanLine,  а затем поэлементное сравнение
> массивов работает весьма медленно.

Ни о каких образах речь не идет.
Можно посмотреть:
http://www.delphimaster.ru/articles/pixels/index.html
и ответить на вопрос МВо - он по ускоренной работе с графикой - дока.


 
miek ©   (2003-11-22 11:11) [9]

M> Как? Имеешь ввиду сделать цвет на единичное значение отличающимся?

Именно. А еще есть такая штука, как палитра.

Еще раз говорю - сравнивать два изображения, о содержании которых заранее ничего не известно - это задача для суперкомпов. Если известно, тогда, впрочем, другое дело. Сравнил размеры, потом пару пикселей из заранее заданных ключевых точек и все.


 
Думкин ©   (2003-11-22 11:17) [10]

> [9] miek ©   (22.11.03 11:11)
Ты вопрос почитай и остальное. Ты как глухой на дискотеке.
Тебе про Фому, а ты все про Ерему. Какие образы?


 
Fenik ©   (2003-11-22 12:07) [11]

function BitmapOfBitmap(B1, B2: TBitmap): Boolean;
var x, y, n: Integer;
   p1, p2: pByteArray;
begin
 Result := False;
 if (B1.Width <> B2.Width) or (B1.Height <> B2.Height) then Exit;
 B1.PixelFormat := pf24Bit;
 B2.PixelFormat := pf24Bit;
 for y := 0 to B1.Height - 1 do begin
   p1 := B1.ScanLine[y];
   p2 := B2.ScanLine[y];
   for x := 0 to B1.Width - 1 do begin
     n := x*3;
     if (p1[n]<>p2[n]) or (p1[n+1]<>p2[n+1]) or (p1[n+2]<>p2[n+2]) then Exit;
   end;
 end;
 Result := True;
end;


True, если растры абсолютно одинаковые,
False - если отличаются хоть на один пиксель.


 
Dima1   (2003-11-22 13:16) [12]

Это не мое, когдато уже встречалось в форуме.
Может поможет
---------

набросок для 24-битных картинок (для других форматов еще проще),
результат от 0 до 1 при полном совпадении

function CompareBmp24(bmp1, bmp2: TBitmap): Double;
var
i, j, Sum: Integer;
SLine1, SLine2: PByteArray;
begin
Assert((bmp1.PixelFormat = pf24bit) and (bmp2.PixelFormat = pf24bit),
  "24bit only!");
Assert((bmp1.Width <> 0) and (bmp1.Height <> 0), "Empty bitmap!");
if (bmp1.Height <> bmp2.Height) or (bmp1.Width <> bmp2.Width) then
begin
  Result := 0;
  Exit;
end;
Sum := 0;
for i := 0 to bmp1.Height - 1 do
begin
  SLine1 := bmp1.ScanLine[i];
  SLine2 := bmp2.ScanLine[i];
  for j := 0 to bmp1.Width - 1 do
    if (PInteger(@SLine1[j * 3])^ and $FFFFFF00) =
      (PInteger(@SLine2[j * 3])^ and $FFFFFF00) then
        inc(Sum);
end;
Result := Sum / (bmp1.Width * bmp1.Height);
end;


 
Думкин ©   (2003-11-22 13:44) [13]


> [11] Fenik ©   (22.11.03 12:07)

Читаем:

> Собственно вся проблема сделать это быстро.
> Использование ScanLine,  а затем поэлементное сравнение
> массивов работает весьма медленно.


 
Fenik ©   (2003-11-22 15:52) [14]

>Думкин ©  (22.11.03 13:44) [13]

Тогда можно эту усовершенствовать. Сверяем строки снизу и сверху одновременно, сходясь к середине.
Т.о. вероятност обнаружить разницу больше, и разные картинки отсеиваются быстро.

function BOB2(B1, B2: TBitmap): Boolean;
var x, y, n, h, hend: Integer;
   p1, p2, p3, p4: pByteArray;
begin
 Result := False;
 if (B1.Width <> B2.Width) or (B1.Height <> B2.Height) then Exit;
 B1.PixelFormat := pf24Bit;
 B2.PixelFormat := pf24Bit;
 h := B1.Height;
 hend := h div 2 + h mod 2;
 Dec(h);
 for y := 0 to hend do begin
   p1 := B1.ScanLine[y];
   p2 := B2.ScanLine[y];
   p3 := B1.ScanLine[h - y];
   p4 := B2.ScanLine[h - y];
   for x := 0 to B1.Width - 1 do begin
     n := x*3;
     if (p1[n]<>p2[n]) or (p1[n+1]<>p2[n+1]) or (p1[n+2]<>p2[n+2]) or
        (p3[n]<>p4[n]) or (p3[n+1]<>p4[n+1]) or (p3[n+2]<>p4[n+2]) then Exit;
   end;
 end;
 Result := True;
end;


Кстати, если это поисковик иконок, который отсеивает одинаковые, то можно сортировать иконки, например, по цвету цетрального пикселя, и сверять уже только соответствующие экземпляры. Думаю, идея понятна.


 
Fenik ©   (2003-11-22 15:56) [15]

>Думкин ©  (22.11.03 13:44) [13]

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


 
miek ©   (2003-11-22 17:56) [16]

Думкин, не переходи на личности.

И вообще, вы все свихнулись на сканлиниях, что ли? Типа круто?

---------
M> Как? Имеешь ввиду сделать цвет на единичное значение отличающимся?

Именно. А еще есть такая штука, как палитра.

Еще раз говорю - сравнивать два изображения, о содержании которых заранее ничего не известно - это задача для суперкомпов. Если известно, тогда, впрочем, другое дело. Сравнил размеры, потом пару пикселей из заранее заданных ключевых точек и все.


 
truntaev   (2003-11-22 18:47) [17]

Мужики, благодарю за внимание к вопросу и помощь.
К сожалению все три примера построены на работе пресловутой
ScanLine. Попробуйте просто отработать с двумя битмапами
800х600. Это секунды 2-3 на 1Гц процессоре. Медленно это...
Хотя бы 300 Мс получить.


 
Думкин ©   (2003-11-22 19:28) [18]


> [16] miek ©   (22.11.03 17:56)
> Думкин, не переходи на личности.

А я имею дело не с личностью? Извини. Кстати и не переходил - простот - вопрос почитай и подумамй. Без обид.
Человек конкретно спросил - не мути воду в Байкале.


> [17] truntaev   (22.11.03 18:47)
> К сожалению все три примера построены на работе пресловутой ScanLine.

Эти примеры - да. Но статью глянь - там несколько иначе. Почитай - не пожалеешь.


 
MBo ©   (2003-11-23 08:01) [19]

>Попробуйте просто отработать с двумя битмапами
800х600. Это секунды 2-3 на 1Гц процессоре. Медленно это

Так я и подозревал...
Дело не в ScanLine, а в твоем коде - на гигагерцовой машине скорость со Scanline будет при правильном подходе в десятки-сто раз больше.


 
miek ©   (2003-11-23 09:49) [20]

Если сравнение одно, то да, а вот когда ему надо их десятками сравнивать, то где-то так и должно быть.


 
truntaev   (2003-11-23 10:44) [21]

Я прочитал, что MBo - дока в вопросах графики. Поэтому
вопрос конкретный. Что можно улучшить (ускорить) в этом
коде???
   for y := 0 to BMp.Height -1 do
   begin
     P := BMp.ScanLine[y];
   end;

Если bmp.Width=800, а BMp.Height=600 этот код и работает
пару секунд.

А вообще приятно и любопытно почитать высказывания умных
людей по этому вопросу. Спасибо.
Думкину > Пойду почитаю предложенную статью. Я сначала ссылку
пропустил - теперь время.


 
MBo ©   (2003-11-23 12:13) [22]

>Если bmp.Width=800, а BMp.Height=600 этот код и работает
пару секунд.

Чудеса рассказываешь...

Вот набросок сравнения:

Equal:=true;
w:=bmp.width*ByesPerPoint;
for y := 0 to BMp.Height -1 do
  begin
    P1:= BMp.ScanLine[y];
    P2:= BMp2.ScanLine[y];
    if not CompareMem(p1,p2,w) then begin
      Equal:=False;
      Break;
    end;
  end;


 
Думкин ©   (2003-11-23 15:02) [23]


> [21] truntaev   (23.11.03 10:44)

МВо и является одним из авторов той статьи.


 
truntaev   (2003-11-23 20:09) [24]

Уважаемый, MBo, и все кто может объяснить не специалисту по графике!
к сожалению красивое сравнение не работает :
   if not CompareMem(p1,p2,w) then begin
     Equal:=False;
а может от того, что я просто не знаю, что такое ByesPerPoint?
Буду признателен за объяснение, но это не совсем проблема.
Может я просто морочу голову мастерам, но проблема в следующем:

bmp1:=TBitmap.Create;
{bmp1.Height:=600;
bmp1.Width:=800;
}
Bmp1.LoadFromFile("wallp.bmp"); // файл какой-то картинки на р.стол
for y := 0 to BMp1.Height -1 do
 begin
   P1:= BMp1.ScanLine[y];
 end;
Действительно шустренько работает.
После этого и следующий код работает быстро:

DC:=GetDC(0);
bitblt(bmp1.Canvas.Handle, 0, 0, 800, 600,DC, 0, 0, SRCCOPY);
for y := 0 to Bmp1.Height -1 do
 begin
   P1:= Bmp1.ScanLine[y];
 end;

Однако, если я пишу просто такой код, он тормозит со страшной силой:
Procedure proba;
Begin
 bmp1:=TBitmap.Create;
 bmp1.Height:=600;
 bmp1.Width:=800;
 DC:=GetDC(0);
 bitblt(bmp1.Canvas.Handle, 0, 0, 800, 600,DC, 0, 0, SRCCOPY);
 for y := 0 to Bmp1.Height -1 do
 begin
   P1:= Bmp1.ScanLine[y];
 end;
End
В чем тут дело?


 
Mihey ©   (2003-11-23 23:15) [25]

Юзай Graphic32, и всё будет нормально.


 
MBo ©   (2003-11-24 08:55) [26]

Не первый раз пишешь это чудо:
begin
  P1:= Bmp1.ScanLine[y];
end;
может, какой тайный смысл в этом есть?

формат битмапов такой же, как у экрана.
7 миллисекунд на один прогон по битмапам на AXP1900+
если внести в цикл и получение снимка экрана (раскомментировать A, закомм. B) - 53 миллисек. Так что драйвер hands.sys, видимо, глючит.


procedure TForm1.Button1Click(Sender: TObject);
var b1,b2:TBitmap;
   x,y,k:Integer;
   w:Integer;
   Equal:Integer;
   dc:HDC;
   t:Cardinal;
   p1,p2:Pointer;
begin
b1:=TBitmap.Create;
b2:=TBitmap.Create;
b1.Width:=1024;
b1.Height:=768;
b1.PixelFormat:=pf32bit;
//A
//t:=GetTickCount;
//for k:=1 to 100 do begin
 DC:=GetDC(0);
 BitBlt(b1.Canvas.Handle,0,0,1024,768,dc,0,0,srccopy);
 ReleaseDC(0,DC);
 b2.Assign(b1);
 Equal:=1;
 w:=b1.width*4;

//B
t:=GetTickCount;
for k:=1 to 100 do begin

 for y := 0 to B1.Height -1 do  begin
   P1:= B1.ScanLine[y];
   P2:= B2.ScanLine[y];
   if not CompareMem(p1,p2,w) then begin
     Equal:=0;
     Break;
   end;
 end;
end;
Caption:=Format("Одинаковы: %d Время: %d",[Equal,(GetTickCount-t) div 100]);
end;



 
Карелин Артем ©   (2003-11-24 10:01) [27]

При использовани компонентов, указанных выше мной можно получить попиксельную отрисовку кучи битмапов на подложке 720*576 с эффектами прозрачности, вычисляющимися тут же (мой алгоритм, основанный на попиксельном доступе к битмапу) и записью этого в авишник(поддержка этого не входит в тот набор) со скоростью 5 кадров в секунду на 900 целероне.


 
bolegator ©   (2004-02-27 08:20) [28]

> Что можно улучшить (ускорить) в этом коде???
>    for y := 0 to BMp.Height -1 do
>    begin
>      P := BMp.ScanLine[y];
>    end;

dx:=BMp.ScanLine[0]-BMp.ScanLine[1]; // dx>0
   for y := 0 to BMp.Height -1 do
   begin
     inc(integer(P),dx)
   end;



Страницы: 1 вся ветка

Форум: "Media";
Текущий архив: 2004.05.16;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.53 MB
Время: 0.033 c
9-1072442625
MoGiLsHiKK
2003-12-26 15:43
2004.05.16
Первая игра???


4-1080544622
Akvilon
2004-03-29 11:17
2004.05.16
окно выбора папки


1-1083105428
Mishenka
2004-04-28 02:37
2004.05.16
Выделение в ListBox


11-1069230587
mi4g
2003-11-19 11:29
2004.05.16
KOLIndy


7-1081159262
Azazzello
2004-04-05 14:01
2004.05.16
Как узнать работает определенная программа или нет





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский