图像拼接(八):拼接多幅图像+Matlab实现+StanfordOpenCourse

图像拼接(⼋):拼接多幅图像+Matlab实现+StanfordOpenCourse
本博客与以下⽂档资料⼀起服⽤效果更佳。
Matlab源码地址:
开始正⽂。
梳理⼀下本篇博客图像拼接的原理:
特征检测:SIFT⾓点检测
特征描述:SIFT描述⼦
特征匹配:暴⼒搜索+欧⽒距离
求变换矩阵:最⼩⼆乘法+RANSAC+仿射变换
拼接多幅图像
完整实现⼀个SIFT都很⿇烦,也并没必要。本博客是在斯坦福⼤学计算机视觉课程⼤作业的基础上实现的,读者也可以按课程PPT及作业pdf指导书,⾃⼰实现⼀遍,定会加深⾃⼰对其中关键算法的理解。
本博客根据其作业指导书,展⽰其中⼀些算法的Matlab代码实现。
<;译>
#1.引⽂
全景拼接是计算机视觉领域取得的⼀项早期成就。在2007年,Brown 和 Lowe发表了著名的图像拼接论⽂。⾃打那以后,⾃动全景拼接技术受到⼴泛应⽤,例如Google街景地图、智能⼿机上的全景照⽚、拼接软件⽐如Photosynth和AutoStitch。
在这个⼤作业中,我们会从多幅图像中匹配SIFT关键点,来构建单幅全景图⽚。这涉及以下任务:
使⽤⾼斯差分(DoG)检测器关键点,返回它的坐标位置和尺度。(这⼀步已经提供给你)
给⼀副图像的每个关键点构建SIFT描述⼦。
从两幅不同的图像中⽐较两组SIFT描述⼦,到匹配点。
给定⼀个关键点匹配的列表,使⽤最⼩⼆乘法到仿射变换矩阵,这个矩阵能将iamge1上的位置映射到image2上的位置。
使⽤RANSAC使仿射变换矩阵的估计具有更好的鲁棒性。
给定变换矩阵,使⽤它变换(平移、尺度、或者倾斜)image1,将它覆盖到image2上⾯,构建⼀个全景图。(这⼀步已经提供给你)
在真实世界场景中的特定例⼦中,把多幅图像拼接在⼀起。
<;译>
#2.构建SIFT描述⼦
复习SIFT算法的讲义PPT,编写给定的SIFTDescriptor.m,来为每个DoG关键点,产⽣SIFT关键点描述⼦。注意关键点的位置和尺度已经提供给你,使⽤的是⾼斯⾦字塔。
运⾏提供的EvaluateSIFTDescriptor.m,检查你的实现。
防摔玻璃杯这⼀步需要⾃⼰写的代码包括计算图像导数(x和y⽅向)、梯度(⼤⼩和⽅向)、计算邻域块的主⽅向、每个采样点的梯度相对⽅向、计算直⽅图的变量(⽅向箱⼦的划分,每个箱⼦的幅值)、计算梯度直⽅图以及将其串接进⼀个1*128的数组中。
代码提供了标准的结果数据和测试代码,经过测试,我编写的SIFT与标准数据偏差明显。
注:感谢yuanyuan12222的评论指正。出现偏差的原因是:主⽅向选取没有向下取(308⾏注释有说明),将312⾏代码direction
=2pi loc(1)/num_bins;改为direction =2pi(loc(1)-1)/num_bins;就OK了。
说明我的某部分实现不符合标准实现。但由最后的拼接效果来看,实现是可⽤的。
我的实现(Matlab代码):
SIFTDescriptor.m
tomgrofunction descriptors = SIFTDescriptor(pyramid, keyPtLoc, keyPtScale)
% SIFTDescriptor Build SIFT descriptors from image at detected key points'
% location with detected key points' scale and angle
%
% INPUT:
%  pyramid: Image pyramid. pyramid{i} is a rescaled version of the
%            original image, in grayscale double format
%
%  keyPtLoc: N * 2 matrix, each row is a key point pixel location in
%  pyramid{round(keyPtScale)}. So pyramid{round(keyPtScale)}(y,x) is the center of the keypoint
%
%  keyPtScale: N * 1 matrix, each entry holds the index in the Gaussian
%  pyramid for the keypoint. Earlier code interpolates things, so this is a
%  double, but we'll just round it to an integer.
红外焦平面探测器
%
% OUTPUT:
%  descriptors: N * 128 matrix, each row is a feature descriptor
%
% Precompute the gradients at all pixels of all pyramid scales
% This is a cell array, which is like an ArrayList that holds matrices.
% You use {} to index into it, like this: magnitude = grad_mag{1}
grad_theta = cell(length(pyramid),1);
grad_mag = cell(length(pyramid),1);
for scale = 1:length(pyramid)
currentImage = pyramid{scale}; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%双层玻璃茶杯
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %                                                                              %
%                                YOUR CODE HERE                                %
%                          Read the doc for filter2.                          %
%                Use with the filter [-1 0 1] to fill in img_dx,              %
%                  and the filter [-1;0;1] to fill in img_dy.                  %
%                    Please use the filter2 'same' option so                  %
%                the result will be the same size as the image.                %
%                                                                              % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%        % gradient image, for gradients in x direction.
img_dx = zeros(size(currentImage));
img_dx=filter2([-1 0 1],currentImage);
% gradients in y direction.
img_dy = zeros(size(currentImage));
img_dy=filter2([-1;0;1],currentImage);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %                                                                              %
%                              END OF YOUR CODE                              %
%                                                                              % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %                                                                              %
%                                YOUR CODE HERE                                %
%                Use img_dx and img_dy to compute the magnitude                %
%                  and angle of the gradient at each pixel.                  %
%      store them in grad_mag{scale} and grad_theta{scale} respectively.      %
%          The atan2 function will be helpful for calculating angle          %
%                                                                              % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%        % Calculate the magnitude and orientation of the gradient.
grad_mag{scale} = zeros(size(currentImage));
grad_theta{scale} = zeros(size(currentImage));
grad_mag{scale}=sqrt(img_dx.^2+img_dy.^2);
grad_theta{scale}=atan2(img_dy,img_dx);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %                                                                              %
%                              END OF YOUR CODE                              %
%                                                                              % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%        % atan2 gives angles from -pi to pi. To make the histogram code
% easier, we'll change that to 0 to 2*pi.
grad_theta{scale} = mod(grad_theta{scale}, 2*pi);
end
% The number of bins into which each gradient vector will be placed.
num_angles = 8;
% The patch extracted around each keypoint will be divided into a grid
% of num_histograms x num_histograms.
num_histograms = 4;
% Each histogram covers an area "pixelsPerHistogram" wide and tall
pixelsPerHistogram = 4;
% For each keypoint we will extract a region of size
% patch_size x patch_size centered at the keypoint.
patch_size = num_histograms * pixelsPerHistogram;
% Number of keypoints that were found by the DoG blob detector
N = size(keyPtLoc, 1);
% Initialize descriptors to zero
descriptors = zeros(N, num_histograms * num_histograms * num_angles);
% Iterate over all keypoints
for i = 1 : N
scale = round(keyPtScale(i));
% Find the window of pixels that contributes to the descriptor for the
% current keypoint.
xAtScale = keyPtLoc(i, 1);%center of the DoG keypoint in the pyramid{2} image
yAtScale = keyPtLoc(i, 2);
x_lo = round(xAtScale - patch_size / 2);
x_hi = x_lo+patch_size-1;
y_lo = round(yAtScale - patch_size / 2);
y_hi = y_lo+patch_size-1;
% These are the gradient magnitude and angle images from the
% These are the gradient magnitude and angle images from the
% correct scale level. You computed these above.
magnitudes = grad_mag{scale};
thetas = grad_theta{scale};
try
母线夹% Extract the patch from that window around the keypoint
patch_mag = zeros(patch_size,patch_size);
patch_theta = zeros(patch_size,patch_size);
patch_mag = magnitudes(y_lo:y_hi,x_lo:x_hi);
patch_theta = thetas(y_lo:y_hi,x_lo:x_hi);
catch err
% If any keypoint is too close to the boundary of the image
% then we just skip it.
continue;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %                                                                              %
%                              YOUR CODE HERE:                                %
%                                                                              %
%  Express gradient directions relative to the dominant gradient direction    %
%                              of this keypoint.                              %
%                                                                              %
%            HINT: Use the ComputeDominantDirection function below.            %
%                                                                              % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%        % Step 1: compute the dominant gradient direction of the patch
patch_angle_offset = ComputeDominantDirection(patch_mag, patch_theta);
% Step 2: change patch_theta so it's relative to the dominant direction
patch_theta = patch_theta-patch_angle_offset;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %                                                                              %
%                              END OF YOUR CODE                                %
%                                                                              % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This line will re-map patch_theta into the range 0 to 2*pi
patch_theta = mod(patch_theta, 2*pi);
% Weight the gradient magnitudes using a gaussian function
patch_mag = patch_mag .* fspecial('gaussian', patch_size, patch_size / 2);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %                                                                              %
%                            YOUR CODE HERE:                                  %
%                                                                              %
%        Compute the gradient histograms and concatenate them in the          %
%  feature variable to form a size 1x128 SIFT descriptor for this keypoint.    %
%                                                                              %
%            HINT: Use the ComputeGradientHistogram function below.            %
%                                                                              % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%        % The patch we have extracted should be subdivided into
% num_histograms x num_histograms cells, each of which is size
% pixelsPerHistogram x pixelsPerHistogram.
% Compute a gradient histogram for each cell, and concatenate
% the histograms into a single feature vector of length 128.
% Please traverse the patch row by row, starting in the top left,
% in order to match the given solution. E.g. if you use two
% nested 'for' loops, the loop over x should  be the inner loop.
% (Note: Unlike the SIFT paper, we will not smooth a gradient across
% nearby histograms. For simplicity, we will just assign all
% gradient pixels within a pixelsPerHistogram x pixelsPerHistogram
% square to the same histogram.)
% Initializing the feature vector to size 0. Hint: you can
% concatenate the histogram descriptors to it like this:
% feature = [feature, histogram]
feature = [];
subdivided_patch_theta=zeros(pixelsPerHistogram,pixelsPerHistogram);
subdivided_patch_mag=zeros(pixelsPerHistogram,pixelsPerHistogram);
for y=1:4:13
for x=1:4:13
subdivided_patch_theta=patch_theta(y:y+3,x:x+3);
subdivided_patch_mag=patch_mag(y:y+3,x:x+3);
[histogram,angles]=ComputeGradientHistogram(num_angles,subdivided_patch_mag,subdivided_patch_theta);
feature=[feature,histogram];
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %                                                                              %
%                                END YOUR CODE                                %
%                                                                              % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Add the feature vector we just computed to our matrix of SIFT
% descriptors.
descriptors(i, :) = feature;
end
% Normalize the descriptors.
descriptors = NormalizeDescriptors(descriptors);
end
function [histogram, angles] = ComputeGradientHistogram(num_bins, gradient_magnitudes, gradient_angles)
% Compute a gradient histogram using gradient magnitudes and directions.
% Each point is assigned to one of num_bins depending on its gradient
% direction; the gradient magnitude of that point is added to its bin.
%
% INPUT
% num_bins: The number of bins to which points should be assigned.
% gradient_magnitudes, gradient angles:
%      Two arrays of the same shape where gradient_magnitudes(i) and
%      gradient_angles(i) give the magnitude and direction of the gradient
%      for the ith point. gradient_angles ranges from 0 to 2*pi
%
% OUTPUT
% histogram: A 1 x num_bins array containing the gradient histogram. Entry 1 is
%      the sum of entries in gradient_magnitudes whose corresponding
%      gradient_angles lie between 0 and angle_step. Similarly, entry 2 is for
%      angles between angle_step and 2*angle_step. Angle_step is calculated as
背光驱动
%      2*pi/num_bins.
% angles: A 1 x num_bins array which holds the histogram bin lower bounds.
%      In other words, histogram(i) contains the sum of the
%      gradient magnitudes of all points whose gradient directions fall
%      in the range [angles(i), angles(i + 1))
angle_step = 2 * pi / num_bins;

本文发布于:2024-09-23 13:25:06,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/3/227419.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:实现   拼接   关键点   图像   矩阵   匹配
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议