基于OpenCV1.1的图像拼接

最近开发基于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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值