您的位置:首页 > Web前端

使用liner、feather、multiband对已经拼接的数据进行融合

2014-07-15 20:40 441 查看
所谓"blend",英文解释为“vt. 混合vi. 混合;协调n. 混合;掺合物”这里应该理解为是图像数据的融合。这是“识别->对准->融合”的最后一步。融合是决定拼接质量的关键一步,一方面它决定于图像对准的质量,一方面它本身的也直接对拼接的最终结果负责。

最简单和便于理解的融合为liner,正好借这个例子来说明说明是融合,简单的说,就是在融合的区域……(这个地方引用相关资料)liner在opencv中没有实现,但是本身简单有效,对于要求不是很高的情况可以使用,这里给出函数(再做相关解释)
#pragma region mulitStitch
[align=left]/*----------------------------[/align]
[align=left] * 功|能 : 多图?匹配?[/align]
[align=left] *----------------------------[/align]
[align=left] * 函数y : MulitMatch[/align]
[align=left] * 访?问 : private[/align]
[align=left] * 返回? : void[/align]
[align=left] *[/align]
[align=left] * 参?数y : matinput [in] 全?部?需要a匹配?图?的?vector[/align]
[align=left] * 参?数y : matloc1 [ot] 所有D匹配?中D对?应|于第一?图?的?结果?向量?[/align]
[align=left] * 参?数y : matloc1 [ot] 所有D匹配?中D对?应|于第二t图?的?结果?向量?[/align]
[align=left] * 参?数y : match_method [in] 匹配?方?法[/align]
[align=left] */[/align]
[align=left]void MulitMatch(deque<Mat>& matinput,deque<Point>& matloc1,deque<Point>& matloc2, int match_method)[/align]
[align=left]{[/align]
[align=left] Mat img_display1;Mat img_display2;[/align]
[align=left] Point matchLoc1;Point matchLoc2;[/align]
[align=left] for (int i =0;i<matinput.size()-1;i++)[/align]
[align=left] {[/align]
[align=left] [/align]
[align=left] //拷?贝副本?[/align]
[align=left] img_display1 = matinput[i];[/align]
[align=left] img_display2 = matinput[i+1];[/align]
[align=left] //以?中D心?区?域为aroi[/align]
[align=left] // Mat imagetmp (img_display1, Rect(img_display1.rows/2, img_display1.cols/2, 10, 10) );//11:44:02[/align]
[align=left] [/align]
[align=left] Mat imagetmp (img_display1, Rect(960,240, 10, 10) );//11:44:02[/align]
[align=left] int result_cols = img_display1.cols - imagetmp.cols + 1;[/align]
[align=left] int result_rows = img_display1.rows - imagetmp.rows + 1;[/align]
[align=left] Mat imagematch;[/align]
[align=left] imagematch.create( result_cols, result_rows, CV_32FC1 );[/align]
[align=left] /// 进?行D匹配?和标准?化[/align]
[align=left] //匹配?1[/align]
[align=left] matchTemplate( img_display1, imagetmp, imagematch, match_method );[/align]
[align=left] normalize( imagematch, imagematch, 0, 1, NORM_MINMAX, -1, Mat() );[/align]
[align=left] double minVal; double maxVal;[/align]
[align=left] Point minLoc; Point maxLoc;[/align]
[align=left] minMaxLoc( imagematch, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );[/align]
[align=left] //智?能判D断?,这a里?的?matchLoc就是?最?佳?匹配?点?[/align]
[align=left] if( match_method == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED )[/align]
[align=left] { matchLoc1 = minLoc; }[/align]
[align=left] else[/align]
[align=left] { matchLoc1 = maxLoc; }[/align]
[align=left] matloc1.push_back(matchLoc1); //加入?序列D[/align]
[align=left] //匹配?2[/align]
[align=left] matchTemplate( img_display2, imagetmp, imagematch, match_method );[/align]
[align=left] normalize( imagematch, imagematch, 0, 1, NORM_MINMAX, -1, Mat() );[/align]
[align=left] minMaxLoc( imagematch, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );[/align]
[align=left] //智?能判D断?,这a里?的?matchLoc就是?最?佳?匹配?点?[/align]
[align=left] if( match_method == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED )[/align]
[align=left] { matchLoc2 = minLoc; }[/align]
[align=left] else[/align]
[align=left] { matchLoc2 = maxLoc; }[/align]
[align=left] matloc2.push_back(matchLoc2); //加入?序列D[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left]/*----------------------------[/align]
[align=left] * 功|能 : 多图?对?准?[/align]
[align=left] *----------------------------[/align]
[align=left] * 函数y : MulitAlign[/align]
[align=left] * 访?问 : private[/align]
[align=left] * 返回? : Mat[/align]
[align=left] *[/align]
[align=left] * 参?数y : matinput [in] 全?部?需要a匹配?图?的?vector[/align]
[align=left] * 参?数y : matloc1 [ot] 所有D匹配?中D对?应|于第一?图?的?结果?向量?[/align]
[align=left] * 参?数y : matloc1 [ot] 所有D匹配?中D对?应|于第二t图?的?结果?向量?[/align]
[align=left] */[/align]
[align=left]Mat MulitAlign(deque<Mat>& matinput,deque<Point>& matloc1,deque<Point>& matloc2)[/align]
[align=left]{ [/align]
[align=left] Mat outImage; //待y输?出?图?片?[/align]
[align=left] //计?算?图?片?大小? [/align]
[align=left] int nr = matinput[0].rows;[/align]
[align=left] int nl = matinput[0].cols*matinput[0].channels();[/align]
[align=left] int ioffset = 0;int ioffsetdetail = 0;[/align]
[align=left] //计?算?offset[/align]
[align=left] for (int i =0;i<matloc1.size()-1;i++)[/align]
[align=left] {[/align]
[align=left] ioffset = ioffset+matloc1[i].y- matloc2[i].y;[/align]
[align=left] }[/align]
[align=left] outImage.create( matinput[0].rows+ioffset, matinput[0].cols, matinput[0].type());[/align]
[align=left] for (int i=0;i<matloc1.size()-1;i++)[/align]
[align=left] {[/align]
[align=left] if (i == 0)//如?果?第一?弹[/align]
[align=left] {[/align]
[align=left] for (int a=0;a<nr;a++) //第一?图?[/align]
[align=left] {[/align]
[align=left] const uchar* inData=matinput[0].ptr<uchar>(a);[/align]
[align=left] uchar* outData=outImage.ptr<uchar>(a); [/align]
[align=left] for(int j=0;j<nl;j++)[/align]
[align=left] {[/align]
[align=left] outData[j]=inData[j]; [/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] for (int b=0;b<nr;b++) //第二t图?[/align]
[align=left] {[/align]
[align=left] const uchar* inData=matinput[1].ptr<uchar>(b);[/align]
[align=left] uchar* outData=outImage.ptr<uchar>(b+matloc1[0].y-matloc2[0].y); [/align]
[align=left] for(int j=0;j<nl;j++)[/align]
[align=left] {[/align]
[align=left] outData[j]=inData[j]; [/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] ioffsetdetail += matloc1[0].y-matloc2[0].y;[/align]
[align=left] }[/align]
[align=left] else//如?果?不?是?第一?弹[/align]
[align=left] {[/align]
[align=left] for (int b=0;b<nr;b++) [/align]
[align=left] {[/align]
[align=left] const uchar* inData=matinput[i+1].ptr<uchar>(b);[/align]
[align=left] uchar* outData=outImage.ptr<uchar>(b+ioffsetdetail+matloc1[i].y-matloc2[i].y); [/align]
[align=left] for(int j=0;j<nl;j++)[/align]
[align=left] {[/align]
[align=left] outData[j]=inData[j]; [/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] ioffsetdetail += matloc1[i+1].y-matloc2[i].y;[/align]
[align=left] } [/align]
[align=left] [/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] return outImage;[/align]
[align=left]}[/align]
[align=left]/*----------------------------[/align]
[align=left] * 功|能 : 多图?融合?[/align]
[align=left] *----------------------------[/align]
[align=left] * 函数y : MulitBlend[/align]
[align=left] * 访?问 : private[/align]
[align=left] * 返回? : Mat&[/align]
[align=left] *[/align]
[align=left] * 参?数y : matinput [in] 图?片?输?入?序列D[/align]
[align=left] * 参?数y : imagesrc [in] 已?经-对?准?的?图?片?[/align]
[align=left] * 参?数y : matloc1 [in] 第一?图?匹配?位?置?[/align]
[align=left] * 参?数y : matloc2 [in] 第二t图?匹配?位?置?[/align]
[align=left] */[/align]
[align=left]Mat MulitBlend(deque<Mat>& matinput, const Mat& imagesrc,deque<Point>& matloc1,deque<Point>& matloc2)[/align]
[align=left]{ [/align]
[align=left] Mat outImage; //待y输?出?图?片?[/align]
[align=left] imagesrc.copyTo(outImage); //图?像?拷?贝[/align]
[align=left] int ioffsetdetail = 0;[/align]
[align=left] double dblend = 0.0;[/align]
[align=left] for (int i =0;i<matloc1.size()-1;i++)[/align]
[align=left] {[/align]
[align=left] dblend = 0.0;[/align]
[align=left] int ioffset = matloc1[i].y - matloc2[i].y;//row的?偏?移?[/align]
[align=left] for (int j = 0;j<100;j++)//这a个?地?方?用?i 和 j很不?好?[/align]
[align=left] { [/align]
[align=left] outImage.row(ioffsetdetail+ioffset+j) = matinput[i].row(ioffset+j)*(1-dblend)+ matinput[i+1].row(j)*(dblend);[/align]
[align=left] dblend = dblend +0.01;[/align]
[align=left] }[/align]
[align=left] ioffsetdetail += ioffset;[/align]
[align=left] }[/align]
[align=left] return outImage;[/align]
[align=left]}[/align]
[align=left]#pragma endregion mulitStitch[/align]

在最新版的opencv中(至少在2.4.5之后),提供了mulitband和feather函数。jsxyhelu认为,总体来说,mulitband是目前最好的融合算法,(paper),在(2007)这篇经典的图像拼接论文中得到引用,需要提及的一点是opencv的stitch函数主要就是基于2007这篇论文实现的,它的算法实现的第一篇引用论文就是2007。当然,好的算法可能用起来比较麻烦,简单的算法也有其适合使用的地方。
。。。。。。pipleline
mulitblend的主要思想是小频率事件大空间划分,大频率事件小空间划分,具体内容参考论文。featherblend就是常见的所谓“羽化”,这里主要考虑工程实现。

首先参考image blander函数
detail::Blender
class detail::Blender
Base class for all blenders.
class CV_EXPORTS Blender
{
public:
virtual ~Blender() {}
enum { NO, FEATHER, MULTI_blend };
static Ptr<Blender> createDefault(int type, bool try_gpu = false);
void prepare(const std::vector<Point> &corners, const std::vector<Size> &sizes);
virtual void prepare(Rect dst_roi);
virtual void feed(const Mat &img, const Mat &mask, Point tl);
virtual void blend(Mat &dst, Mat &dst_mask);
protected:
Mat dst_, dst_mask_;
Rect dst_roi_;
};

在detail空间中存在blender函数,是所有blender的基函数。可以实现的包括feather和multiblend两种方法。

[align=left] blender = Blender::createDefault(blend_type, try_gpu);是创建函数,两个参数决定了采用哪一种blender方法,和是否采用gpu[/align]
[align=left] [/align]
[align=left] [/align]

[align=left]detail::Blender::prepare[/align]

为blend准备相关数据
C++: void detail::Blender::prepare(const std::vector<Point>& corners, const std::vector<Size>&
sizes)
Parameters
corners – 原始图像文件的左上角点
sizes – 原始文件大小
[align=left]注意这里的两点都是vector[/align]
[align=left] [/align]
[align=left]detail::Blender::feed
处理图像
C++: void detail::Blender::feed(const Mat& img, const Mat& mask, Point tl)
Parameters
img –原始图像
mask – mask[/align]
[align=left]tl topleft点[/align]
[align=left]注意这里是一张一张处理图像的[/align]
[align=left] [/align]
[align=left]detail::Blender::blend
处理blend操作,是最后最后输出操作 ,从blend结构体中返回pano全景图像了
C++: void detail::Blender::blend(Mat& dst, Mat& dst_mask)
Parameters
dst – Final pano
dst_mask – Final pano mask[/align]
[align=left] [/align]
[align=left]detail::MultiBandBlender
class detail::MultiBandBlender : public detail::Blender
Blender which uses multi-band blending algorithm (see [BA83],就是前面提到的那篇论文).
class CV_EXPORTS MultiBandBlender : public Blender
{
public:
MultiBandBlender(int try_gpu = false, int num_bands = 5);
int numBands() const { return actual_num_bands_; }
void setNumBands(int val) { actual_num_bands_ = val; }[/align]
[align=left]void prepare(Rect dst_roi);
void feed(const Mat &img, const Mat &mask, Point tl);
void blend(Mat &dst, Mat &dst_mask);
private:
/* hidden */
};
See also:
detail::Blender[/align]
[align=left] [/align]
[align=left]detail::FeatherBlender
class detail::FeatherBlender : public detail::Blender
Simple blender which mixes images at its borders.
class CV_EXPORTS FeatherBlender : public Blender
{
public:
FeatherBlender(float sharpness = 0.02f) { setSharpness(sharpness); }
float sharpness() const { return sharpness_; }
void setSharpness(float val) { sharpness_ = val; }
void prepare(Rect dst_roi);
void feed(const Mat &img, const Mat &mask, Point tl);
void blend(Mat &dst, Mat &dst_mask);
// Creates weight maps for fixed set of source images by their masks and top-left corners.
// Final image can be obtained by simple weighting of the source images.
Rect createWeightMaps(const std::vector<Mat> &masks, const std::vector<Point> &corners,
std::vector<Mat> &weight_maps);
private:
/* hidden */
};
See also:
detail::Blender[/align]
[align=left]这两个函数在文档中都没有详细的解释。这里进行补充说明。[/align]
[align=left]基于cookbook第9章的estimateH.cpp继续前进[/align]
[align=left]将其cv::Mat image1= cv::imread( "parliament1.bmp",1);[/align]
[align=left] cv::Mat image2= cv::imread( "parliament2.bmp",1);[/align]
[align=left]结果没有问题,拼接的出来了,但是缝合线也非常明显[/align]
[align=left] [/align]
[align=left]将不需要的代码注释掉,需要注意的是,书中的代码认为图片是从右向左移动的[/align]

[align=left]//需要a注意a的?一?点?是?,?原-始?文?件t的?图?片?是?按照?从右至左边?进?行D移?动的?。[/align]
[align=left] cv::Point* p1 = new cv::Point(image1.cols,1);[/align]
[align=left] cv::Point* p2 = new cv::Point(image1.cols,image2.rows-1);[/align]
[align=left] cv::line(result,*p1,*p2,cv::Scalar(255,255,255),2);[/align]
[align=left] cv::namedWindow( "After warping0");[/align]
[align=left] cv::imshow( "After warping0",result);[/align]
[align=left]画出一条白线,基本标注位置[/align]
[align=left] [/align]
[align=left] [/align]

[align=left]cv::Mat result;[/align]
[align=left] cv::warpPerspective(image1, // input image[/align]
[align=left] result, // output image[/align]
[align=left] homography, // homography[/align]
[align=left] cv::Size(2*image1.cols,image1.rows)); // size of output image[/align]
[align=left] cv::Mat resultback;[/align]
[align=left] result.copyTo(resultback);[/align]
[align=left] [/align]
[align=left] // Copy image 1 on the first half of full image[/align]
[align=left] cv::Mat half(result,cv::Rect(0,0,image2.cols,image2.rows));[/align]
[align=left] image2.copyTo(half);[/align]
[align=left] // Display the warp image[/align]
[align=left] cv::namedWindow( "After warping");[/align]
[align=left] cv::imshow( "After warping",result);[/align]
[align=left] //需要a注意a的?一?点?是?,?原-始?文?件t的?图?片?是?按照?从右至左边?进?行D移?动的?。[/align]
[align=left]// cv::Point* p1 = new cv::Point(image1.cols,1);[/align]
[align=left]// cv::Point* p2 = new cv::Point(image1.cols,image2.rows-1);[/align]
[align=left]// cv::line(result,*p1,*p2,cv::Scalar(255,255,255),2);[/align]
[align=left]// cv::namedWindow("After warping0");[/align]
[align=left]// cv::imshow("After warping0",result);[/align]
[align=left] //进?行Dliner的?融合?[/align]
[align=left] Mat outImage; //待y输?出?图?片?[/align]
[align=left] result.copyTo(outImage); //图?像?拷?贝[/align]
[align=left] double dblend = 0.0;[/align]
[align=left] int ioffset =image2.cols-100;//col的?初?始?定位?[/align]
[align=left] for (int i = 0;i<100;i++)[/align]
[align=left] { [/align]
[align=left] outImage.col(ioffset+i) = image2.col(ioffset+i)*(1-dblend) + resultback.col(ioffset+i)*dblend;[/align]
[align=left] dblend = dblend +0.01;[/align]
[align=left] }[/align]
[align=left]需要注意的是这里不是将image1和image2进行融合,而是将原始的result和image进行融合。[/align]

由于背景比较单一,而且图片分辨率不是很高,所以这个结果融合的 结果非常不




[align=left] [/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: