MATLAB拼接图片

MATLAB拼接图片

rygdsddssd God
找到的题目来源

题目

将下面这样的多个图片拼接到一起

题目

预备知识

函数

官方文档
Zeros Max
实际上看这些不如你先去看上面官方文档,看不懂再找别人写的

实例

读取图片

imread函数:MATLAB中读取图片的常用函数
用法:

  • A = imread(filename)
  • A = imread(filename,fmt)
  • A = imread(___,idx)
  • A = imread(___,Name,Value)
  • [A,map] = imread(___)
  • [A,map,transparency] = imread(___)
    其中,A为返回的数组,用于存放图像中的像素矩阵
1
2
3
4
a1=imread('000.bmp');
[m,n]=size(a1);
imshow(a1);%显示图像
%image(a1);

注意几个显示图片函数的区别:imshow是显示灰度图像的;image和imagesc 显示出来是彩色的(索引图像),索引图像是矩阵和colormap配合起来显示的。
批量读取图片

1
2
3
4
5
6
7
8
9
10
11
12
dirname = 'ImageChips';
files = dir(fullfile(dirname, '*.bmp'));
a=zeros(m,n,19);
pic=[];
for ii = 1:length(files)
filename = fullfile(dirname, files(ii).name);
a(:,:,ii)=imread(filename);
pic=[pic,a(:,:,ii)];
end
%double(pic);
figure
imshow(pic,[])
怎样识别拼接

这一题的重难点就是在于

  • 应该谁跟谁拼接?
  • 第i片的右边缘应该跟左边缘具有相似性;相似性如何度量?(标准不唯一!)
    总体相关系数
    样本相关系数
计算第4片的右边缘与第7片左边缘的相关系数
1
2
3
4
5
6
7
8
9
a=double(a);
b=a/255;
x=b(:,72,4);
y=b(:,1,7);
r1=sum((x-mean(x)).*(y-mean(y)));
r2=sqrt(sum((x-mean(x)).^2))*sqrt(sum((y-mean(y)).^2));
r=r1/r2
%或利用库函数来求样本相关系数
rr=corrcoef(x,y)

源代码

这里先把图片全读进来(在a里)再二值化放到b里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
a1=imread('c:\Users\22251\Desktop\工程文件\数模\matlab-数据准备\000.bmp');
[m,n]=size(a1);

dirname = 'c:\Users\22251\Desktop\工程文件\数模\matlab-数据准备\ImageChips';
files = dir(fullfile(dirname,'*.bmp'));
a=zeros(m,n,19);
pic=[];
for f_n = 1:length(files)
filename = fullfile(dirname,files(f_n).name);
a(:,:,f_n)=imread(filename);
end

%二值化
a=double(a);
b=a/255;

这里是构建rrs数组
本来我是准备用笨方法,类似于排序算法那种,疯狂的写flag值每一轮判断相关性一直要一直记住最大相关性的index与值,凭借之后进行下一轮比较。
想想都觉得非常麻烦啊,简化一下,创建一个数组变量arr[index,value],第i轮直接比较 arr[i,value] 放进去。

我的方法类似于数据结构中的有向图,我直接创建一个二维数组rr[,]rrs[i,j] 是i的最右列与j的最左列的相关性。
这样的话for循环就非常好写,最后直接遍历找相似的拼接就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
rrs=zeros(19,19);
for i=1:19
for j=1:19
if i==j
continue
end
x=b(:,72,i);
y=b(:,1,j);
r1=sum((x-mean(x)).*(y-mean(y)));
r2=sqrt(sum((x-mean(x)).^2))*sqrt(sum((y-mean(y)).^2));
rrs(i,j)=r1/r2;
end
end

一开始我是直接写flag_index=1就准备开始遍历图进行拼接了,然后想到第一张图实际上不一定就是最左侧的。
看了一下我的rrs
rrs
显然最左侧最右侧十分明显,不过我一开始以为NaN是null,因为我想当然的认为:
嗯,最右侧已经找不到最左侧能和它匹配了最左侧亦然。
但是

  • 我写的是两个for i=1:19,最左列和最右列是会比较的
  • 拼接后的图片左右两侧有留白,所以最侧边的两给图片边缘列是无穷大的相似——NaN
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    %先找谁在最左边
    %(i,:)最大值为0的在最左边
    %更正:(:,i)最大值为0在最左边,因为是是文档截屏,最左最右是留白完全一样
    flag_index=1;
    for i=1:19
    temp_index=find(rrs(:,i)==max(rrs(:,i)));
    if max(rrs(:,i))==0
    flag_index=temp_index;
    end
    end

    pic=[pic,a(:,:,flag_index)];

    for i=1:19
    temp_index=find(rrs(flag_index,:)==max(rrs(flag_index,:)));
    pic=[pic,a(:,:,temp_index)];
    flag_index=temp_index;
    end

    double(pic);
    figure
    imshow(pic,[])

最后的结果

结果

更新:最后一个for i=1:19应该改成1:18,多拼了一次,结果图能看出来

总结

做完题目的一点想法

这里实际上也有点歪打正着,如果给的图片左右两侧并不是相同的情况呢?
那就不会出现NaN这样的特征值,最左侧和最右侧对比的相似度也会是一个看起来很正常的值
这时候又要怎么做才能将整个图片拼接完成呢?

我觉得可以队列式拼接,思路就是按照相关性的大小进行次序拼接,这样拼接到最后就是一个图片。

如果你在想:”最左侧的最左列与最右侧最右列有可能相关性大于其他组的相关性“的话,那么这个依靠相关性判断相邻的方法从一开始就错了。这个问题是不需要考虑的。
而且,左右两侧不相同的情况下大概率不是黑白的二值图了,届时判断相关性的xy就不再是简单的0与1,最起码应该是0-225了,这样的可能性就几乎变成了抛硬币立起来的概率。

解决了什么问题

  • 怎样将多个图片拼接成一个整体
    • 应该谁跟谁拼接?拼接的依据是什么,如何判断?

得到了什么结果

  • 数组处理图像
  • 第一次将数学知识在编程中运用
    • 相关性
  • 第一次将数据结构知识在编程中运用
    • 有向图

形成了什么结论

  • 图像二值化可以有效减少运算量
    • 精度不高的彩色图像处理可以考虑先二值化
  • 图像处理时需要注意是否有特征性的留白
    • 文字图片左右侧可能有留白
  • 相关系数用来判断相似的可行性分析

其他

介绍说的突然感觉打通任督二脉主要就是说上面那里用了有向图的思想,相关性不正是权值嘛。
而且解决的也确实是有关于图的问题hh

说到图的话,那么先后拼接图片的顺序貌似也能弄成邻接矩阵啊
不过细想一下又觉得在这里没有什么必要

  • 麻烦,牛刀杀鸡
  • 我觉得邻接矩阵与邻接表的主要功能更应该是建立xxx的拓扑结构,显然这里需要做到的并不是建立拓扑而是单纯的排序

如果你有什么想法欢迎与我交流讨论!

  • 标题: MATLAB拼接图片
  • 作者: rygdsddssd
  • 创建于 : 2023-03-20 18:38:16
  • 更新于 : 2023-04-01 16:44:42
  • 链接: http://rygdsddssd.github.io/2023/03/20/matlab拼接图片/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
 评论