Перейти к содержимому
Compvision.ru
TroyashkA

Матрица преобразования гомографии

Recommended Posts

Всем привет! Получаю матрицу преобразования гомографии. Хочу сместить изображение на -20 по X. Смещаю, но проблема в том, что изображение не смещается, а сжимается! :(

Вот скриншот:

post-2854-0-23455100-1303150009_thumb.pn

Как видно из скриншота, размеры исходного и трансформированного изображений различаются. dry.gif

P.S. Изображение включено в проект.

P.P.S. не пойму, почему НЕ ВСЕ координаты X углов смещаются. Возможно ошибка в функции GetCorners() ?

Вот простенький проект (с комментариями):

opcvBlank.rar

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Поразмышлял немного... Смещение надо производить немного по-другому:

CvPoint2D64f dst_corners[4]; // Изменил тип точек

...

dst_corners[i] = cvPoint2D64f(X, Y); // Изменил немного GetCorners

...


// Ну и сам сдвиг усложнился

cvmSet(homo, 0, 2, cvmGet(homo, 2, 2) * (dst_corners[0].x - 20));

cvmSet(homo, 0, 0, ((cvmGet(homo, 2, 0) * (double)loaded->width + cvmGet(homo, 2, 2)) * (dst_corners[1].x - 20) - cvmGet(homo, 0, 2)) / (double)loaded->width);

cvmSet(homo, 0, 1, ((cvmGet(homo, 2, 1) * (double)loaded->height + cvmGet(homo, 2, 2)) * (dst_corners[3].x - 20) - cvmGet(homo, 0, 2)) / (double)loaded->height);

Теперь мои мысли:

1. раз преобразование координаты X углов изображения зависит от трёх параметров матрицы гомографии (double X = (h[0] * x + h[1] * y + h[2]) * Z;), то и при сдвиге должны изменяться все три параметра.

2. Для трёх параметров нужна система из трёх уравнений.

- В выражение из пункта 1 подставляем точку с координатами (0; 0), которая соответствует dst_corners[0] и вместо X подставляем X - 20 - находим h[2]

- В выражение из пункта 1 подставляем точку с координатами (width; 0), которая соответствует dst_corners[1] и вместо X подставляем X - 20 - находим h[0]

- В выражение из пункта 1 подставляем точку с координатами (0; height), которая соответствует dst_corners[3] и вместо X подставляем X - 20 - находим h[1]

Вот и всё.

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Поразмышлял немного... Смещение надо производить немного по-другому:

CvPoint2D64f dst_corners[4]; // Изменил тип точек

...

dst_corners[i] = cvPoint2D64f(X, Y); // Изменил немного GetCorners

...


// Ну и сам сдвиг усложнился

cvmSet(homo, 0, 2, cvmGet(homo, 2, 2) * (dst_corners[0].x - 20));

cvmSet(homo, 0, 0, ((cvmGet(homo, 2, 0) * (double)loaded->width + cvmGet(homo, 2, 2)) * (dst_corners[1].x - 20) - cvmGet(homo, 0, 2)) / (double)loaded->width);

cvmSet(homo, 0, 1, ((cvmGet(homo, 2, 1) * (double)loaded->height + cvmGet(homo, 2, 2)) * (dst_corners[3].x - 20) - cvmGet(homo, 0, 2)) / (double)loaded->height);

Теперь мои мысли:

1. раз преобразование координаты X углов изображения зависит от трёх параметров матрицы гомографии (double X = (h[0] * x + h[1] * y + h[2]) * Z;), то и при сдвиге должны изменяться все три параметра.

2. Для трёх параметров нужна система из трёх уравнений.

- В выражение из пункта 1 подставляем точку с координатами (0; 0), которая соответствует dst_corners[0] и вместо X подставляем X - 20 - находим h[2]

- В выражение из пункта 1 подставляем точку с координатами (width; 0), которая соответствует dst_corners[1] и вместо X подставляем X - 20 - находим h[0]

- В выражение из пункта 1 подставляем точку с координатами (0; height), которая соответствует dst_corners[3] и вместо X подставляем X - 20 - находим h[1]

Вот и всё.

Спасибо! Почему-то считал, что за перенос по оси Х/Y отвечает лишь один элемент матрицы ...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

по идее если работать с координатами, то можно вычислить новые координаты

u= (m11*x + m12*y + m13)/(m31*x + m32*y + m33);

v= (m21*x + m22*y + m23)/(m31*x + m32*y + m33);
и вычитать из u необходимое смещение по X. и запихнуть их в remap. а так за перенос по оси Х отвечает лишь один элемент матрицы
//test for homography

	double matrix[9];

	CvMat* homo = cvCreateMat(3, 3, CV_64F);

	matrix[0] = 1; matrix[1] = 0; matrix[2] = 100;

	matrix[3] = 0; matrix[4] = 1; matrix[5] = 100;

	matrix[6] = 0; matrix[7] = 0; matrix[8] = 1.0;


	cvmSet(homo, 0, 0, matrix[0]);

	cvmSet(homo, 0, 1, matrix[1]);

	cvmSet(homo, 0, 2, matrix[2]);

	cvmSet(homo, 1, 0, matrix[3]);

	cvmSet(homo, 1, 1, matrix[4]);

	cvmSet(homo, 1, 2, matrix[5]);

	cvmSet(homo, 2, 0, matrix[6]);

	cvmSet(homo, 2, 1, matrix[7]); 

	cvmSet(homo, 2, 2, matrix[8]);



	IplImage* img= cvLoadImage("1.png");

	IplImage* des= cvCreateImage(cvSize(1000, 1000), 8, 3);




	cvWarpPerspective(img, des, homo);


	cvSaveImage("test_homo.png",des);

соответсвенно код выводит неизмененное изображение img, на изображении des в точке (100;100), но размер des должен быть больше img + смещение. иначе будет обрубок.

соответственно, если еще и наклонные стороны, то надо следить чтобы углы не вышли за пределы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
соответсвенно код выводит неизмененное изображение img, на изображении des в точке (100;100), но размер des должен быть больше img + смещение. иначе будет обрубок.

соответственно, если еще и наклонные стороны, то надо следить чтобы углы не вышли за пределы.

У тебя это работает только потому, что изображение не повёрнуто - соответствующие элементы матрицы гомографии равны нулю. Запусти оригинальный пример и сразу увидишь разницу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

double m11= cvmGet(homo, 0, 0);

	double m12= cvmGet(homo, 0, 1);

	double m13= cvmGet(homo, 0, 2);

	double m21= cvmGet(homo, 1, 0);

	double m22= cvmGet(homo, 1, 1);

	double m23= cvmGet(homo, 1, 2);

	double m31= cvmGet(homo, 2, 0);

	double m32= cvmGet(homo, 2, 1); 

	double m33= cvmGet(homo, 2, 2);


//через ремап

	IplImage* mapx = cvCreateImage( cvGetSize(img), IPL_DEPTH_32F, 1 );

	IplImage* mapy = cvCreateImage( cvGetSize(img), IPL_DEPTH_32F, 1 );

	for (int x = 0; x < mapx->width; x++)

	{

		for (int y = 0; y < mapx->height; y++)

		{

			double u= (m11*x + m12*y + m13)/(m31*x + m32*y + m33);

			cvSetReal2D(mapx, y, x, u);

		}

	}


	for (int x = 0; x < mapy->width; x++) 

	{

		for (int y = 0;y < mapy->height; y++)

		{

			double v= (m21*x + m22*y + m23)/(m31*x + m32*y + m33);

			cvSetReal2D(mapy, y, x, v);

		}

	}

	IplImage* temp = cvCloneImage(img);

	/*IplImage* temp_des = cvCloneImage(des);

	cvSetImageROI(temp_des, cvRect(0, 0, temp->width, temp->height));

	cvCopy(temp,temp_des);

	cvResetImageROI(temp_des);*/

	cvRemap( temp/*temp_des*/, img/*des*/, mapx, mapy ); // нужны одинаковые размеры

	cvSaveImage("remap.png",img/*des*/);

с ремап я погорячился если не изменять размеры изображения, то обрубает, а если изменять надо дополнительно дописывать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
соответсвенно код выводит неизмененное изображение img, на изображении des в точке (100;100), но размер des должен быть больше img + смещение. иначе будет обрубок.

соответственно, если еще и наклонные стороны, то надо следить чтобы углы не вышли за пределы.

У тебя это работает только потому, что изображение не повёрнуто - соответствующие элементы матрицы гомографии равны нулю. Запусти оригинальный пример и сразу увидишь разницу.

ну с матрицей

matrix[0] = 0.8198920262340416; matrix[1] = -0.0464624885991283; matrix[2] = 139.7937963290747800;

	matrix[3] = -0.0843852113893465; matrix[4] = 0.9651779736070743; matrix[5] = 6.7298523737051692;

	matrix[6] = -0.0008243186600599; matrix[7] = 0.0000350886555917; matrix[8] = 1.0;
верхний край выходит за края изображения. но если я изменю
matrix[2] = 119.7937963290747800;

то так же будет смещение по X на -20.

вообще тут как бы надо различать само смещение и координаты точек углов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

ну с матрицей

matrix[0] = 0.8198920262340416; matrix[1] = -0.0464624885991283; matrix[2] = 139.7937963290747800;

	matrix[3] = -0.0843852113893465; matrix[4] = 0.9651779736070743; matrix[5] = 6.7298523737051692;

	matrix[6] = -0.0008243186600599; matrix[7] = 0.0000350886555917; matrix[8] = 1.0;
верхний край выходит за края изображения. но если я изменю
matrix[2] = 119.7937963290747800;

то так же будет смещение по X на -20.

Смещение на -20 будет только лишь у левой верхней точки изображения. Само оно деформируется при этом, а нужен полноценный параллельный перенос. Об этом и пишется в начальном сообщении.

вообще тут как бы надо различать само смещение и координаты точек углов.

Надо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Смещение на -20 будет только лишь у левой верхней точки изображения. Само оно деформируется при этом, а нужен полноценный параллельный перенос. Об этом и пишется в начальном сообщении.

ну так перенос будет абсолютным, все точки переместятся.

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

по сути применяя матрицу мы совершаем перенос ровного изображения, а потом двигаем углы..

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×