implicitly declaring library_no such object available

implicitly declaring library_no such object availableAPAP论文源码中全局单应GH的部分!

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺


前言

论文及源码地址:APAP项目入口
论文精读:【论文精读】As-Projective-As-Possible Image Stitching with Moving DLT

源码用的MDLT code,解压后的文件夹是mdlt
注意,matlab是基于向量优先的!
让我们从main.m开始!

准备工作与全局变量

比较高版本的matlab需要将多线程部分改成如下代码

%poolsize = matlabpool('size');
poolsize = parpool('local');
if poolsize == 0 %if not, we attempt to do it:
    parpool open;
end

全局变量如下,fitfn等是准备好的求全局单应的函数,在文件夹modelspecific中,C1,C2是网格数

%-------------------------
% User defined parameters.
%-------------------------
% Global model specific function handlers.
clear global;
global fitfn resfn degenfn psize numpar
fitfn = 'homography_fit';
resfn = 'homography_res';
degenfn = 'homography_degen';
psize   = 4;
numpar  = 9;

M     = 500;  % Number of hypotheses for RANSAC.
thr   = 0.1;  % RANSAC threshold.

C1 = 100; % Resolution/grid-size for the mapping function in MDLT (C1 x C2).
C2 = 100;

gamma = 0.1; % Normalizer for Moving DLT. (0.0015-0.1 are usually good numbers).
sigma = 8.5;  % Bandwidth for Moving DLT. (Between 8-12 are good numbers).   
scale = 1;    % Scale of input images (maybe for large images you would like to use a smaller scale).

基于全局单应的图像拼接过程

1.读入图像,特征点检测与匹配

采用原作者注释掉的读取自己输入的两张图片形式,具体代码细节及思想见代码注释,下同。

%------------------
% Images to stitch.
%------------------
path1 = 'images/case26/6.JPG';
path2 = 'images/case26/7.JPG';
%-------------
% Read images.
%-------------
fprintf('Read images and SIFT matching\n');tic;
fprintf('> Reading images...');tic;
img1 = imresize(imread(sprintf('%s',path1)),scale);
img2 = imresize(imread(sprintf('%s',path2)),scale);
fprintf('done (%fs)\n',toc);
%--------------------------------------
% SIFT keypoint detection and matching.
%--------------------------------------
fprintf('  Keypoint detection and matching...');tic;
%single(rgb2gray(img1))将img1转换成单精度灰度图,sift固定格式,必须是单精度的
%'PeakThresh':DoG算法的阈值,值越小,检测到的特征点越多
%'edgethresh':消除DoG尺度空间峰值,值越大,检测到的特征点越多
%kp每一列是一个四元组[x,y,s,th],代表一个特征点信息,分别x,y坐标,s为长度空间大小,th指的是主方向
%ds是特征描述子,也就是那个128维的向量,128×特征点数的矩阵
[ kp1,ds1 ] = vl_sift(single(rgb2gray(img1)),'PeakThresh', 0,'edgethresh',500);
[ kp2,ds2 ] = vl_sift(single(rgb2gray(img2)),'PeakThresh', 0,'edgethresh',500);
%vl_ubcmatch:欧式距离匹配,返回匹配矩阵和匹配对间距离
%[matches, scores] = vl_ubcmatch(ds1, ds2) ;
%matches返回的是2*特征点数量矩阵,
%第一行是一幅图中的匹配点索引,第二行是另一幅图匹配点索引
%每一列是一个匹配点对索引,scores是距离
matches   = vl_ubcmatch(ds1,ds2);
fprintf('done (%fs)\n',toc);

2.数据归一化,RANSAC剔除异常值

% Normalise point distribution.
% 数据归一化的作用是方便后面RANSAC剔除错误点,消除干扰,提高精度,简化计算
fprintf('  Normalising point distribution...');tic;
%matches(1,:):匹配点第一行索引
%matches(2,:):另一张图中的匹配点索引
%kp1(1:2,matches(1,:)):提取出匹配点索引的对应横纵坐标
%size(matches,2):取matches的第二维也就是列,共482列,也就是匹配点数目
%ones(1,size(matches,2)):生成1×4821矩阵
%data_orig是6×482,每个列是两个点的[x y 1]
data_orig = [ kp1(1:2,matches(1,:)) ; ones(1,size(matches,2)) ; kp2(1:2,matches(2,:)) ; ones(1,size(matches,2)) ];
%T矩阵为3×3矩阵
%normalise2dpts作用:把一系列的齐次坐标[x y 1]归一化,使得这些点以原点为中心,距离原点均值为sqrt(2)[ dat_norm_img1,T1 ] = normalise2dpts(data_orig(1:3,:));
[ dat_norm_img2,T2 ] = normalise2dpts(data_orig(4:6,:));
%data_norm:6*482
data_norm = [ dat_norm_img1 ; dat_norm_img2 ];
fprintf('done (%fs)\n',toc);
% %展示输入图像
% if size(img1,1) == size(img2,1)    
%     % Show input images.
%     fprintf(' Showing input images...');tic;
%     figure;
%     imshow([img1,img2]);
%     title('Input images');
%     fprintf('done (%fs)\n',toc);
% end
%-----------------
% Outlier removal.前半部分没读懂代码 mutigs文件夹里有该函数
%-----------------
fprintf('Outlier removal\n');tic;
% Multi-GS
%设置随机种子,rand('state',0),相当于C++中的srand(0)
rng(0);
[ ~,res,~,~ ] = multigsSampling(100,data_norm,M,10);
con = sum(res<=thr);
[ ~, maxinx ] = max(con);
%找到匹配度最高的特征点序列,inliers存的是匹配对的索引
inliers = find(res(:,maxinx)<=thr);
if size(img1,1) == size(img2,1)
% Show results of RANSAC.
fprintf(' Showing results of RANSAC...');tic;
figure;
imshow([img1 img2]);
%添加新绘图保持原绘图
hold on;
%ro是形状:红圈,LineWidth线宽为2
%data_orig前两行是一个图的匹配点,用红圈画,45行是另一个图的点,红圈画
plot(data_orig(1,:),data_orig(2,:),'ro','LineWidth',2);
%+size(img1,2)为了让它在第二张图位置显示
plot(data_orig(4,:)+size(img1,2),data_orig(5,:),'ro','LineWidth',2);
for i=1:length(inliers)
%选择对应内点索引的坐标,12行是一幅图,45行是另一幅图,绿圈画
plot(data_orig(1,inliers(i)),data_orig(2,inliers(i)),'go','LineWidth',2);
plot(data_orig(4,inliers(i))+size(img1,2),data_orig(5,inliers(i)),'go','LineWidth',2);
%14行对应横坐标矩阵,25行对应纵坐标矩阵,绿线相连
plot([data_orig(1,inliers(i)) data_orig(4,inliers(i))+size(img1,2)],[data_orig(2,inliers(i)) data_orig(5,inliers(i))],'g-');
end
title('Ransac''s results');
fprintf('done (%fs)\n',toc);
end

3.计算全局单应,获取拼接图大小,拼接

%-----------------------
% Global homography (H).计算全局单应
%-----------------------
fprintf('DLT (projective transform) on inliers\n');
% Refine homography using DLT on inliers.
fprintf('> Refining homography (H) using DLT...');tic;
%feval调用参数中fitfn函数,参数为data_norm(:,inliers),即归一化后数据内点索引所在的列
[ h,A,D1,D2 ] = feval(fitfn,data_norm(:,inliers));
%上一步处理之后要再处理回去
Hg = T2\(reshape(h,3,3)*T1);%Hg是全局单应矩阵
fprintf('done (%fs)\n',toc);
%----------------------------------------------------
% Obtaining size of canvas (using global Homography).
%----------------------------------------------------
fprintf('Canvas size and offset (using global Homography)\n');
fprintf('> Getting canvas size...');tic;
%获得拼接图大小,左图不变,右图单应变换
% Map four corners of the right image.
%由于求得的H 是将左图映射到右图,
%即 H*x_left = x_right,所以 x_left = inv(H) * x_right.
%取右图的四个顶点的齐次坐标 分别作为 x_right 的值
%以img1左顶点为坐标源点,得到新的四个顶点坐标:TL, BL, TR, BR
TL = Hg\[1;1;1];%inv(Hg)*[1;1;1], 得到非齐次形式
TL = round([ TL(1)/TL(3) ; TL(2)/TL(3) ]);% 齐次化!
BL = Hg\[1;size(img2,1);1];
BL = round([ BL(1)/BL(3) ; BL(2)/BL(3) ]);
TR = Hg\[size(img2,2);1;1];
TR = round([ TR(1)/TR(3) ; TR(2)/TR(3) ]);
BR = Hg\[size(img2,2);size(img2,1);1];
BR = round([ BR(1)/BR(3) ; BR(2)/BR(3) ]);
% Canvas size.确定画布的尺寸(cw, ch)
% 投影面的 宽,通过最大的x()-最小的x()+1
cw = max([1 size(img1,2) TL(1) BL(1) TR(1) BR(1)]) - min([1 size(img1,2) TL(1) BL(1) TR(1) BR(1)]) + 1;
% 投影面的 高
ch = max([1 size(img1,1) TL(2) BL(2) TR(2) BR(2)]) - min([1 size(img1,1) TL(2) BL(2) TR(2) BR(2)]) + 1;
fprintf('done (%fs)\n',toc);
% Offset for left image.确定左图的偏移量off,即左图img1 左顶点 在画布坐标系中的 坐标
fprintf('> Getting offset...');tic;
off = [ 1 - min([1 size(img1,2) TL(1) BL(1) TR(1) BR(1)]) + 1 ; 1 - min([1 size(img1,1) TL(2) BL(2) TR(2) BR(2)]) + 1 ];
fprintf('done (%fs)\n',toc);
%--------------------------------------------
% Image stitching with global homography (H).
%--------------------------------------------
% Warping source image with global homography 
fprintf('Image stitching with global homography (H) and linear blending\n');
fprintf('> Warping images by global homography...');tic;
%创建一个拼接图的空画布
warped_img1 = uint8(zeros(ch,cw,3));
%将左图按照左图偏移off放到画布上
warped_img1(off(2):(off(2)+size(img1,1)-1),off(1):(off(1)+size(img1,2)-1),:) = img1;
%调用imagewarping.cpp,实现warp
warped_img2 = imagewarping(double(ch),double(cw),double(img2),Hg,double(off));
%c++中维度变了,变回matlab所需维度
warped_img2 = reshape(uint8(warped_img2),size(warped_img2,1),size(warped_img2,2)/3,3);
fprintf('done (%fs)\n',toc);

在这之后我添加了单张图放在画布上的结果,以及融合之前的结果

%--------------------------------------------
% 显示单独放在画布上的两张图和融合前的拼接图
%--------------------------------------------
%得到的warped_img1,warped_img2是单独放在整个画布上的
figure;
imshow(warped_img1);
title('warpedimg1');
figure;
imshow(warped_img2);
title('warpedimg2');
output_canvas(:,:,1) = warped_img1(:,:,1)+warped_img2(:,:,1);
output_canvas(:,:,2) = warped_img1(:,:,2)+warped_img2(:,:,2);
output_canvas(:,:,3) = warped_img1(:,:,3)+warped_img2(:,:,3);
output_canvas = uint8(output_canvas);
figure;
imshow(output_canvas);
title('output_canvas');

融合前的效果:
在这里插入图片描述
可见融合是为了消除两张拼接图光照不同的影响。

4.加权融合

% Blending images by simple average (linear blending)
fprintf('  Homography linear image blending (averaging)...');tic;
linear_hom = imageblending(warped_img1,warped_img2);
fprintf('done (%fs)\n',toc);
figure;
imshow(linear_hom);
title('Image Stitching with global homography');

imageblending.m:

function output_canvas = imageBlending(warped_img1,warped_img2)
%本函数作用:加权平均融合
%将输入warp图形二值化并填充孔
w1 = imfill(im2bw(uint8(warped_img1), 0),'holes');
w2 = imfill(im2bw(uint8(warped_img2), 0),'holes');
%转换为灰度图
w1 = mat2gray(w1);
w2 = mat2gray(w2);
%注意转换类型
%matlab处理图像一定先将图像转换为double,im2double
%1 有些函数支持double型,而不支持uint8的数据类型,所以要转换
%2 精度问题了,因为uint8进行数据处理的时候,容易造成数据溢出或精度不够。
warped_img1 = double(warped_img1);
warped_img2 = double(warped_img2);
%每个维度根据两张图的二值化灰度图进行融合,主要是处理两张图亮度不同
%注意都是矩阵运算: .*,./ 点乘点除
output_canvas(:,:,1) = ((warped_img1(:,:,1).*w1)+(warped_img2(:,:,1).*w2))./(w1+w2);
output_canvas(:,:,2) = ((warped_img1(:,:,2).*w1)+(warped_img2(:,:,2).*w2))./(w1+w2);
output_canvas(:,:,3) = ((warped_img1(:,:,3).*w1)+(warped_img2(:,:,3).*w2))./(w1+w2);
%最后转换回uint8
output_canvas = uint8(output_canvas);

融合之后的结果:
在这里插入图片描述
消除了光照带来的影响,但是没对齐。

总结

本章讲述了用matlab实现全局单应Global homography的过程及源码分析,本章并不算论文APAP中的部分,而是用来对比APAP方法的优点的,那么我们将在下一章重点讲解APAP的实现原理及过程,欢迎对图像拼接领域的感兴趣的朋友们讨论!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/190475.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • QCustomPlot使用手册(一)

    QCustomPlot使用手册(一)QCustomPlot是一个基于Qt的画图和数据可视化C++控件。QCustomPlot致力于提供美观的界面,高质量的2D画图、图画和图表,同时为实时数据可视化应用提供良好的解决方案。

    2022年10月16日
  • Java 生成 UUID[通俗易懂]

    Java 生成 UUID[通俗易懂]1.UUID简介UUID含义是通用唯一识别码(UniversallyUniqueIdentifier),这是一个软件建构的标准。也是被开源软件基金会(OpenSoftwareFou

  • 非常好的Ansible入门教程(超简单)

    非常好的Ansible入门教程(超简单)Ansible是一个配置管理和配置工具,类似于Chef,Puppet或Salt。这是一款很简单也很容易入门的部署工具,它使用SSH连接到服务器并运行配置的任务,服务器上不用安装任何多余的软件,只需要开启ssh,所有工作都交给client端的ansible负责。关于Ansible的一个好处是,将bash脚本转换为可执行任务是非常容易的。我们可以编写自己的配置程序,但是Ansible更加干净,因为它

  • codeblocks批量注释快捷键_vue多行注释快捷键

    codeblocks批量注释快捷键_vue多行注释快捷键ctrl+shift+c:注释多行ctrl+shift+x:取消多行注释,当然,也可以注释一行哦!

  • bs模型与cs模型共同点_bs模型的基本假设

    bs模型与cs模型共同点_bs模型的基本假设bs模式客户端通过浏览器,浏览web服务器上的网页,这样的模型叫bs模型,b指客户端browser,s指服务端server。在客户端和浏览器端之间走的报文是http协议(即超文本传输协议) cs模型客户端(client)发报文,服务器(server)收报文,服务器收到报文之后处理。这与bs模式没有很大区别,只不过是c与s间可以自定义数据传送报文。cs模式一般走的协议是tcp协议

  • mapminmax 用法「建议收藏」

    mapminmax 用法「建议收藏」mapminmax是MATLAB实现归一化的工具包,默认:(1)将矩阵的每行分别进行归一化;(2)每行的最大值最小值作为每行归一化的xmin和xmax;(3)将数据归一化到[-1,1].若要将数据归一化到0到1之间,即y∈[0,1],使用b=mapminmax(a,0,1);若给与确定的最大值和最小值作为每行的xmin和xmax,使用:b= mapminmax(a,0,1);PS.xmin…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号