Как побыстрее сравнить две картинки
Сейчас делаю это так:
Код:
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
{
//Равны
};
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 пиксела, что не есть конесно очень хорошо (т.к. могу пропустить мелкие изменения) но сравнивать подряд - это совсем медленно получится).
Есть ли какой-нибудь метод (кроме еще большего увеличения шага) ускорить процесс сравнения этих картинок?
Цитата:
Originally posted by MVal
Мне нужно найти разницу между двумя скриншетами в виде ....
Мне нужно найти разницу между двумя скриншетами в виде ....
Если тебе нужно бустро, то про Canvas->Pixels[X][Y] вообще забудь. Сделай хотябы через ScanLine. Но при этом необходимо учитывать формат картинки.
HNADLE h= Image->Canvas-> bitmap->handle;
Потом
выдели память
int memCount = WidthImage*HeigthImage;
HANDLE mem = new int[memCount];
и коперни в память
GetBitmapBits(h,memCount,mem);
А далле я бы советовал обратиться к асм - кой функции сканирования или к MMX. Уже и е помню есть ли тоам что нибудь. А ещё мощешь покапать OpenGL или DirectX, по моему там можно всё сделать наибыстрейшим образом
Цитата:
Originally posted by Jump
Сделай хотябы через ScanLine.
Сделай хотябы через ScanLine.
Спасибо за совет. Подскажи, только как узнать, сколько байт выделяется на пиксел (чтобы эту величину умножить на ширину картинки). А так - действительно на много быстрее.
И еще y считается быстро (порядка 15 мс).
Код:
for (int y=0; y<h; y++)
{
if (!CompareMem(Bitmap2->ScanLine[y], Bitmap1->ScanLine[y], w*3))
{
y1=y;
break;
};
};
{
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;
};
};
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;
};
};
Про иксы - сравниваю через 3 байта (по R-коналу. Думаю, мало вероятно, чтобы R-канал не поменялся, а пиксел изменил цвет).
В результате процедура занимает порядка 110 мс (на той же машине старый вариант клутился порядка 600 мс). Так что прогресс на лицо.
Цитата:
Originally posted by MVal
Поменяй циклы местами х<->y - и вынеси ScanLine() из цика по х.Указатель со ScanLine действителен все время жизни битмапа, и нет смысла повторять эту функцию для каждого пикселя одной строчки. У меня время полного доступа к битмапу 800*600 порядка 10-15 мс.
+ Ставь лучше 32байта и указатели не на byte а на int и тогда за одно сравнение сравнише сразу по всей РГБ.