matlab——图像配准

说明

资料来自《详解MATLAB图像函数及其应用》
作者:张倩,占君,陈珊
出版社:电子工业出版社
出版时间:2011-04
这是我对MTALAB图像处理整理出来的学习笔记,望与君共勉
采用部分只有代码,其他的我自己收集来的资料,萌新一枚,侵权即删
内容来自书的第十九章1375页

图像配准

  • 主要目的:
    去除或抑制待配准图像和参考图像之间在几何上的不一致,并融合这些数据从而得到被测对象更完整的信息
  • 配准控制点:
    输入图像与参考图像上映射配准的对应点,而进行图像配准的几何参数需根据图像的一些配准点来进行计算

配准点选取

配准点的选取遵循的原则:

  1. 两幅图像上的配准点的特征必须保持一致,一般是两幅图像中都共同拥有的标记,如道路的拐弯或道路两旁的标志性建筑物等
  2. 选择的配准点要相对分散,尽量不要集中在某个区域
  3. 配准点的数量要恰当,不能过多也不能过少。配准点太少会影响配准精度,如果太多则影响配准速度。

对四幅不同的图像进行图像配准

本例通过图像配准将四幅图像转换成同一角度拍摄的同一幅图像

  1. 将图像读入MATLAB的工作区,通过对话框选择图像文件,打开图像文件并判断图像文件有效性
  2. 采集图像中的控制点对,并保存控制点对
    对每幅图像进行控制点的采集,要求控制点个数至少要2个,每幅图像的控制点必须相同
    为了便于采集控制点,将图像放大至屏幕左上角显示
  3. 选取一个基准图像进行图像配准
    以第k帧图像为基准图像进行图像配准,配准前确定变换类型,利用指定的变换类型进行图像配准
  4. 显示配准后的图像

步骤一

下面是第一段源码

[filename,pathname]=uigetfile({'*.bmp';'*.jpg';'*.gif';'*.tif';'*.*'},'打开原始图','MultiSelect','on');
if ~iscell(filename)
    errordlg('打开文件失败!');
    return;
end
imnum=length(filename);
imA=cell(imnum,1);
for i=1:imnum
    fullname=fullfile(pathname,filename{i});
    imA{i}=imread(fullname);
    figure
    imshow(imA{i});
end

uigetfile函数

[filename,pathname]=uigetfile(filterspec,dialogtitle,‘MultiSelect’,mode)

  1. filename:返回的文件名,属性为细胞矩阵,每个元素存放一个文件的文件名
  2. pathname:返回的文件的路径名,属性为字符串,存放文件的路径
  3. filterspec:文件类型设置,如png,jpg,tif,gif等
  4. dialogtitle:打开对话框的标题,显示在选取图像时的对话框左上角

并且本例指定用户可以选择多个文件,将模式设置为on,将允许进行多选图像文件

  • 其他用法:
    创建标准的对话框并通过交互式操作取得文件名

file=uigetfile

  1. 显示一个模态对话框,对话框列出了当前目录下的文件和目录,用于可以选择一个将要打开的文件名
  2. 如果文件名是有效的且该文件存在,则当用户点击Open时函数uigetfile返回该文件名
  3. 若不存在,uigetfile显示一个控制返回对话框值的错误提示信息,此时用户可以输入另外的文件名或点击cancel按钮
  4. 如果用户点击cancel按钮或关闭对话框,函数uigetfile将返回0

[filename,pathname,filterindex]=uigetfile(filterspec,dialogtitle,defualtname)

  1. filename:返回的文件名
  2. pathname:返回的文件的路径名
  3. filterindex:选择的文件类型
  4. filterspec:文件类型设置
  5. dialogtitle:打开对话框的标题
  6. defaultname:默认指向的文件名

创建并显示对话框,列出当前目录下的文件

  • FilterSpec决定文件的初始显示,它可以为一个文件全名或者包含通配符*,如‘*.doc’表示列出所有的文档文件
  • 如果FilterSpec是一个包含文件名的字符串,则该文件名所在的文件名域将被选中并显示出来,且该文件的扩展名将作为过滤作用
  • 如果FilterSpec是一个包含文件路径的字符串,例如‘.’,’…’或’/’,例如‘…/*.m’表示列出当前目录上的所有M文件
  • 如果FilterSpec是一个单元数组,则其第一列为扩展名列表,第二列为描述列表
  • 如果FilterSpec没有指定路径对象,则uigetfile将使用默认路径下的所有文件类型

iscell函数

tf=iscell(A)

  • 如果A为cell array,则返回1,否则返回0

errordlg函数

errordlg(error_string)
错误对话框

  • 其他:
  • 普通对话框——h=dialog(‘PropertyName’,‘PropertyValue’)
  • 警告对话框——h=warndlg(warning_string,dlgname,createmode)
  • 帮助对话框——help(‘help_string’,‘dlgname’)
  • 信息对话框——msgbox(message,title,icon)
    • icon有’error’,‘warn’,‘help’,‘custom’
  • 提问对话框——button=questdlg(‘q_string’,‘titlt’,‘str1’,‘str2’,‘str3’,default)

length函数

y=length(x)

  • 计算指定向量或矩阵的长度y,x为向量则返回长度,x为非空矩阵,则length(x)等价于max(size(x))

cell函数

a=cell(n,m)

  • 把a初始化为一个n行m列的空元胞数组
    赋值方式:a{1,1}=rand(5)

fullfile函数

f=fullfile(filepart1,…,filepartN)

  • 从各部分构建完整的文件名
  • 不同平台的文件分隔符不同,windows为反斜杠(\),最后一个part的末尾无分隔符

结果就创建了每幅图的路径
在这里插入图片描述因为是循环出来的,所以就剩一个第四幅图的路径,结果会弹四个窗口出来的,很占底部状态栏,可以关了吧

imread函数

[X,map]=imread(filename)

  • 从指定的图像文件中读取索引图像和颜色表
    X为索引图像
    map为颜色表,其值自动被调整到[0 1]的范围

A=imread(filename,fmt)

  • 从指定的图像中读取灰度图像或真彩色图像
    filename表示文件名
    fmt表示文件类型

其他说明

  1. 读取图像,我把tif格式去掉之后便出现了下图
    在这里插入图片描述去掉后面的“.”好像没啥用啊,那个所有文件的按钮都在的
  2. 然后打开原始图显示在
    在这里插入图片描述这个位置
  3. 打开失败是这样的
    在这里插入图片描述就是读取进去然判断是否读入了元胞数组,这些元胞数组被读成的样子是
    在这里插入图片描述我读入了四个读片,分别叫imge1/2/3/4,格式为png(QQ截图)
    至于那个return到底是怎么回事,我学matlab到现在也没明白,也许有一天能理解吧
  4. 然后是图像个数、创建4x1的元胞数组、显示读取的图像,注意uigetfile并没有读入图片,而是读入图片的路径信息,最终读入图片要靠循环和imread函数给imA数组,元胞数组用{}这个括号

步骤二

hfigid=figure;
scrsz=get(0,'ScreenSize');
for i=1:imnum
    imagevalue=imA{i};
    imshow(imagevalue);
    set(hfigid,'Position',[0,scrsz(4)*0.3-80,scrsz(3)*0.7,scrsz(4)*0.7]);
    if i==1
        ka=sum(size(imagevalue));%length(imagevalue)
        k=1;
        xy=ginput;
        xynum=size(xy,1);
        if xynum<2
            errordlg('控制点个数至少要两个');
            close(hfigid);
            return;
        end
        imxy=zeros(xynum,2,imnum);
        questdlg({['控制点个数:',num2str(xynum)]});
        hfig0=figure;
        figure(hfig0);
        imshow(imagevalue);
        hold on;
        plot(xy(:,1),xy(:,2),'*r');
        hold off;
        figure(hfigid);
    else
        ka1=sum(size(imagevalue));
        if ka>ka1
        k=i;
        ka=ka1;
        end
    xy=ginput(xynum);
    if size(xy,1)~=xynum
        errordlg('控制点个数不一致');
        close(hfigid);
        close(hfig0);
        return;
    end
end
imxy(:,:,i)=xy;
end
close(hfigid);
close(hfig0);

get函数

v=get(h)

  • 查询图形对象属性

本例是返回句柄0的对象的screensize值

set函数

set(H,name,value)

  • 设置图形对象属性
    为H标识的对象指定其name属性的值
  • 使用时须用单引号将属性名引起来,如果H是对象的向量,则set会为所有对象设置属性

本例用于设置句柄参数的位置和大小

ginput函数

[x,y]=ginput

  • 标识坐标区坐标
  • 可用于无线多个点,要选择一个点,将光标移至所需位置,然后按下鼠标按键或键盘上的键,按return键可停止选择,返回所选点的坐标
  • 如果没有当前坐标区,调用ginput会创建一个笛卡尔坐标区
    对于[x,y,button]=ginput(N),其中N为次数,button为操作的ascii码,x,y为横纵坐标,敲击键盘或鼠标总计N次后返回相应值

本例在i=1也就是对第一幅图进行采样,xy内记录了鼠标点击的地方的坐标值,一般应该都是Nx2的double型吧,我还没采集过3维,毕竟这个例子就是采集二维然后分析特征的嘛

其他说明

  • hfigid结果变成了figure类型,继续打开之后就是一列可以继续打开的数据,然而打开之后什么都没有,连数据都没有,如下图
    在这里插入图片描述

采集图像中的控制点对,并保存控制点对
对每幅图像进行控制点的采集,要求控制点个数至少2个,每幅图像的控制点必须相同,反正你的点数相同才能继续下一幅图的采集和结束采集点操作

  • 图像统一放大至屏幕左上角显示

在这里插入图片描述

  • 通过鼠标采集控制点,并记录控制点个数
    xynum里就记录了点的个数

  • 最后的IF语句模块用于判断采集点数是否大于等于2
    显示第一幅图像及其控制点,作为后面图像的控制,并选取尺寸最小的图像作为基准图像

本次我采用maya制作一个长方体,并用ps进行图像大小限制之后再进行的采样,故四幅图大小一致
判断控制点个数是否一致,并且关闭图像

  • 然后是用zeros函数创建一个xynum2imnum大小的三维零矩阵,本次应是3x2x4,即三个采样点,x和y两个坐标值,4幅图
  • 第一幅图采样完之后你可以敲击回车结束采集,会弹出一个询问框,如下图
    在这里插入图片描述比如我某一次采样点为4,然后执行hold on;plot第一列所有点+第二列所有点+红色星号
    在这里插入图片描述可以看到已经是第七张新图了,然后继续弹出第二幅图的采样,当你完成第二幅图的采样时,上面这幅图也不会消失,直到你把四幅图采样完成才会关闭
  • 然后是hfig0的出现,它就是创建采样图的那个新图用的,正常情况下会出现读取的4幅图即figure1234,然后采样图占一幅5,出现这个hfig0就是第6个句柄,我出现7是还有一幅我上次采样三个点用的
  • 然后下边是if语句的出现,这是用来查找最小的图像的
  • 又继续用ginput函数采点,达到第一幅图的采集次数会自动进行下一幅(close函数),点数不够又敲击的话会弹出报错窗口,然后关闭第一幅图的采样位置图
  • 或者采集完也会自动关闭的,一个在if语句内,一个在外
  • 然后把采集的位置传给imxy,前两个全部传,第三维指向图的顺序

步骤三

imA1=imA{k};
[imAx,imAy]=size(imA1);
if xynum==2
    formstr='linear conformal';
elseif xynum==3
    formstr='affine';
else
    strlx=questdlg('请选择变换类型:仿射变换(Affine)/透视变换(Projective)','','Affine','Projective','Cancel','Affine');
    if strcmp(strlx,'Affine')
        formstr='affine';
    elseif strcmp(strlx,'Projective')
        formstr='projective';
    else
        return;
    end
end
imB=uint8(zeros(imAx,imAy,3,imnum));
for i=1:imnum
    tform=cp2tform(imxy(:,:,i),imxy(:,:,k),formstr);
    imB(:,:,:,i)=imtransform(imA{i},tform,'XData',[1 imAy],'YData',[1 imAx]);
end

uint8函数

Y=uint8(X)

  • 8位无符号整数数组
  • 将X中的值转换为uint8类型,超出范围[0 2^8-1]的值映射到最近的端点,对数对矩阵都是如此,此为标量操作

本次出现4-D uint8表示4维无符号整型,第四维表示帧数

zeros函数

X=zeros(sz1,…,szN)

  • 返回由0组成的sz1x…xszN数组

cp2tform函数

TFORM = cp2tform(input_points, base_points, ‘affine’);

  • 对图像进行变换(模型参数估计)
  • 在图像配准中,分别由标准图像和待测图像得出关键点坐标后,需进行仿射变换参数估计

我也没看懂这个函数,它创造出来的参量是这样的
在这里插入图片描述看了好久的帮助文档之后,我只能说这个函数可以用于图像的旋转(二、三维)、液化、分段线性拉伸、分段非线性拉伸,我也用其他简单的参数试了一下
在这里插入图片描述没看懂,可能是里边还有嵌套的概念吧,容我研究个几年

imtransform函数

B=imtransform(A,tform)

  • 参数tform来自cp2tform函数
  • 将二维空间变换应用于图像
  • 具体细节请移步帮助文档
  1. 按我第一次研究的理解的话,就是可以用一个三维实现灰度图像的变形,要保持1x0;x10;001这样的,其中x可以作为修改图片的参数,第一行作为左右边的图片的上下错位,第二行作为图片的上下边错位,书面表达叫水平(垂直)剪切
  2. 还有个用途叫做图像配准,就是你拍同一个东西,会产生手抖,就有核心内容还在,但是边缘出现内容的增加或减少,然后用这个函数进行亿些操作,就可以检测出一点点变化
  3. 本例中的XData、YData指XY输出空间中的空间范围,XData 的两个元素分别给出 B 的第一列和最后一列的 x 坐标(水平)。YData 的两个元素给出 B 的第一行和最后一行的 y 坐标(垂直)。

其他说明

  • 当控制点为2时,默认使用线形变换矩阵
  • 当控制点为3时,默认使用仿射变换矩阵
  • 当控制点大于3时,由用户选择使用仿射变换矩阵或透视矩阵,由questdlg函数弹出选择框
  • 然后定义一个四维零矩阵,存放配准后的图像集,原代码中第三维大小为1,于是matlab弹出error,在修改创建大小和存放大小之后,error消失
  • k出现在判断最小的图那里,因为我的四幅图大小一样,所以k=1

步骤四

figure
montage(imB);

montage函数

montage(photoname1,photoname2,…)
montage(D,map)

  • 显示多帧图像的所有帧

测试结果

第一幅图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述当采样点数为3时
在这里插入图片描述
当采样点数为4且选择affine仿射变换
在这里插入图片描述我们可以知道这个图像配准配了什么鬼我们并看不懂,如实我按照教材说的各种奇妙的三角形去试试
第一幅采样图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述2个采样点
在这里插入图片描述
4个采样点,选择affine
在这里插入图片描述
终于到这里变得规则了一点,至于这些图给了什么信息,还请容我用时间来慢慢渗透理解

猜你喜欢

转载自blog.csdn.net/qq_43600632/article/details/105690198