Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Как побыстрее сравнить две картинки

830
24 января 2006 года
MVal
76 / / 17.10.2002
Мне нужно найти разницу между двумя скриншетами в виде координат левого верхнего и правого нижнего углов прямоугольника, который изменился, чтобы потом передать этот прямоугольник (и его координаты).
Сейчас делаю это так:
Код:
int sm1, sm2;
 for ( X=0; X<w; X+=4)
{
 sm1=0; sm2=0;
 for ( Y=0; Y<h; Y+=4)
 {
  sm1+=(lasti->Canvas->Pixels[X][Y]);
  sm2+=(image->Canvas->Pixels[X][Y]);
 };
 if (sm1!=sm2) break;

};
if (sm1!=sm2)
{
  x1=max(0,X-3);  
}
else
{
  //Равны
};

Получаю левый X. Аналогично получаю остальные координаты.
Все бы ничего, да даже в таком виде это занимает около половины секунды времени (при 1072х768). (X+4 - т.к. сравнивуаю через 4 пиксела, что не есть конесно очень хорошо (т.к. могу пропустить мелкие изменения) но сравнивать подряд - это совсем медленно получится).
Есть ли какой-нибудь метод (кроме еще большего увеличения шага) ускорить процесс сравнения этих картинок?
4.8K
24 января 2006 года
Jump
128 / / 09.11.2005
Цитата:
Originally posted by MVal
Мне нужно найти разницу между двумя скриншетами в виде ....



Если тебе нужно бустро, то про Canvas->Pixels[X][Y] вообще забудь. Сделай хотябы через ScanLine. Но при этом необходимо учитывать формат картинки.

16K
24 января 2006 года
Konstantin_STD
2 / / 24.01.2006
Получи Handl Bitmap
HNADLE h= Image->Canvas-> bitmap->handle;
Потом
выдели память
int memCount = WidthImage*HeigthImage;
HANDLE mem = new int[memCount];
и коперни в память
GetBitmapBits(h,memCount,mem);
А далле я бы советовал обратиться к асм - кой функции сканирования или к MMX. Уже и е помню есть ли тоам что нибудь. А ещё мощешь покапать OpenGL или DirectX, по моему там можно всё сделать наибыстрейшим образом
830
25 января 2006 года
MVal
76 / / 17.10.2002
Цитата:
Originally posted by Jump
Сделай хотябы через ScanLine.


Спасибо за совет. Подскажи, только как узнать, сколько байт выделяется на пиксел (чтобы эту величину умножить на ширину картинки). А так - действительно на много быстрее.

И еще y считается быстро (порядка 15 мс).

 
Код:
for (int y=0; y<h; y++)
 {
 if (!CompareMem(Bitmap2->ScanLine[y], Bitmap1->ScanLine[y], w*3))
  {
    y1=y;
    break;
  };
 };

Иксы же раз в 20 дольше (т.к. приходится брать по одному иксу из разных массивов (что всеравно быстрее, чем Canvas->Pixels[X][Y]). Но всеже можно ли как-нибудь улучшить ситуацию с иксами?
Код:
byte * ptr2;
 byte * ptr1;
  for (int x=0; x<w*3; x++)
   {
     sum1=0; sum2=0;
     for (int y=y1; y<y2; y++)
      {
        ptr2 = (byte *) Bitmap2->ScanLine[y];
        ptr1 = (byte *) Bitmap1->ScanLine[y];
        sum1+=ptr1[x];
        sum2+=ptr2[x];
      };
     if (sum1!=sum2)
      {
        x1=x/3;
        break;
      };
  };
830
26 января 2006 года
MVal
76 / / 17.10.2002
Про колличество байт - это разобрался. Установить PixelFormat=pf24bit и будет всегда через 3 байта.
Про иксы - сравниваю через 3 байта (по R-коналу. Думаю, мало вероятно, чтобы R-канал не поменялся, а пиксел изменил цвет).
В результате процедура занимает порядка 110 мс (на той же машине старый вариант клутился порядка 600 мс). Так что прогресс на лицо.
4.8K
26 января 2006 года
Jump
128 / / 09.11.2005
Цитата:
Originally posted by MVal



Поменяй циклы местами х<->y - и вынеси ScanLine() из цика по х.Указатель со ScanLine действителен все время жизни битмапа, и нет смысла повторять эту функцию для каждого пикселя одной строчки. У меня время полного доступа к битмапу 800*600 порядка 10-15 мс.

+ Ставь лучше 32байта и указатели не на byte а на int и тогда за одно сравнение сравнише сразу по всей РГБ.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог