您的位置:首页 > 运维架构

基于OpenCV1.1的图像拼接

2015-04-09 18:05 246 查看
最近开发基于OpenCV的图像处理,OpenCV的确强大,根据近来的所学心得,来个比较麻烦也比较有代表性的项目,图像拼接,根据图像surf特征拼接.

首先准备两张有关联的图片,或者直接把一张图片分成两半。

大概步骤如下:

1 特征提取

载入图片后,转灰度,计算图片的特征点,经典的surf算法就可以。

直接使用OpenCV方法:cvExtractSURF( object, 0, &objectKeypoints, &objectDescriptors, storage, params );

2 特征点匹配

特征点的匹配的准确性直接影响投影矩阵,所以匹配要求还是要尽量去准确,采用opencv例程中的匹配算法,

需要计算特征向量的距离,计算欧式距离,采用最近邻(Nearest Neighbor,NN)方法对特征点进行粗匹配来判断是否匹配

int	naiveNearestNeighbor( const float* vec, int laplacian,
const CvSeq* model_keypoints,
const CvSeq* model_descriptors )
{
int length = (int)(model_descriptors->elem_size/sizeof(float));
int i, neighbor = -1;
double d, dist1 = 1e6, dist2 = 1e6;
CvSeqReader reader, kreader;
cvStartReadSeq( model_keypoints, &kreader, 0 );
cvStartReadSeq( model_descriptors, &reader, 0 );

for( i = 0; i < model_descriptors->total; i++ )
{
const CvSURFPoint* kp = (const CvSURFPoint*)kreader.ptr;
const float* mvec = (const float*)reader.ptr;
CV_NEXT_SEQ_ELEM( kreader.seq->elem_size, kreader );
CV_NEXT_SEQ_ELEM( reader.seq->elem_size, reader );
if( laplacian != kp->laplacian )
continue;
d = compareSURFDescriptors( vec, mvec, dist2, length );
if( d < dist1 )
{
dist2 = dist1;
dist1 = d;
neighbor = i;
}
else if ( d < dist2 )
dist2 = d;
}
if ( dist1 < 0.6*dist2 )
return neighbor;
return -1;
}
一对特征保存连续的集合中,后面计算在分别取出奇数和偶数对特征,取出特征

findPairs( objectKeypoints, objectDescriptors, imageKeypoints, imageDescriptors, ptpairs );
n = ptpairs.size()/2;
if( n < 4 )
return 0;

pt1.resize(n);
pt2.resize(n);
for( i = 0; i < n; i++ )
{
pt1[i] = ((CvSURFPoint*)cvGetSeqElem(objectKeypoints,ptpairs[i*2]))->pt;
pt2[i] = ((CvSURFPoint*)cvGetSeqElem(imageKeypoints,ptpairs[i*2+1]))->pt;
}


3 特征点提纯

4 旋转矩阵

根据取出的特征,求单应性矩阵,
_pt1 = cvMat(1, n, CV_32FC2, &pt1[0] );

_pt2 = cvMat(1, n, CV_32FC2, &pt2[0] );
单应性矩阵 cvFindHomography( &_pt1, &_pt2, &_h, CV_RANSAC, 5 )

此处用CV_RANSAC算法

计算投影图像各点的投影位置

for( i = 0; i < 4; i++ )
{
double x = src_corners[i].x, y = src_corners[i].y;
double Z = 1./(h[6]*x + h[7]*y + h[8]);
double X = (h[0]*x + h[1]*y + h[2])*Z;
double Y = (h[3]*x + h[4]*y + h[5])*Z;
dst_corners[i] = cvPoint2D32f(X,Y/*cvRound(X), cvRound(Y)*/);
}


对图像进行投影:cvWarpPerspective(object,m_projImg,&PH);

m_projImg 即是投影后的图片,待拼接

5 图像拼接

根据投影的图像,进行拼接,分别设置roi,

CvRect roiRect = cvRect(xMin+m_iXL,yMin+m_iYT,xMax-xMin,yMax-yMin);

cvSetImageROI(m_pBigImg,roiRect);

roiRect = cvRect(xMin,yMin,xMax-xMin,yMax-yMin);

cvSetImageROI(m_projImg,roiRect);

cvCopy(m_projImg,m_pBigImg);

6.测试结果

大图:



暂时效果是可以,因为还没做图像融合,所以还需进一步处理,

全部代码地址:http://download.csdn.net/detail/inmiracle/8578651

欢迎大家交流学习,Q群:213700322
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: