图像拼接matlab
作者:互联网
图像拼接
声明
这是我本科期间的数字图像处理大作业,存在一定的问题无法保证一定可以使用。
且此篇文章为我第一次在CSDN上发布,可能存在一定的问题。
同时由于是在本科期间的课程大作业,内容原创性比较少轻喷(主要是将网上的一些和图像拼接有关的内容进行一个整合,这次文章的发布仅为一次实验)。
本篇文章会加入一些我自己的认为与理解,仅代表个人观点,轻喷。
希望不会有啥维权的问题,如果出现本人会删除这篇文章。
网上的几种方法
1.SIFT
2.Surf
3.角点检测
(网上的内容都挺详尽的,建议百度一下)
框图
写了个总的函数,加了点用户输入的部分。
Surf:
Harris:
Coding
function image_stitching(A,B,varargin)
%@Author ;HuangWeiChen
%@Time :2021/5/5
% Input:
% input_A :image 1
% input_B : image 2
% Output:
% output_image - combined new image
%@Note :
%{
1.No return ,show the combined image directly
2.Without the GUI ,the function is stil working .
Because I forget the gui so I do this function better.
That's the reason why has this function .
The main.m is the test file maybe it is a reference,
so i still save it.
%}
%@Power ;1. Detecting the input image is null or not.
% Detecting the image dimension is matching or not
%
% 2.if the input is too big and the use choose the harris,
% it will run a long time ,so I detect the image size.
% When the size is bigger than 2000,I suggest the use to using
% SURF,so I wirte the input code . User choose YES
% --SURF,whether NO --just run the harris
% 3. it will show the Corner point
%
%@TODO :The SURF do only run with gray image. If you want run wiht
% GRB,maybe bulid a new file.
% : harris is too slow!!!!!!!!!!!!!!!!!!!
%%%%%%%%%%%%%%%%%%%%%%%%%
%{
Sample:
addpath('resource');
addpath('Image');
imagePath = 'Image\eyes';
first = 1;
second = 2;
buildingScene = imageSet(imagePath);
A = read(buildingScene, first);
B= read(buildingScene, second);
A = rgb2gray(A);
B = rgb2gray(B);
% These functions you can choose,it big enough(smile)
image_stitching(A,B,'SURF');
% image_stitching(A,B,'SURF','write');
% image_stitching(A,B,'harris');
% image_stitching(A,B);
% image_stitching(A,B,'harris','write');
% image_stitching(A,B,'harris','Corner');
%}
%%%%%%%%%%%%%%%%%%%%%%%%%
%% detect input
if isempty(A)
error('the first image is empty!');
elseif isempty(B)
error('the second image is empty!');
end
Size_A =max(size(A));
Size_B =max(size(B));
dimension_A=numel(size(A));
dimension_B = numel(size(B));
if dimension_B *dimension_A~=9&&dimension_B *dimension_A~=4
error('the input image dimension is not correct,they should have the same dimension');
end
%% image is too big
times = 1;
while(1)
if times ==1
if Size_A>2000||Size_B>2000
prompt={ 'the image is too big,we think you should use SURF, Yes or No' };
name='Warring';
numlines=1;
defaultanswer={'Yes'};
options.Resize='on';
options.WindowStyle='normal';
options.Interpreter='tex';
answer=inputdlg(prompt,name,numlines,defaultanswer,options);
else
flag = -1;
break;
end
else
string = answer;
if string =="Yes"
flag = 1;
break;
elseif string =="No"
flag = -1;
break;
else
disp("Please input the right string!!");
end
end
times =times +1;
end
%% choose a way
if flag == 1
MSURF(A ,B);
else
if nargin == 3
if varargin{1} ~="harris"&&varargin{1} ~="SURF"
error('the first input string is incorrect! ');
elseif varargin{1} =="SURF"
MSURF(A ,B);
elseif varargin{1} =="harris"
[newImage]= Mharris(A,B);
figure('Name',"Harris,3");
imshow(uint8(newImage));
end
elseif nargin == 2
[newImage]= Mharris(A,B);
figure('Name',"Harris,2")
imshow( uint8(newImage));
elseif nargin == 4
if varargin{2}=="write"||varargin{2}=="Corner"
if varargin{2}=="write"
Mwrite = 1;
else
Mwrite = 0;
end
if varargin{2}=="Corner"
Mcorner = 1;
else
Mcorner = 0;
end
else
error('the second input string is incorrect');
end
if varargin{1} ~="harris"&&varargin{1} ~="SURF"
error('the first input string is incorrect! ');
elseif varargin{1} =="SURF"
output = MSURF(A ,B);
if Mwrite ==1 %write
saveas(output,'Output\SURF','png');
elseif Mcorner ==1
error("the SURF don't have the corner points!!");
end
elseif varargin{1} =="harris"
[newImage,R1,R2]= Mharris(A,B,varargin{2});
if Mcorner ==1
figure('Name','Harris 3');
imshow( uint8(newImage));
figure('Name','Corner');
subplot(121);
imshow(R1);
title('First');
subplot(122);
imshow(R2);
title('Second');
elseif Mwrite ==1
figure('Name','Harris write');
imshow( uint8(newImage));
imwrite(uint8(newImage),'Output\Harris.png');
else
error('the input string is bug !!');
end
end
end
end
end
Mharris:
function varargout= Mharris(A,B,varargin)
%% detect 3D
detect_bug = numel(size(A))*numel(size(B));
if detect_bug~=9&&detect_bug~=4
error('The picture dimensions must be consistent! ')
end
if numel(size(A))>2
A_gray =im2double(rgb2gray(A));
else
A_gray = im2double(A);
end
if numel(size(B))>2
B_gray =im2double(rgb2gray(B));
else
B_gray = im2double(B);
end
%% size
[height_wrap, width_wrap] = size(A_gray);
[height_unwrap, width_unwrap] = size(B_gray);
%% find the cornet points in these two image
[x_A, y_A, v_A, R1] = harris(A_gray, 2, 0.0, 2);
[x_B, y_B, v_B, R2] = harris(B_gray, 2, 0.0, 2);
%% (ANMS) Adaptive non-maximum suppression
ncorners = 500;
[x_A, y_A, ~] = ada_nonmax_suppression(x_A, y_A, v_A, ncorners);
[x_B, y_B, ~] = ada_nonmax_suppression(x_B, y_B, v_B, ncorners);
%% get the features points
sigma = 7;
[des_A] = GFD(A_gray, x_A, y_A, sigma);
[des_B] = GFD(B_gray, x_B, y_B, sigma);
%% distance A and B
dist = distance(des_A,des_B);
[ord_dist, index] = sort(dist, 2);
%% ratio
% the ratio is better than distance
% the threshold is the tolerance
ratio = ord_dist(:,1) ./ ord_dist(:,2);
threshold = 0.5;
idx = ratio < threshold;
x_A = x_A(idx);
y_A = y_A(idx);
x_B = x_B(index(idx,1));
y_B = y_B(index(idx,1));
npoints = length(x_A);
%% 使用4点随机抽样一致计算鲁棒单应性估计,保持第一张图像不扭曲。
matcher_A = [y_A, x_A, ones(npoints,1)]'; %!!! previous x is y and y is x,
matcher_B = [y_B, x_B, ones(npoints,1)]'; %!!! so switch x and y here.
[hh, ~] = rmy(matcher_B, matcher_A, npoints, 10);
%% 使用反向旋转方法确定整个图像的大小
[newH, newW, newX, newY, xB, yB] = GNS(hh, height_wrap, width_wrap, height_unwrap, width_unwrap);
[X,Y] = meshgrid(1:width_wrap,1:height_wrap);
[XX,YY] = meshgrid(newX:newX + newW - 1, newY:newY + newH - 1);
AA = ones(3,newH * newW);
AA(1,:) = reshape(XX,1,newH * newW);
AA(2,:) = reshape(YY,1,newH * newW);
AA = hh * AA;
XX = reshape(AA(1,:) ./ AA(3,:), newH, newW);
YY = reshape(AA(2,:) ./ AA(3,:), newH, newW);
%% Interp2
if numel(size(A))==2&&numel(size(B))==2
newImage(:,:) = interp2(X, Y, double(A(:,:)), XX, YY);
elseif numel(size(A))>2&&numel(size(B))>2
newImage(:,:,1) = interp2(X, Y, double(A(:,:,1)), XX, YY);
newImage(:,:,2) = interp2(X, Y, double(A(:,:,2)), XX, YY);
newImage(:,:,3) = interp2(X, Y, double(A(:,:,3)), XX, YY);
end
%% output
if nargin == 2
varargout{1} = Mblend(newImage, B, xB, yB);
elseif nargin == 3
varargout{1} = Mblend(newImage, B, xB, yB);
varargout{2} = R1;
varargout{3} = R2;
end
end
MSURF:
function output = MSURF(A ,B)
%% Input
dimension_A=numel(size(A));
dimension_B = numel(size(B));
if dimension_B *dimension_A==9
color_flag = 1;
elseif dimension_B *dimension_A==4
color_flag = 0;
else
error('the input image dimension is not correct,they should have the same dimension');
end
%% imfliter
if color_flag ==1
I1 = rgb2gray(A);
I2 = rgb2gray(B);
elseif color_flag ==0
I1 = (A);
I2 = (B);
end
h = fspecial('gaussian',7,0.05);
I1 = imfilter(I1,h,'corr','replicate');
I2 = imfilter(I2,h,'corr','replicate');
I1 = imerode(I1,[0 1 0;0 1 0;0 1 0]);
I1 = imopen(I1,[0 0 0;1 1 1;0 0 0]);
I2 = imerode(I2,[0 1 0;0 1 0;0 1 0]);
I2 = imopen(I2,[0 0 0;1 1 1;0 0 0]);
%对原始图像滤波并采用纵向矩阵消除背景噪声和横向噪声,增大检测到的正确匹配点数目
%% Backup
img1=I1;
img2=I2;
%% SURF
%input :image
%Output :SURFPoints
points_1=detectSURFFeatures(img1);
points_2=detectSURFFeatures(img2);%检测SURF特征点
%% 特征向量
[img1Features, points_1] = extractFeatures(img1, points_1);%使用64维向量表示特征描述子,
%第一个返回的参数即为每个特征点对应的特征描述子,第二个参数是特征点
[img2Features, points_2] = extractFeatures(img2, points_2);
%% 用于特征点匹配
boxPairs = matchFeatures(img1Features, img2Features);%特征描述子匹配
%% find the Features points in all SURF points
matchedimg1Points = points_1(boxPairs(:, 1));%第二个参数:可以不加,因为其为n行1列的结构体数组
matchedimg2Points = points_2(boxPairs(:, 2));
%%
[tform, ~, ~] = ...
estimateGeometricTransform(matchedimg2Points, matchedimg1Points, 'similarity');%射影变换,tfrom映射点对1内点到点对2内点
%该函数使用随机样本一致性(RANSAC)算法的变体MSAC算法实现,去除误匹配点
%The returned geometric transformation matrix maps the inliers in matchedPoints1
%to the inliers in matchedPoints2.返回的几何映射矩阵映射第一参数内点到第二参数内点
%
% showMatchedFeatures(I1, I2, matchedimg1Points, ...
% matchedimg2Points, 'montage');
% title('Matched Points (Inliers Only)');%显示匹配结果
%%
Rfixed = imref2d(size(I1));
[registered2, Rregistered] = imwarp(I2, tform);%图像射影变换,以图1作为基准
% [registered1, Rregistered1] = imwarp(I1, tform);%以图2作为基准
figure('Name','SURF');
output= imshowpair(I1,Rfixed,registered2,Rregistered,'blend');%图像拼接
里面有一些函数我没有放出来,我认为网上是都可以找到的。
我的一些认为
Surf: 由于matlab本身是有函数可以调用的,所以相对比较简单且速度很快,但是他会生成一种特殊的格式,其他的函数不太好调用。如果想修改的话,可能得从头开始写这个。
并且matlab里面的方法好像不能处理彩色的图片,得先变成灰度。
Harris:代码没有被打包,可以修改,复用性挺好的,就是速度有点慢。如果大尺寸的图片估计会卡死,建议先做一个图像的压缩。如果太大了建议还是使用Surf,感觉效果差不多。
一点展望
1.将不同维度的图片(一张彩色和一张灰度)的进行拼接,最后显示的有彩色的,有灰度(就是别直接把彩色变成灰度来处理)。
2.图片的大小不一定需要相同,可以用不同尺寸的图片进行拼接。
3.对多张有序的图片进行拼接。
4.对多张无序的图片进行拼接。
一个很不错的图像拼接项目
(无序多图拼接全景,但是存在一定参数的需要人为给定的问题)
标签:SURF,end,%%,image,拼接,matlab,图像,dimension,size 来源: https://blog.csdn.net/hopefullying/article/details/117301151