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

所谓"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对已经拼接的数据进行融合

时间: 2024-07-31 03:05:47

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

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

理解mulitband.所谓的mulitband,其实就是一种多尺度的样条融合,其实现的主要方法就是laplace金字塔. 高斯金字塔是向下采样,而laplace金字塔式向上采样(也就是恢复),采用的都是差值的方法.如何能够在金字塔各个层次上面进行图像的融合,结果证明是相当不错的.网络上面流传的一个类解释了这个问题,并且能够拿来用: // GOImage.cpp : 定义? DLL 的?初?始?化例y程. // #include "stdafx.h" #include <iost

004.原始套接字,拼接UDP数据包,通信

大致流程: 建立一个client端,一个server端,自己构建IP头和UDP头,写入数据(hello,world!)后通过原始套接字(SOCK_RAW)将包发出去. server端收到数据后,打印UDP数据并发送确认消息(yes),client收到yes后将其打印. 其中: client端IP:192.168.11.104 端口:8600 server端IP:192.168.11.105 端口:8686 注意事项: 1.运行原始套接字socket需要有root权限. 2.注意主机字节序和网络字

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

作用: 解决一开始数据库建立不合理造成的字段冗余,从而提取部分字段,数据迁移.拼接字符串的功能. 格式: concat(字段1,'间隔符',字段2....) concat_ws('间隔符',字段1,字段2) 数据准备: #创建表 create table employee( id int not null unique auto_increment, name varchar(20) not null, sex enum('male','female') not null default 'ma

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

get请求的utl数据是这样的,例如:/banner/findBanner?bannerType=1&_=1556107073181 ''' 1-banner图-banner/findBanner ''' str1=parse.urlencode(data1) url1='{0}/banner/findBanner?bannerType=1&_=1556107073181'.format(yuming) headers ={'Content-Type':'application/json;

拼接JSON数据

//根据记录表IDRecordID查找所有文件                IList<Model.FILECHANGE_FILE> listFile = cFile.GetList(" where t.RecordID", "");                if (listFile.Count > 0)                {                    //返回JSON数据                    _s

mysql 拼接列数据

SELECT IF(@ids=w.contract_id,@num:[email protected],@num:[email protected]+1) AS num,@ids:=w.contract_id,w.* FROM (SELECT (SELECT GROUP_CONCAT(project_name) FROM production_income_data WHERE contract_id = a.contract_id) AS `names`, (SELECT GROUP_CONC

基于OpenCV进行图像拼接原理解析和编码实现(提纲 代码和具体内容在课件中)

一.背景 1.1概念定义 我们这里想要实现的图像拼接,既不是如题图1和2这样的"图片艺术拼接",也不是如图3这样的"显示拼接",而是实现类似"BaiDU全景"这样的全部的或者部分的实际场景的重新回放. 对于图像拼接的流程有很多定义方式,本教程中主要介绍实现主流方法,总结梳理如下: 图像采集->投影变换->特征点匹配->拼接对准->融合->反投影 图像采集不仅仅指的是普通的图像数据的获取.为了能够拼接过程能够顺利进行.

全景视频拼接(二)--OpenCV源码解析

本文参考:http://blog.csdn.net/skeeee/article/details/19480693,做了一定修改和补充. 一.stitching_detail程序运行流程 1.命令行调用程序,输入源图像以及程序的参数 2.特征点检测,判断是使用surf还是orb,默认是surf. 3.对图像的特征点进行匹配,使用最近邻和次近邻方法,将两个最优的匹配的置信度保存下来. 4.对图像进行排序以及将置信度高的图像保存到同一个集合中,删除置信度比较低的图像间的匹配,得到能正确匹配的图像序列

拼接字符串,生成tree格式的JSON数组

之前做的执法文书的工作,现在需要从C#版本移植到网页版,从Thrift接口获取数据,加载到对应的控件中 之前用的easyui的Tree插件,通过<ul><li><span></span></li></ul>标签的方式生成node树,条理清晰,虽然麻烦点,但是用循环写几行代码就能搞定,但是,在Ajax的函数里面,tree的样式加载不上,显示的格式就是元素自带的含义,<ul>和<li>,无法点击,下面的工作也就无法