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

Приведение к прямоугольному виду после склейки

Recommended Posts

Как можно после склейки двух изображений результат "ужать" в прямоугольник? Может есть какая-нибудь функция в opencv или готовый алгоритм?

post-5245-0-38478600-1335728750_thumb.pn

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


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

Что значит "ужать"?

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


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

Что значит "ужать"?

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

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


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

И сразу еще один вопрос задам: правое (преобразованное) изображение сильно потеряло в качестве, что при разрешении 600х450 очень заметно. Тут я уже ничего поделать не смогу?

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


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

Код приложения (нашел на каком-то сайте), пытаюсь реализовать под свои нужды:


// StartOpenCV.cpp: определяет точку входа для консольного приложения.

//

/**

#include "stdafx.h"

#include <cv.h>



int _tmain(int argc, _TCHAR* argv[])

{

	return 0;

}


*/

#include "StdAfx.h"

#include <iostream>

#include <cv.h>

#include <cxcore.h>

#include <highgui.h>

#include <cvaux.h>


using namespace std;


typedef struct MATCH_PAIR

{

	int nA;

	int nB;

} MATCH_PAIR;



void MergeImages(IplImage* Image1, IplImage* Image2, IplImage* dstImage);

int FindMatchingPoints(const CvSeq* tKeypoints, const CvSeq* tDescriptors, const CvSeq* srcKeypoints, const CvSeq* srcDescriptors, int descriptor_size, MATCH_PAIR *pMatchPair);

int FindNearestPoints(const float* pA, int laplacian, const CvSeq* srcKeypoints, const CvSeq* srcDescriptors, int descriptor_size);


//void main()

//{

int _tmain(int argc, _TCHAR* argv[])

{	


	IplImage *T1Img = cvLoadImage("C:/im2.jpg");

	IplImage *T2Img = cvLoadImage("C:/im1.jpg");

	IplImage *mT2Img, *mT1Img;



	mT1Img = cvCreateImage(cvSize(T1Img->width, T1Img->height),T1Img->depth, 1);

	cvCvtColor(T1Img, mT1Img, CV_BGR2GRAY);





	mT2Img = cvCreateImage(cvSize(T2Img->width, T2Img->height),T2Img->depth, 1);

	cvCvtColor(T2Img, mT2Img, CV_BGR2GRAY);


	CvMemStorage* storage =cvCreateMemStorage(0);

	CvSURFParams params = cvSURFParams(1000, 0);


	CvSeq *T1_Keypoints = NULL;

	CvSeq *T1_Descriptors = NULL;

	cvExtractSURF(mT1Img, NULL, &T1_Keypoints, &T1_Descriptors, storage, params);


	CvSeq *T2_Keypoints = NULL;

	CvSeq *T2_Descriptors = NULL;

	cvExtractSURF(mT2Img, NULL, &T2_Keypoints, &T2_Descriptors, storage, params);


	CvSURFPoint* surf1;

	CvSURFPoint* surf2;


	MATCH_PAIR *pMatchPair = new MATCH_PAIR[T1_Keypoints->total];

	int descriptor_size = params.extended? 128 : 64;

	int nMatchingCount = FindMatchingPoints(T1_Keypoints, T1_Descriptors, T2_Keypoints, T2_Descriptors,         descriptor_size, pMatchPair);


	CvPoint2D32f *pt1 = new CvPoint2D32f[nMatchingCount];

	CvPoint2D32f *pt2 = new CvPoint2D32f[nMatchingCount];


	int x1, y1, x2, y2;

	for(int k=0; k<nMatchingCount; k++)

	{


		surf1 = (CvSURFPoint*) cvGetSeqElem(T1_Keypoints, pMatchPair[k].nA);

		x1 = cvRound(surf1->pt.x);

		y1 = cvRound(surf1->pt.y);


		surf2 = (CvSURFPoint*) cvGetSeqElem(T2_Keypoints, pMatchPair[k].nB);

		x2 = cvRound(surf2->pt.x)  + T1Img->width;

		y2 = cvRound(surf2->pt.y);

		CvPoint r1 = cvPoint(x1, y1);

		CvPoint r2 = cvPoint(x2, y2);

		pt1[k] = surf1->pt;

		pt2[k] = surf2->pt;

	} 


	if(nMatchingCount<4)

	{


		return 0;

	}


	CvMat M1, M2;	

	double H[9];

	CvMat mxH = cvMat(3, 3, CV_64F, H);

	M1 = cvMat(1, nMatchingCount, CV_32FC2, pt1);

	M2 = cvMat(1, nMatchingCount, CV_32FC2, pt2);

	if( !cvFindHomography(&M1, &M2, &mxH, CV_RANSAC, 2))

	{

		return 0;

	}


	IplImage* WarpImg = cvCreateImage(cvSize(T1Img->width*2, T1Img->height*1.5), T1Img->depth, T1Img->nChannels);	

	cvWarpPerspective(T1Img, WarpImg, &mxH);


	cvSetImageROI(WarpImg, cvRect(0, 0, T2Img->width, T2Img->height));

	cvCopy(T2Img, WarpImg);

	cvResetImageROI(WarpImg);



	cvNamedWindow("WarpImg Img",1);

	cvShowImage("WarpImg Img", WarpImg);


	cvWaitKey(0);


	delete pMatchPair;

	delete pt1;

	delete pt2;

	cvReleaseImage(&WarpImg);

	cvReleaseImage(&T1Img);

	cvReleaseImage(&T2Img);

	cvReleaseImage(&mT1Img);

	cvReleaseImage(&mT2Img);

}




void MergeImages(IplImage* Image1, IplImage* Image2, IplImage* dstImage)

{

	cvSet(dstImage, CV_RGB(255, 255, 255));

	cvSetImageROI(dstImage, cvRect(0, 0, Image1->width, Image1->height));

	cvSetImageCOI(dstImage, 1); //Г¤іО 1

	cvCopy(Image1, dstImage);	

	cvSetImageCOI(dstImage, 2); //Г¤іО 2

	cvCopy(Image1, dstImage);	

	cvSetImageCOI(dstImage, 3); //Г¤іО 3

	cvCopy(Image1, dstImage);



	cvSetImageROI(dstImage, cvRect(Image1->width, 0, Image2->width, Image2->height));

	cvSetImageCOI(dstImage, 1); //Г¤іО 1

	cvCopy(Image2, dstImage);

	cvSetImageCOI(dstImage, 2); //Г¤іО 2

	cvCopy(Image2, dstImage);

	cvSetImageCOI(dstImage, 3); //Г¤іО 3

	cvCopy(Image2, dstImage);

	cvResetImageROI(dstImage);


}



int FindMatchingPoints(const CvSeq* tKeypoints, const CvSeq* tDescriptors, const CvSeq* srcKeypoints, const CvSeq* srcDescriptors, int descriptor_size, MATCH_PAIR *pMatchPair)

{

	int i;

	float* pA;

	int nMatchB;

	CvSURFPoint* surfA;

	int k=0;

	for(i=0; i<tDescriptors->total; i++)

	{

		pA = (float*) cvGetSeqElem(tDescriptors, i);

		surfA = (CvSURFPoint*) cvGetSeqElem(tKeypoints, i);

		nMatchB = FindNearestPoints(pA, surfA->laplacian, srcKeypoints, srcDescriptors, descriptor_size);

		if(nMatchB > 0)

		{

			pMatchPair[k].nA=i;

			pMatchPair[k].nB = nMatchB;

			k++;

		}

	}


	return k;

}



int FindNearestPoints(const float* pA, int laplacian, const CvSeq* srcKeypoints, const CvSeq* srcDescriptors, int descriptor_size)

{

	int i, k;

	float* pB;

	CvSURFPoint *surfB;

	int nMatch = -1;

	double sum2, min1 = 1000, min2 = 1000;

	for(i=0; i<srcDescriptors->total; i++)

	{

		surfB = (CvSURFPoint*) cvGetSeqElem(srcKeypoints, i);

		pB = (float*) cvGetSeqElem(srcDescriptors, i);

		if(laplacian != surfB->laplacian)

			continue;


		sum2 = 0.0f;

		for(k=0; k<descriptor_size; k++)	{	sum2 +=(pA[k]-pB[k])*(pA[k]-pB[k]);	}


		if(sum2 < min1)

		{

			min2 = min1;

			min1 = sum2;

			nMatch = i;

		}

		else if(sum2<min2)	{	min2 = sum2;	}

	}

	if(min1<0.6*min2)

		return nMatch;


	return -1;

}


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


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

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

Можно посмотреть тут (тут правда для выпуклых областей,но думаю здесь поможет cvConvexityDefects):

http://cgm.cs.mcgill.ca/~athens/cs507/Projects/2003/DanielSud/

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


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

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

Можно посмотреть тут (тут правда для выпуклых областей,но думаю здесь поможет cvConvexityDefects):

http://cgm.cs.mcgill.ca/~athens/cs507/Projects/2003/DanielSud/

Надеялся что будет простое решение =( Дело в том что не могу произвести такое количество действий. Думал что могут как-то помочь cvRemap или cvWarpAffine. Может какой-то недочет в коде?

Нашел сайт по скриншотам вроде оно: <_<

http://blog.naver.com/PostView.nhn?blogId=tramper2&logNo=100086964864&categoryNo=20&viewDate=&currentPage=1&listtype=0

Почти как описали

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


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

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

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

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×