Конференция "Media" » Быстрое сравнение двух рисунков [D7, WinXP]
 
  • EPaul (20.09.10 10:33) [0]
    Есть ли какой нибудь метод быстрого сравнения двух рисунков, типа if bitmap1 = bitmap2 then Попиксельный метод сравнения 2 bitmap не подходит, очень медленно, да и систему нагружает сильно. Заранее спасибо за ответы
  • CrytoGen (20.09.10 10:39) [1]
    Быстрее попиксельного на вряд ли что то найдётся, может вы его готовить не умеете?
  • DVM © (20.09.10 14:36) [2]

    > Попиксельный метод сравнения 2 bitmap не подходит, очень
    > медленно

    думаю до 500fps для 800x600x24b на среднем процессоре выжать можно легко - это медленно?
  • EPaul (20.09.10 20:49) [3]
    Дроблю экран разрешением 1680х1050 на кусочки 50х50 пикселей получается 714 кусочков. Делаю снимок на старте проги в PredBMP и с определенной периодичностью снимаю экран в CurrBMP. Сравниваю между собой 714 кусочков из PredBMP и CurrBMP с одинаковыми координатами, если не совпадают сохраняю порядковый номер кусочка в StringList и сам измененный рисунов в ResulBMP размером Height=50 и Width= количество измененных кусочков * 50. Сравниваю попиксельно отдельной процедурой. Если есть разница, вылетает из процедуры сравнения и переходит к сравнению следующих 2 аналогичных рисунков. Если экран изменился очень мало, то естественно проверяет все пиксели во всех 714 кусочках. Если опрашивать 10 в секунду, то процессор нагружается до 50%. Это много.
  • antonn © (20.09.10 22:58) [4]
    каким образом пиксели "обходятся"?
  • EPaul (20.09.10 23:10) [5]
    procedure Make;
     var j, y, x :integer;
         c1, c2: PByte;
         MyRect: TRect;
    begin
       for y := 0 to cmPredBufBMP.Height - 1 do begin
          c1 := cmPredBufBMP.Scanline[y];
          c2 := cmCurrBufBMP.Scanline[y];
          for x := 0 to cmPredBufBMP.Width - 1 do begin
            for j := 0 to BytesPerPixel - 1 do begin
              If (c1^<>c2^) then begin
                List.Add(IntToStr(i));
                //-- Определяю координаты в ректе, куда вставлять выбранный блок и вставляю в конец .

                SetRect(MyRect, lCounter*LenghtBlok, 0, lCounter*LenghtBlok+cmCurrBufBMP.Width, cmCurrBufBMP.Height);

                cmLongBufBMP.Canvas.StretchDraw(MyRect, cmCurrBufBMP);
                Inc(lCounter);
                Exit;
              end;
              Inc(c1);
              Inc(c2);
            end;
          end;
       end;
    end;
  • DVM © (21.09.10 00:48) [6]

    > EPaul   (20.09.10 23:10) [5]

    Не, так не пойдет, неправильно так.

    Тебе надо просто сказать идентичны(или наоборот не иденичны, что даже лучше) битмапы или нужно знать какие именно пикселы отличаются?
  • DVM © (21.09.10 00:50) [7]

    > EPaul

    Случайно не детектор движения делаешь?
  • antonn © (21.09.10 01:51) [8]
  • Eraser © (21.09.10 01:54) [9]
    потомство Ивана Кулибина )
  • EPaul (21.09.10 07:17) [10]
    DVM
    Каким образом узнать идентичны или нет. Именно это и нужно.
    так тоже пробовал
       izm:=false;
       ScreenStream1.Clear;
       ScreenStream2.Clear;
       cmPredBufBMP.SaveToStream(ScreenStream1);
       cmCurrBufBMP.SaveToStream(ScreenStream2);
       if ScreenStream1.Size<>ScreenStream2.Size then izm:=true
       else if not CompareMem(ScreenStream1, ScreenStream2, ScreenStream1.Size) then  izm:=true;

    что-то такое делает http://forum.vingrad.ru/forum/topic-310393/anchor-entry/0.html#entry   это тоже я. Ищу помощи где только возможно.
  • brother © (21.09.10 07:37) [11]
    на RAdmin алгоритм похоже...
  • EPaul (21.09.10 07:57) [12]
    brother  Угадали.  Осваиваю Delphi  изобретая велосипед. Помогите внуку Ивана Кулибина
  • DVM © (21.09.10 16:09) [13]

    > EPaul   (21.09.10 07:17) [10]


    > Каким образом узнать идентичны или нет. Именно это и нужно.


    Это не одно и то же что


    > brother  Угадали.  Осваиваю Delphi  изобретая велосипед.

    В программе RADMIN нужно не столько знать что изображение изменилось, а сколько ГДЕ ИЗМЕНИЛОСЬ. Это не одно и то же.
  • EPaul (21.09.10 20:26) [14]
    Так ведь я так и делаю, делю экран на N-ое количество фрагментов, сравниваю между собой фрагменты экрана, с какой-то периодичностью, и собираю все измененные фрагменты в один длинный bitmap, плюс порядковые номера измененных фрагментов в stringlist. На другой стороне, по порядковому номеру вычисляются координаты фрагментов и прорисовываются на экране. Все работает, но только очень грузит процессор. Даже если экран почти не меняется, пересылается очень мало измененных фрагментов, нагрузка на сеть нулевая, а процессор грузится прилично, сравниваются всегда все пиксели экрана 1680х1050х3 . Вот и ищу другой способ сравнения, без перебора пикселей, более быстрый.
  • Дрон (22.09.10 13:23) [15]
  • EPaul (23.09.10 12:46) [16]
    Дрон  Как раз эта ссылка не работает!!!
  • Плохиш © (23.09.10 23:53) [17]

    > Если опрашивать 10 в секунду

    Зачем опрашивать 10 раз в секунду? Всё-равно цепочка послать-сеть-принять-нарисовать не даст этой скорости.

    > Как раз эта ссылка не работает

    Всё там работает.
  • DVM © (24.09.10 00:22) [18]

    > EPaul   (23.09.10 12:46) [16]

    а то что по ссылке тебе мало что даст, тебе ж нужно фиксировать отличия вместе с координатами а не просто быстро сравнить две области памяти.
  • EPaul (24.09.10 01:11) [19]
    DVM  Гораздо чаще бывает, когда меняется не весь экран, а очень небольшая его часть. И в этом случае, быстро сравнить допустим 714 фрагментов между собой, и определить, что 15-20 фрагментов отличаются, и только с этими фрагментами дальше работать, чем постоянно попиксельно сравнивать два больших экрана, когда в таком огромном цикле, любое условие на проверку чего-либо грузит проц. на полную катушку, было бы на мой взгляд лучше. Установить порог - выше которого передаются уже не измененные фрагменты, а весь экран.
    Но что-то я уже разуверился , что в делфи это можно сделать.    

    Плохиш У меня не получается скачать по ссылке CompareMemBV14.zip  Выдает ошибку 404  файл не найден. Другие ссылки работают. Кинь мне на почту, если у тебя получается. ПОЖАЛУЙСТА.
  • Дрон (24.09.10 08:58) [20]
    > EPaul   (23.09.10 12:46) [16]

    Вот блог автора этих быстрых функций - http://www.guildalfa.ru/alsha/.
    Спроси у него.
  • Плохиш © (24.09.10 10:57) [21]

    > EPaul   (24.09.10 01:11) [19]


    > Плохиш У меня не получается скачать по ссылке CompareMemBV14.
    > zip  Выдает ошибку 404  файл не найден.

    В гугле это ищется за 10 секунд.
  • DVM © (24.09.10 12:01) [22]

    > EPaul   (24.09.10 01:11) [19]


    > Но что-то я уже разуверился , что в делфи это можно сделать.
    >     

    Если ты не можешь, это не значит, что этого сделать нельзя. И Делфи тут не при чем.
    Сделать можно многое. Правда путь ты выбрал не самый лучший, все же просто периодически сканировать все изображение - не выход. Тут вероятно драйвер нужен для обнаружения изменений с минимальной загрузкой.
    Тебе же посоветовал бы отказаться от TBitmap в пользу TFastDIB (поищи в интернет). В ней проход по пикселам можно выполнить гораздо быстрее.
  • DVM © (24.09.10 12:57) [23]

    > EPaul

    http://msdn.microsoft.com/en-us/library/ff568319(VS.85).aspx

    что то типа того тебе надо.
  • DVM © (24.09.10 13:08) [24]

    > EPaul

    Вот тебе еще одна небольшая вводная http://www.inf.tsu.ru/library/Publications/2005/43.pdf если хочешь конечно серьезно этой темой заняться.

    Больше помочь ничем не могу, вопросом создания mirror драйверов не занимался, это вон к Eraser надо обращаться.
  • EPaul (25.09.10 15:50) [25]
    DVM  Спасибо всем за ответы. На Vingrad мне дали один замечательный код. Сейчас занимаюсь его перевариванием.  Тема пока не закрыта.
  • EPaul (25.09.10 15:59) [26]
    DVM  Написание драйверов - это супер. Может быть, когда нибудь... а пока, что-нибудь попроще.
  • grisme © (10.10.10 10:12) [27]
    EPaul   (25.09.10 15:59) [26]

    при соединении, можно передать изображение всего экрана, а потом:
    - отлавливать получения фокуса окошками.
    - следить за курсором(движения, нажатия), быстро расчитывать в какой "зоне" он проходит/нажимает и отправлять эту зону на перерисовку.
    - точно так же с клавиатурой.
    - и т.д., чем больше "оконных" и мыше-клавных сообщений отлавливать, тем больше будет "правильных" корректировок зон.

    нутыпонел. хуки такие хуки.
  • han_malign (11.10.10 18:00) [28]
    по поводу сравнения:

      pitch:= (cmPredBufBMP.Width * BytesPerPixel + 3) and not 3;
      size:= pitch * cmPredBufBMP.Height;
      if( not CompareMem(cmPredBufBMP.Scanline[0], cmCurrBufBMP.Scanline[0], size) )then begin
         ...
      end;



    > нутыпонел. хуки такие хуки.

    - при выводе анимации никак пользовательских действий не происходит...

    Сравнение полного кадра экрана с предыдущим, по отношению к времени скриншота(копирования из видеопамяти) - занимает меньше 1%... Если использовать зеркальный драйвер(из готовых условно бесплатных, DFMirage - например) - сравнимо. У меня больше 90% времени ZLib отжирает, но если предварительно дельта и RLE сжатие сделать, вытягивает кадров 10-15 в секунду при 10% загрузке CPU...
  • Студент (03.02.11 14:07) [29]

    > Дроблю экран разрешением 1680х1050 на кусочки 50х50 пикселей
    > получается 714 кусочков.


    О, ужас... Зачем?? Тратить время на разбитие картинки, чтоб потом спотыкаться об огромное количество фрагментов? Так только тормозить всё...

    Цель какая? Пересылать изменения экрана на удалённый комп? Дык попробуйте делать XOr а потом Хаффманом... И всё, можно отсылать изменения...
  • Студент (27.06.13 16:46) [30]
    hgjgh
  • scharkhowa (12.11.13 17:35) [31]
    http://www.str-plus.ru/
    Сравнение полного кадра экрана с предыдущим, по отношению к времени скриншота(копирования из видеопамяти) - занимает меньше 1%... Если использовать зеркальный драйвер(из готовых условно бесплатных, DFMirage - например) - сравнимо. У меня больше 90% времени ZLib отжирает, но если предварительно дельта и RLE сжатие сделать, вытягивает кадров 10-15 в секунду при 10% загрузке CPU...

    Ну если только попробовать сделать сжатие
  • Juggernaut (03.12.13 14:53) [32]
    > Попиксельный метод сравнения 2 bitmap не подходит

    А другого не бывает, мил-человек! =)))
    По крайней мере если нужно 100% точное соответствие, а не частичное.

    > очень медленно

    Если через усовершенствованный аналог CompareMem() - жутко быстро.

    > Дык попробуйте делать XOr а потом Хаффманом...
    Любопытно. А TeamViewer делает пачкой из 4-х скринов, каждый из которых... Как бы это... Строка, 3 пропущены, строка, 3 пропущены. И каждый скрин есть 4-я часть оригинала.
 
Конференция "Media" » Быстрое сравнение двух рисунков [D7, WinXP]
Есть новые Нет новых   [134427   +37][b:0][p:0.001]