发布网友 发布时间:2024-10-16 16:35
共1个回答
热心网友 时间:2024-11-25 17:21
内容摘要:MATLAB强大的运算和图形展示功能,使图像处理变得更加的简单和直观。本博文基于MATLAB编程语言,详细介绍了如何利用MATLAB及其图像处理函数进行经典拼图游戏设计,并通过具体方法步骤及相应代码逐步实现游戏的完美运行。(有详细步骤及代码解释,适合新手以及进阶的朋友参考)
关键词:拼图游戏;MATLAB;数字图像处理
下载链接: mbd.pub/o/bread/mbd-Ypq...
前言:
Matlab是MathWork公司推出的一套高性能的数值计算和可视化软件。它是一个高度集成的系统,集科学计算、图像处理、声音处理于一体,具有极高的编程效率。数字图像处理是一种通过计算机采用一定的算法对图形图像进行处理的技术。数字图像处理技术已经在各个领域上都有了比较广泛的应用。MATLAB强大的运算和图形展示功能,使图像处理变得更加的简单和直观。本文介绍了如何利用MATLAB进行经典拼图游戏设计。拼图游戏是一款非常经典的小游戏,因为它比较简单有趣,可变性很高且耐玩,有利于开发智力,帮助提高动手解决问题的能力。
拼图游戏的设计对一个MATLAB语言设计者进行语言提高和进阶都是一个很好的锻炼机会,说起来这个程序是笔者当年大学时完全自己构思摸索的第一个长的完整程序,作为一名刚接触编程语言的菜鸟,在痛苦与激动中整整花了一个星期才完成。如今我已是一名研究生,转眼再看过去写的那些程序,可能诸多不足但那些编程的锻炼确实让我感获良多,面对如今众多的研究课题时,入门编程让我可以从容地用编程语言去释放自己的思想,不必在有好想法时因为编程问题而浇灭灵感的火花。临近年关,辞旧迎新之际,外面的世界熙来攘往,早已沉浸着春节的热闹与喜悦中,我仍要挑个安静的时间总结反思过去一年各方面的得与失。一个想法划过脑海想把前面做过的程序做个整理和改进,分享出来希望能够给刚接触编程的朋友们一点帮助和启发,对于我也是一个总结与提高,期待我们今后一起能够继续学习和进步。
2. MATLAB的图像处理:
MATLAB的基本数据单位是矩阵,它的指令表达式与数学,工程中常用的形式十分相似,故用MATLAB来解算问题要比用C、FORTRAN等语言完相同的事情简捷得多。MATLAB支持五种图像类型,即索引图像、灰度图像、二值图像、RGB图像和多帧图像阵列。MATLAB中,一幅图像包含一个数据矩阵,RGB图像分别用红,绿,蓝三个亮度值为一组,代表每个像素的颜色。图像数组为M*N*3,M,N表示图像像素的行列数。MATLAB图像处理工具箱是由一系列支持图像处理操作的函数组成,可以进行诸如几何操作、线性滤波和滤波器设计、图像变换、图像分析与图像增强、二值图像操作以及形态学处理等图像处理操作。
这里拼图游戏中的图像处理主要是对图像数组的操作,涉及矩阵分割、重组等步骤。本文将在后面几节结合代码进行详细介绍。
设计步骤:
到此为止,前面的内容稍作了解即可,接下来的主要设计思路无需细看但了解大概的流程却是有必要的,毕竟编写程序前还是得清楚到底要做什么的,简洁清晰的设计方案能起到提纲挈领的作用。
拼图游戏的主要思想是先读入准备好的图片,将存储图像的数据矩阵平均分为9个小的矩阵块,并用一个矩阵元素为1,2,3,4,5,6,7,8,0的3*3的数组矩阵标记每一个小矩阵块。仿照人工随机打乱拼图的方法,将标记矩阵打乱,根据标记矩阵拼接相应的拼图块并显示整个图像,通过设置图形窗口鼠标点击事件的回调函数的方式获得鼠标点击位置的坐标值,判断点击位置并移动相应的拼图块,当拼图顺序完全正确时提示游戏完成。图3.1和图3.2是拼图游戏的程序流程图。
设计步骤大致如下:
3.1 开始程序设计:
首先需要准备一张彩色图片,图片的尺寸最好为正方形(否则不易于后面的处理,而且可能不好看),这里我选择的图片是一张经过裁剪的长宽为300*300的图片,如下文件'jigsawImage.jpeg'
在matlab中新建一个m文件,这里我命名的文件名为'jigsaw.m',为了方便两个文件放在同一文件夹下,如下图所示。
准备好这些我们就可以正式开始编写程序了,所有代码编写在jigsaw.m文件中,下面将逐个介绍其中的代码及设计细节。
3.2 分割拼图:
这里我们设计的是一个九宫格的拼图游戏,因此在打乱拼图前需要先将图片平均切割为相等的九份。首先我们来看看MATLAB中图片的储存与表示,执行命令”image=imread('jigsawImage.jpeg');“读入jigsawImage图片(若图片与m文件不在同一位置需输入绝对路径,如image=imread('C:\Users\Administrator\Desktop\jigsaw puzzle\jigsawImage.jpeg');)在MATLAB中的存储情况如图3.2.1所示。
可以看出MATLAB中图片的存储是以矩阵的形式进行,image是个300*300*3的矩阵,300、300分别是矩阵的横纵尺寸。平均分割image矩阵,则第一块小拼图的数据矩阵可以为x1=image(1:100,1:100,:);这行代码的意思是选取image矩阵中横坐标从1到100,纵坐标也从1到100的那部分矩阵数据。可通过下面的代码验证,帮助简单理解
在命令窗口执行以上代码,可以看到如下运行结果
将整幅图像平均分割成9块,为了方便每一块用一个数字表示,从左到右,从上到下开始将9个小拼图块分别标记为1,2,3,4,5,6,7,8,0;其位置及坐标系如图3.2.3所示
从上图中可以看到每块拼图在原图中的坐标位置,其实也是矩阵的索引范围,因此同样可以通过上面的方式引用标号为2,3,4,5,6,7,8,0的拼图块,代码如下
按照上面的思路,现在自定义一个从原图中分割拼图并按照相应拼图块的标记截取小拼图的函数choose( ),输入参数为image,index,其中image为原图的数据矩阵,index为要选择的拼图块的标记;输出为x,x是标记为index的小拼图块的数据矩阵。代码如下
首先第3到第6行中当index为1,2,3,...,8时先计算出行数row以及列数column,行数可通过求除以3后的商确定,fix( )是MATLAB中的取整函数,而列数可通过求余数确定,mod( )是求余函数,返回index-1除以3的余数。为了便于按照上面的方法分割矩阵,这里的row、column相当于一个倍数,如 x=image(1+row*100:100*(row+1),1+column*100:100*(column+1),:);则将行列数乘分割间隔100(因为选择的图片大小是300*300的,分成3*3的拼图块所以索引间隔为100,若为其他尺寸的图片应为长宽分别除以3后的结果)即可根据行列数row,column引用相应位置上的小拼图块的数据矩阵了。例如index=4时,经过第5,6行代码计算出的row=1,column=0,代入第8行代码中,则实际x=image(1+1*100:100*2,1+0*100:100*1,:);这与前面代码中写出的”x4=image(101:200,1:100,:);%拼图块4矩阵数据“作用一致。
当index=0时则执行第9行else下的代码部分,你可能会奇怪,为什么拼图块0不是从imge矩阵中分割而是放到else中了?这是因为0这个位置比较特殊,留作空白处,拼图游戏进行时当空白处附近某个拼图块被点击时,该拼图块就会移动到这个空白位置。这里ones( )函数产生一个100*100*3的全1矩阵,乘255则像素灰度值最亮,显示为全白,最后uint8( )统一数据类型。因此当index=0时,执行else中的代码,输出x为一块全白的拼图块。
3.3 按标记序号矩阵显示拼图:
前面一节介绍了可以通过标记序号分割原图获得小拼图块数据矩阵的方法,一幅拼图可由9块小拼图块拼接而成,因此用一个9个元素的标记矩阵,每个位置上的元素值作为一个标记序号表示相应位置的拼图块,就可以通过这个标记矩阵表示整个的拼图了。
这样原图就可以用矩阵[公式] 表示,而任意打乱的拼图也可以通过改变矩阵相应位置上的元素值表示了。现在我们编写一个根据标记矩阵显示对应拼图的函数drawmap( ),输入参数为A,A为一幅拼图的标记矩阵,A大小为3*3。代码如下
第3行代码读入图片并将原图数据矩阵存储在origin中;第4行中image是要显示的拼图数据矩阵,先预定义与origin相同。接下来对image进行逐个赋值,image每一块数据的赋值通过调用前面编写的choose( )函数完成;第9行中”choose(image,A(row,col))“返回标记矩阵A中第row行第col列的元素表示的那一块拼图块的数据矩阵,而前面的一半image(1+(row-1)*100:100*row,1+(col-1)*100:100*col,:)与3.2节中选取每个拼图块的作用类似,这里用于对行数row从1到3,列数col从1到3的拼图块矩阵上的元素逐个赋值。经过9次循环9处拼图块的数据赋值完成,最终显示图像image。可以通过下面的代码简单测试一下drawmap( )函数,设置一个标记矩阵Tag_A=[8 4 5;6 0 3;1 7 2],即[公式] ,按照该矩阵显示这幅拼图。
运行结果如下图所示,对比每个拼图块的标记可以看出函数能实现根据矩阵的值显示拼图了,距离成功又近