Re[2]: [XviD-devel] motion estimation for B/P/I decision

Marco Al xvid-devel@xvid.org
Fri, 20 Sep 2002 19:58:44 +0200


This is a multi-part message in MIME format.

------=_NextPart_000_0007_01C260E0.1FEAAF50
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

Marc FD wrote:

> @MarcoAI
> do you have any C implementation of Zhou Wang's structural distortion
> measure ??

Here is a working one (ignore the C++ stuff around it, thats just for testing it
with the 512*512 GIFs from Zhou Whang's site).

Marco

------=_NextPart_000_0007_01C260E0.1FEAAF50
Content-Type: text/plain;
	name="distort.cpp"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="distort.cpp"

// distort.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "atlimage.h"
#include <iostream.h>

#define BLOCK_SIZE 8
#define N BLOCK_SIZE * BLOCK_SIZE

float
image_structural_distortion(unsigned char *img1,
		   unsigned char *img2,
		   int stride,
		   int width,
		   int height)
{
	int x, y, img1_sum_temp, img2_sum_temp, img1_sq_sum_temp, =
img2_sq_sum_temp,
		img12_sum_temp, img1_sq_sum, img2_sq_sum, img12_sum, img12_sum_mul,
		img12_sum_sq_sum;
	short img1_sum, img2_sum;
	float numerator, denominator1, denominator, q, structural_distortion =
=3D 0;

	//alignment wont do a hell of a lot of good given the way we access =
this ...
	short *img1_sum_ptr, *img1_sum_acc =3D (short *)malloc((height + 1) * =
(width + 1) * 2);
	short *img2_sum_ptr, *img2_sum_acc =3D (short *)malloc((height + 1) * =
(width + 1) * 2);
	int *img1_sq_sum_ptr, *img1_sq_sum_acc =3D (int *)malloc((height + 1) * =
(width + 1) * 4);
	int *img2_sq_sum_ptr, *img2_sq_sum_acc =3D (int *)malloc((height + 1) * =
(width + 1) * 4);
	int *img12_sum_ptr, *img12_sum_acc =3D (int *)malloc((height + 1) * =
(width + 1) * 4);

	img1_sum_ptr =3D img1_sum_acc;
	img2_sum_ptr =3D img2_sum_acc;
	img1_sq_sum_ptr =3D img1_sq_sum_acc;
	img2_sq_sum_ptr =3D img2_sq_sum_acc;
	img12_sum_ptr =3D img12_sum_acc;

	for (x =3D 0; x < width + 1; x++) {
		*(img1_sum_acc + x) =3D 0;
		*(img2_sum_acc + x) =3D 0;
		*(img1_sq_sum_acc + x) =3D 0;
		*(img2_sq_sum_acc + x) =3D 0;
		*(img12_sum_acc + x) =3D 0;
	}

	for (y =3D 1; y < height + 1; y++) {
		*(img1_sum_acc + y * (width + 1)) =3D 0;
		*(img2_sum_acc + y * (width + 1)) =3D 0;
		*(img1_sq_sum_acc + y * (width + 1)) =3D 0;
		*(img2_sq_sum_acc + y * (width + 1)) =3D 0;
		*(img12_sum_acc + y * (width + 1)) =3D 0;
	}

	img1_sum_acc +=3D width + 2;
	img2_sum_acc +=3D width + 2;
	img1_sq_sum_acc +=3D width + 2;
	img2_sq_sum_acc +=3D width + 2;
	img12_sum_acc +=3D width + 2;

	for (y =3D 0; y < height; y++) {
		img1_sum_temp =3D 0;
		img2_sum_temp =3D 0;
		img1_sq_sum_temp =3D 0;
		img2_sq_sum_temp =3D 0;
		img12_sum_temp =3D 0;

		for (x =3D 0; x < width; x++) {
			img1_sum_temp +=3D  *(img1 + x);
			*(img1_sum_acc + x) =3D *(img1_sum_acc + x - (width + 1)) + =
img1_sum_temp;
			img2_sum_temp +=3D *(img2 + x);
			*(img2_sum_acc + x) =3D *(img2_sum_acc + x - (width + 1)) + =
img2_sum_temp;
			img1_sq_sum_temp +=3D *(img1 + x) * *(img1 + x);
			*(img1_sq_sum_acc + x) =3D *(img1_sq_sum_acc + x - (width + 1)) + =
img1_sq_sum_temp;
			img2_sq_sum_temp +=3D *(img2 + x) * *(img2 + x);
			*(img2_sq_sum_acc + x) =3D *(img2_sq_sum_acc + x - (width + 1)) + =
img2_sq_sum_temp;
			img12_sum_temp +=3D *(img1 + x) * *(img2 + x);
			*(img12_sum_acc + x) =3D *(img12_sum_acc + x - (width + 1)) + =
img12_sum_temp;
		}

		img1 +=3D stride;
		img2 +=3D stride;
		img1_sum_acc +=3D width + 1;
		img2_sum_acc +=3D width + 1;
		img1_sq_sum_acc +=3D width + 1;
		img2_sq_sum_acc +=3D width + 1;
		img12_sum_acc +=3D width + 1;
	}

	img1_sum_acc =3D img1_sum_ptr;
	img2_sum_acc =3D img2_sum_ptr;
    img1_sq_sum_acc =3D img1_sq_sum_ptr;
	img2_sq_sum_acc =3D img2_sq_sum_ptr;
    img12_sum_acc =3D img12_sum_ptr;

	for (y =3D 0; y < height - BLOCK_SIZE + 1; y++) {
		for (x =3D 0; x < width - BLOCK_SIZE + 1; x++) {
			img1_sum =3D *(img1_sum_acc + x + BLOCK_SIZE + BLOCK_SIZE * (width + =
1)) -
                *(img1_sum_acc + x + BLOCK_SIZE) -
				*(img1_sum_acc + x + BLOCK_SIZE * (width + 1)) +
				*(img1_sum_acc + x);
			img2_sum =3D *(img2_sum_acc + x + BLOCK_SIZE + BLOCK_SIZE * (width + =
1)) -
				*(img2_sum_acc + x + BLOCK_SIZE) -
				*(img2_sum_acc + x + BLOCK_SIZE * (width + 1)) +
				*(img2_sum_acc + x);
			img1_sq_sum =3D *(img1_sq_sum_acc + x + BLOCK_SIZE + BLOCK_SIZE * =
(width + 1)) -
				*(img1_sq_sum_acc + x + BLOCK_SIZE) -
				*(img1_sq_sum_acc + x + BLOCK_SIZE * (width + 1)) +
				*(img1_sq_sum_acc + x);
			img2_sq_sum =3D *(img2_sq_sum_acc + x + BLOCK_SIZE + BLOCK_SIZE * =
(width + 1)) -
				*(img2_sq_sum_acc + x + BLOCK_SIZE) -
				*(img2_sq_sum_acc + x + BLOCK_SIZE * (width + 1)) +
				*(img2_sq_sum_acc + x);
			img12_sum =3D *(img12_sum_acc + x + BLOCK_SIZE + BLOCK_SIZE * (width =
+ 1)) -
				*(img12_sum_acc + x + BLOCK_SIZE) -
				*(img12_sum_acc + x + BLOCK_SIZE * (width + 1)) +
				*(img12_sum_acc + x);
			img12_sum_mul =3D img1_sum * img2_sum;
			/* the matlab equivalent for the next name was silly, yes even =
sillier than these ones, so instead
			of sq sum mul I used sum sq sum */
			img12_sum_sq_sum =3D img1_sum * img1_sum + img2_sum * img2_sum;

			numerator =3D (float)4 * ((float)N * (float)img12_sum - =
(float)img12_sum_mul) * (float)img12_sum_mul;
			denominator1 =3D (float)N * ((float)img1_sq_sum + (float)img2_sq_sum) =
- (float)img12_sum_sq_sum;
			denominator =3D denominator1 * (float)img12_sum_sq_sum;

			q =3D 1;
			if ((denominator1 =3D=3D 0) && (img12_sum_sq_sum !=3D 0))
				q =3D 2 * (float)img12_sum_mul / (float)img12_sum_sq_sum;
			if (denominator !=3D 0)
				q =3D numerator / denominator;
		=09
			structural_distortion +=3D q;
		}

		img1_sum_acc +=3D width + 1;
		img2_sum_acc +=3D width + 1;
		img1_sq_sum_acc +=3D width + 1;
		img2_sq_sum_acc +=3D width + 1;
		img12_sum_acc +=3D width + 1;
	}
=09
	structural_distortion /=3D (width - BLOCK_SIZE + 1) * (height - =
BLOCK_SIZE + 1);
	return structural_distortion;
}

int _tmain(int argc, _TCHAR* argv[])
{
    CImage im1, im2;
    im1.Load(argv[1]);=20
    im2.Load(argv[2]);

	unsigned char *img1 =3D (unsigned char *)im1.GetBits();
	unsigned char *img2 =3D (unsigned char *)im2.GetBits();

	img1 -=3D 511*512;
	img2 -=3D 511*512;

	cout << "Q: " << image_structural_distortion(img1, img2, 512, 512, =
512);

	return 0;
}

------=_NextPart_000_0007_01C260E0.1FEAAF50--