Форум программистов, компьютерный форум, киберфорум
Delphi: Графика, звук, видео
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/18: Рейтинг темы: голосов - 18, средняя оценка - 4.67
57 / 52 / 5
Регистрация: 18.11.2018
Сообщений: 295

Ускорить сравнение TBitmap

30.11.2020, 11:21. Показов 3676. Ответов 6

Студворк — интернет-сервис помощи студентам
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
function CmpBmp(a,b:TBitmap):Extended;
var
  x,y : Integer;
  Bit1,Bit2 : TBitMap;
  P1,P2,o1,o2 : PIntArray;
  Simil:Integer;
 
 SBytes1,SBytes2:  INTEGER;
 
begin
   Simil:=0;
  Bit1 := TBitMap.create;
    Bit1.PixelFormat:=pf32bit;
  Bit1.Height:=32;Bit1.Width:=32;
 
  Bit2 := TBitMap.create;
  Bit2.PixelFormat:=pf32bit;
  Bit2.Height:=32;Bit2.Width:=32;
 
  Bit1.Canvas.StretchDraw(Bit1.Canvas.ClipRect,a);
  Bit2.Canvas.StretchDraw(Bit2.Canvas.ClipRect,b);
 
    //  P1 := Bit1.ScanLine[0];
    //  P2 := Bit2.ScanLine[0];
 // SBytes1 := integer(a.Scanline[1]) - integer(P1);
 // SBytes2 := integer(b.Scanline[1]) - integer(P2);
 
  //  o1:=P1;
 //   o2:=P2;
    for y := 0 to 31 do
    begin
      P1 := Bit1.ScanLine[y];
      P2 := Bit2.ScanLine[y];
      for x := 0 to 31  do
       if P1[x]=P2[x] then inc(Simil);
    end;
    result:=(Simil/1024)*100;
 
    Bit1.Free;
    Bit2.Free;
  end;
Можно ли ускорить такое сравнение например с помощью работы напрямую с указателями?
Или не стоит и пытаться ,так как основное время видимо идёт на StretchDraw...
В примерном количестве будет сравниваться массив 0..63 с шаблонами (6 штук,возможно больше)
расчёты показывают неутешительные 0,134 секунды.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
procedure TForm1.btn3Click(Sender: TObject);
var t1,t2,freq:Int64;   I:Integer; Rezz:Extended;
tmpBit:TBitmap;
begin
QueryPerformanceFrequency(freq);
 
tmpBit:=TBitmap.Create;
 
for i:=0 to 5 do begin
QueryPerformanceCounter(t1) ;
il1.GetBitmap(i,tmpBit);
rezz:=CmpBmp(imgTwo.Picture.Bitmap,tmpBit);
QueryPerformanceCounter(t2) ;
mmo2.Lines.Add(FormatFloat('0.000000',((T2 - T1)/freq))+' S.'+inttostr(i)+' '+FormatFloat('0.0',rezz));
end;
tmpBit.Free;
end;
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
30.11.2020, 11:21
Ответы с готовыми решениями:

Tbitmap.create и Tbitmap.scanline
Если после создания bitmap-а загрузить изображение (loadfromfile()) то изменение пикселей через scanline работает правильно, но если bitmap...

Ускорить сравнение строк
Доброго дня! Я очень долго просто читал, настало время спросить. Задача: есть одн. массив данных типа AnsiString, каждая строка ровно...

Ускорить сравнение двух List<>
Нужно сравнить два листа, если объекта из первого листа нет во втором, то нужно добавить его в третий. Сейчас у меня сделано так: Класс...

6
Модератор
4114 / 2346 / 807
Регистрация: 15.11.2015
Сообщений: 9,326
30.11.2020, 16:14
Цитата Сообщение от Иван Ежик Посмотреть сообщение
расчёты показывают неутешительные 0,134 секунды.
Размер битмапа какой?
С учётом StretchDraw со сглаживанием быстрее вряд ли будет.
0
57 / 52 / 5
Регистрация: 18.11.2018
Сообщений: 295
30.11.2020, 21:07  [ТС]
Размер 32х32,в коде видно
Сравнений будет 64*6(возможно больше чем 6) и это будет по времени 0,13-0,14 сек...
Слишком долго,мой весь остальной код по бинаризации,сегментации,определению размера образов и их положения для последующей обработки занимает 0,08 сек(800х600х32бит)(это ещё рамки рисуются ,вычисляется площадь и центр масс для каждого объекта,его ориентация и всё это выводится на Канвас для отладки).
Цитата Сообщение от AzAtom Посмотреть сообщение
С учётом StretchDraw со сглаживанием быстрее вряд ли будет
С выключенным сглаживанием ещё дольше чем StretchDraw...
Пробовал вот такой костылик
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
function ScaleBitmap(var Source, Dest: TBitmap; OutWidth, OutHeight: integer):Extended;
var
  src, dst: TGPBitmap;
  g: TGPGraphics;
  h: HBITMAP;
 iCounterPerSec: int64;
 T1, T2: int64; //значение счётчика ДО и ПОСЛЕ операции
 Quality:Integer;
begin
 
    QueryPerformanceFrequency(iCounterPerSec);//определили частоту счётчика
  QueryPerformanceCounter(T1); //засекли время начала операции
  src := TGPBitmap.Create(Source.Handle, 0);
  try
    dst := TGPBitmap.Create(OutWidth, OutHeight);
    // dst.LockBits()
    try
      g := TGPGraphics.Create(dst);
      try
        g.SetInterpolationMode(1); //-1..7
        g.SetPixelOffsetMode(3);   //-1..4
        g.SetSmoothingMode(3);     //-1..4
        
        g.DrawImage(src, 0, 0, dst.GetWidth, dst.GetHeight);
 
{    InterpolationModeInvalid             = QualityModeInvalid;
    InterpolationModeDefault             = QualityModeDefault;
    InterpolationModeLowQuality          = QualityModeLow;
    InterpolationModeHighQuality         = QualityModeHigh;
    InterpolationModeBilinear            = 3;
    InterpolationModeBicubic             = 4;
    InterpolationModeNearestNeighbor     = 5;
    InterpolationModeHighQualityBilinear = 6;
    InterpolationModeHighQualityBicubic  = 7;
    //////////////////////////////////////////////////////
        PixelOffsetModeInvalid     = QualityModeInvalid;
    PixelOffsetModeDefault     = QualityModeDefault;
    PixelOffsetModeHighSpeed   = QualityModeLow;
    PixelOffsetModeHighQuality = QualityModeHigh;
    PixelOffsetModeNone        = 3;    // No pixel offset
    PixelOffsetModeHalf        = 4;    // Offset by -0.5, -0.5 for fast anti-alias perf
    ////////////////////////////////////////////////////////
        SmoothingModeInvalid     = QualityModeInvalid;
    SmoothingModeDefault     = QualityModeDefault;
    SmoothingModeHighSpeed   = QualityModeLow;
    SmoothingModeHighQuality = QualityModeHigh;
    SmoothingModeNone        = 3;
    SmoothingModeAntiAlias   = 4;}
      finally
        g.Free;
      end;
      dst.GetHBITMAP(0, h);
      Dest.Handle := h;
    finally
      dst.Free;
    end;
  finally
    src.Free;
  end;
    QueryPerformanceCounter(T2);
    result:= (T2 - T1) / iCounterPerSec;
end;
С ним в ДВА раза дольше.
Но вообще немного ускорил...Шаблоны итак уже 32х32 ,их не нужно ресайзить.Сэкономил 50-70 микросекунд(одно сравнение стало 0,00025,а было 0,00032).
Сами изображения для уменьшения площадью 250-1000 пикселей,без учёта чёрной области
0
Модератор
4114 / 2346 / 807
Регистрация: 15.11.2015
Сообщений: 9,326
01.12.2020, 10:59
Цитата Сообщение от Иван Ежик Посмотреть сообщение
P1 := Bit1.ScanLine[y];
P2 := Bit2.ScanLine[y];
for x := 0 to 31 do
if P1[x]=P2[x] then inc(Simil);
Цитата Сообщение от Иван Ежик Посмотреть сообщение
Можно ли ускорить такое сравнение например с помощью работы напрямую с указателями?
Так вот же, итак через указатели работа.

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

Для оптимизации нужно заранее приготовить картинки для сравнения нужного размера и с нужной глубиной цвета, тогда останется только одну картинку уменьшить. 32х32 это не много, должно быстро работать.
0
57 / 52 / 5
Регистрация: 18.11.2018
Сообщений: 295
01.12.2020, 11:45  [ТС]
Цитата Сообщение от AzAtom Посмотреть сообщение
Так вот же, итак через указатели работа.
Ну это всё же не те указатели,почти,но не те.
Вот сравнение сделал
1)Сканлайн вызывается для каждой строки. Работа через TrgbQuad
2)Сканлайн вызывается дважды вначале процедуры.Работа через TrgbQuad
3)Работа с указателями без типизиции.Два вложенных цикла...

Размер BMP 1600x900
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/////////////////
begin
       Bitmap := TBitmap.Create;
 
      Bitmap.PixelFormat := pf32bit;
      Bitmap.Width  := WH.Width;
      Bitmap.Height := WH.Height;
      row := Bitmap.Scanline[0];
 
      ScanlineBytes := integer(Bitmap.Scanline[1]) - integer(row);
 
  LoopCount := Form1.SpinEditTimes.Value;
  StartTime := GetTickCount;
  FOR k := 1 TO LoopCount DO
  BEGIN
    row2:=row;
    FOR j := 0 TO Bitmap.Height-1 DO
    BEGIN
      FOR i := 0 TO Bitmap.Width-1 DO
      BEGIN
 
        row2[i]:=((j mod 256) + ((i mod 256) shl 8)+ (k shl 16){ or (k shl 24)});
 
      END;
     INC(Integer(Row2), ScanlineBytes);
    END;
    form1.  img3.Picture.Graphic := Bitmap;
 
   END;
//////////////////////
Возможно сделать ещё быстрее на 10% если использовать один цикл до Width*Height
Цитата Сообщение от AzAtom Посмотреть сообщение
Только тут каждый раз создаются битмапы и производится растягивание. Напрямую сравнить такое вряд ли получится. Нужно вводить некий порог, и ещё нужно сравнивать компоненты цвета по отдельности.
Время ещё тратится на доставание из ImageList,шаблоны можно в памяти держать, по HBitmap к ним обращаться...
Попробую кроме этого сделать 1 битмап для сравнения с шаблонами, и по очереди Блиттить(stretchblt ) на него исседуемые объекты.
Компоненты цвета не нужны,и по порогу уже сделано,я работаю уже с бинаризованным видом,красный просто выбрал как Единицу,чёрный как Ноль.До обработки они были цветными.
0
57 / 52 / 5
Регистрация: 18.11.2018
Сообщений: 295
01.12.2020, 12:46  [ТС]
Цитата Сообщение от AzAtom Посмотреть сообщение
Для оптимизации нужно заранее приготовить картинки для сравнения нужного размера и с нужной глубиной цвета, тогда останется только одну картинку уменьшить. 32х32 это не много, должно быстро работать.
Ну одну уменьшить не получится,их 64 на экране в момент времени...
И каждую найденную нужно будет уменьшить для сравнения с шаблонами, чтобы определить к какому классу отнести.
4 кадра в секунду пока получается, медленно.Надо будет потом, как на низком уровне разгребу,попробовать на 2 потока разделить.
Цитата Сообщение от Иван Ежик Посмотреть сообщение
Работа с указателями без типизиции
Наврал, указатель типизирован(pIntArray)
0
57 / 52 / 5
Регистрация: 18.11.2018
Сообщений: 295
04.12.2020, 11:36  [ТС]
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
 function MasCmpBmp(a:TBitmap;var mas:TArOB):TRres;
var
  x,WH,i : Integer;
  Bit1,Bit2 : TBitMap;
  P1,P2,Pin: PInt;
  o1,o2 :PInt;
  Simil:Integer;
  PreRes:Double;
begin
Result.Val:=0.0;
Result.Num:=-1;
  Bit1 := TBitMap.create;
  Bit1.PixelFormat:=pf32bit;
  Bit1.Height:=Mas[0].Height;Bit1.Width:=Mas[0].Width;
  Bit1.Canvas.StretchDraw(Bit1.Canvas.ClipRect,a);
  WH:=Mas[0].Height*Mas[0].Width-1;
      o1 := Bit1.ScanLine[Bit1.height-1];
      P1:= Bit1.ScanLine[0];
      if cardinal(o1)>cardinal(P1) then o1:=P1;
    //  form1.mmo1.Lines.Add('Mas:'+IntToStr(Length(mas)));
   for i:=Low(MAs) to High(mas) do
   begin
      Pin:=o1;
      mas[i].PixelFormat:=pf32bit;
      Simil:=0;
      PreRes:=0.0;
      o2 := Mas[i].ScanLine[Mas[i].height-1];
      P2:= Mas[i].ScanLine[i];
      if cardinal(o2)>cardinal(P2) then o2:=P2;
 
     for x := WH downto 0 do
     begin
     // form1.mmo1.Lines.Add('X:'+IntToStr(x));
     //  form1.mmo1.Lines.Add('O1:'+Format('$%x',[ Integer(o1) ]));
        if Pin^=o2^ then inc(Simil) ;
        inc(Pin,1);
        inc(o2,1);
     end;
     PreRes:=(Simil/(WH+1))*100;
     if PreRes>Result.Val then
     begin
       Result.Val:=PreRes;
       Result.Num:=i;
     end;  
    end;
    //  form1.Img6.Canvas.StretchDraw(form1.Img6.Canvas.ClipRect,Bit2);
    Bit1.Free;
  end;
Ну вот собственно и пока всё...
Примерная скорость 5420 вызовов в секунду, около 12 раз ускорение от изначального.
В массиве 6 шаблонов,сравнение (вызов процедуры) 64 раза занимает 11,85-12 ms.
С этим можно уже работать.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
04.12.2020, 11:36
Помогаю со студенческими работами здесь

Как ускорить выполнение кода? (Получение цвета пикселя, сравнение и выполнение действия)
Всем привет. Нужна консультация экспертов) Программа такая. Есть пиксель на экране, в нем то появляется яркий цвет, то темный (лампочка...

TBitMap
Как можно двигать по форме объект TBitMap? я хотел по циклу или по таймеру передвигать его горизонтально с помощью Left. Но у него...

TBitMap
Делаю консольное приложение program Project; {$APPTYPE CONSOLE} uses SysUtils, Jpeg, Registry, Graphics, Windows,...

TBitmap 8 bit
интересует каким образом хранить в памяти изображения TBitmap разрядностью в 8 бит на пиксель? ибо 32 бит или 24, точно не знаю...

TBitmap->TMemoryStream
Здравствуйте, участники форума! Я пишу программку, которая делает скрин экрана и передает поток Bitmap'а через TIdTCPServer и...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru