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

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

为blend准备相关数据
C++: void detail::Blender::prepare(const std::vector<Point>& corners, const std::vector<Size>&
sizes)
Parameters
corners – 原始图像文件的左上角点
sizes – 原始文件大小

注意这里的两点都是vector
 
detail::Blender::feed
处理图像
C++: void detail::Blender::feed(const Mat& img, const Mat& mask, Point tl)
Parameters
img –原始图像
mask – mask
tl topleft点
注意这里是一张一张处理图像的
 
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
 
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; }
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
 
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
这两个函数在文档中都没有详细的解释。这里进行补充说明。
基于cookbook第9章的estimateH.cpp继续前进
将其cv::Mat image1= cv::imread( "parliament1.bmp",1);
                cv::Mat image2= cv::imread( "parliament2.bmp",1);
结果没有问题,拼接的出来了,但是缝合线也非常明显
 
将不需要的代码注释掉,需要注意的是,书中的代码认为图片是从右向左移动的
//需要a注意a的一点是,原-始文件t的图片是按照从右至左边进行D移动的。
                cv::Point* p1 = new cv::Point(image1.cols,1);
                cv::Point* p2 = new cv::Point(image1.cols,image2.rows-1);
                cv::line(result,*p1,*p2,cv::Scalar(255,255,255),2);
                cv::namedWindow( "After warping0");
                cv::imshow( "After warping0",result);
画出一条白线,基本标注位置
 
 
cv::Mat result;
                cv::warpPerspective(image1, // input image
                                result,                                      // output image
                                homography,                         // homography
                                cv::Size(2*image1.cols,image1.rows)); // size of output image
                cv::Mat resultback;
                result.copyTo(resultback);
 
                 // Copy image 1 on the first half of full image
                cv::Mat half(result,cv::Rect(0,0,image2.cols,image2.rows));
                image2.copyTo(half);
    // Display the warp image
                cv::namedWindow( "After warping");
                cv::imshow( "After warping",result);
                 //需要a注意a的一点是,原-始文件t的图片是按照从右至左边进行D移动的。
//             cv::Point* p1 = new cv::Point(image1.cols,1);
//             cv::Point* p2 = new cv::Point(image1.cols,image2.rows-1);
//             cv::line(result,*p1,*p2,cv::Scalar(255,255,255),2);
//             cv::namedWindow("After warping0");
//             cv::imshow("After warping0",result);
                 //进行Dliner的融合
                Mat outImage; //待y输出图片
                result.copyTo(outImage); //图像拷贝
                 double dblend = 0.0;
                 int ioffset =image2.cols-100;//col的初始定位
                 for (int i = 0;i<100;i++)
                {              
                                outImage.col(ioffset+i) = image2.col(ioffset+i)*(1-dblend) + resultback.col(ioffset+i)*dblend;
                                dblend = dblend +0.01;
                }
需要注意的是这里不是将image1和image2进行融合,而是将原始的result和image进行融合。
由于背景比较单一,而且图片分辨率不是很高,所以这个结果融合的 结果非常不
 

使用liner、feather、multiband对已经拼接的数据进行融合的更多相关文章

  1. 使用liner、feather、multiband对已经拼接的数据进行融合(下)

    理解mulitband.所谓的mulitband,其实就是一种多尺度的样条融合,其实现的主要方法就是laplace金字塔. 高斯金字塔是向下采样,而laplace金字塔式向上采样(也就是恢复),采用的 ...

  2. 关于json动态拼接响应数据

    在EasyUI http://www.jeasyui.com/demo/main/get_users.php 响应数据如下格式: { "total": "11" ...

  3. 使用concat做字符串拼接和数据迁移

    作用: 解决一开始数据库建立不合理造成的字段冗余,从而提取部分字段,数据迁移.拼接字符串的功能. 格式: concat(字段1,'间隔符',字段2....) concat_ws('间隔符',字段1,字 ...

  4. Python接口测试-以&连接拼接字典数据(get中url请求数据)

    get请求的utl数据是这样的,例如:/banner/findBanner?bannerType=1&_=1556107073181 ''' 1-banner图-banner/findBann ...

  5. python 手动拼接json数据

    第一步:分别拼接为字符串 第二步:将字符串转化为list 第三歩:将两个list合并为dict 第四步:将dict转换为接送数据 如:  import json keys = ['a', 'b', ' ...

  6. udp拼接传递数据包

    1.拼接项少 pl = ["<0112>","<32>","<1024x768>","< ...

  7. sql server full join拼接表数据,按组加序号

    --查询所有数据select A.*,B.* from(select z.id,z.requestId,z.FBillNo,dt5.FCauseAndProcess,dt5.FEquipmentNo, ...

  8. SQL拼接字段数据

    查询语句: SELECT STUFF ( ( SELECT ',' + --分隔符 KeyID --查询字段 FROM #tmp --查询数据表 WITH(NOLOCK) --查询条件 FOR XML ...

  9. Oracle 拼接列数据的方法

    select wm_concat(fphone) phone from dq_phone_ndtbdxz wm_concat(列名):把多列值,合并成一列,用,隔开.

随机推荐

  1. 查询ip

    ifconfig | grep "inet " | grep -v 127.0.0.1

  2. redis系列之数据库与缓存数据一致性解决方案

    redis系列之数据库与缓存数据一致性解决方案 数据库与缓存读写模式策略 写完数据库后是否需要马上更新缓存还是直接删除缓存? (1).如果写数据库的值与更新到缓存值是一样的,不需要经过任何的计算,可以 ...

  3. [INS-20802] Oracle Net Configguration Assistant faild

    Redhat/Centos 安装oracle11gR2时出现以下错误: [INS-20802] Oracle Net Configuration Assistant failed 查看对应日志文件,信 ...

  4. python面向对象高级:定制类

    Python的class中还有许多这样有特殊用途的函数,可以帮助我们定制类. 比如: __str__ 与__repr____iter____getitem____call__ __str__ 与__r ...

  5. debug $mysqli->character_set_name();

    <?php $mysqli = new mysqli('localhost', 'root', '', 'w'); if(mysqli_connect_errno()){ printf('Con ...

  6. flask操作简章

    https://blog.csdn.net/u011054333/article/details/70151857

  7. 【RBAC】打造Web权限控制系统

    引言 权限系统模块对于互联网产品是一个非常重要的功能,可以控制不同的角色合理的访问不同的资源从而达到安全访问的作用 此外本次课程有视频讲解: http://www.imooc.com/learn/79 ...

  8. Dubbo简单环境搭建

    Dubbo服务的发展和作用: 首先,看下一般网站架构随着业务的发展,逻辑越来越复杂,数据量越来越大,交互越来越多之后的常规方案演进历程. 其次,当服务越来越多之后,我们需要做哪些服务治理? 最后,是d ...

  9. PAT Sign In and Sign Out[非常简单]

    1006 Sign In and Sign Out (25)(25 分) At the beginning of every day, the first person who signs in th ...

  10. 申请 Let’s Encrypt 泛域名证书 及 Nginx/Apache 证书配置

    什么是 Let’s Encrypt? 部署 HTTPS 网站的时候需要证书,证书由 CA (Certificate Authority )机构签发,大部分传统 CA 机构签发证书是需要收费的,这不利于 ...