Форум: "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.044 c