实现目标
数值分析实验教学系统开发。要求包含实验课中所有的实验内容,具体系统总体设计、交互的友好性等,各小组组内讨论决定;每个试验模块包括以下子模块:
- 能手动填写姓名、学号、班级等基本信息
- 实验目的,能手动填写
- 实验内容,包括视频讲解、算法推导、程序实现、测试结果。
3.1 视频讲解:视频部分主要为了指导学生怎么开展各个实验,包括代码的讲解,知识点讲解及二者细节的对应关系等·(视频讲解要提前保存在系统中,供学生学习),
3.2 算法推导:以自动滑动的图片展示为主,能够本地制作,拍照后通过系统上传并展示
3.3 程序实现:能在本地编写函数,存入指定文件夹,然后系统在运行时能调用.3.4·测试结果:能实时显示到系统界面上 - 总结及自评,能手动填写
- 自动生成word 版实验报告
参考资料
Matlab读取并按帧显示视频代码 CSDN-liaoqix
【MATLAB】简单易学的GUI BILIBILI视频
MATLAB官方文档 地址
功能实现
主界面实现
包含主菜单和三个区域,分别用于执行函数,显示结果和绘图;菜单栏用于调度其他模块
全局变量: global cur_row cmd pic cnt cur_cnt res
%定义两个text标题框。用来标识下面的两个静态文本框.
text_s = uicontrol(\'Parent\', gcf, ...
\'FontSize\',6, ...
\'Style\', \'text\', ...
\'Units\', \'Normalized\', ...
\'Position\', [0 0.98 0.123 0.02], ...
\'HorizontalAlignment\', \'left\', ...
\'Enable\', \'on\', ...
\'HandleVisibility\', \'on\', ...
\'String\', \'Command\', ...
\'Max\', 2);
text_s_2 = uicontrol(\'Parent\', gcf, ...
\'FontSize\',6, ...
\'Style\', \'text\', ...
\'Units\', \'Normalized\', ...
\'Position\', [0 0.48 0.123 0.02], ...
\'HorizontalAlignment\', \'left\', ...
\'Enable\', \'on\', ...
\'HandleVisibility\', \'on\', ...
\'String\', \'Result\', ...
\'Max\', 2);
接下来定义两个可以编写的文本框(作为命令区和结果显示区)。
edit_c = uicontrol(\'Parent\', gcf, ...
\'Style\', \'edit\', ...
\'Units\', \'Normalized\', ...
\'Position\', [0 0.5 0.5 0.48], ...
\'HorizontalAlignment\', \'left\', ...
\'Enable\', \'on\', ...
\'HandleVisibility\', \'on\', ...
\'Max\', 2);
text_c = uicontrol(\'Parent\', gcf, ...
\'Style\', \'edit\', ...
\'Units\', \'Normalized\', ...
\'Position\', [0 0 1 0.48], ...
\'HorizontalAlignment\', \'left\', ...
\'Enable\', \'on\', ...
\'HandleVisibility\', \'on\', ...
\'Max\', 2);
handles.edit_c = edit_c;
handles.text_c = text_c;
使用GUIDE编写的菜单栏
各区域如图所示
函数编写
函数、脚本编写功能实现
函数功能:在菜单栏当中的函数编写一栏添加回调函数当按下这一栏时候会弹出一个带编辑框的窗口用于编写函数及.m脚本文件。
function edit_fun_Callback(hObject, eventdata, handles)
fig_1 = figure(\'Name\', \'Undefine.m\', ... %定义的figure窗口,
\'Numbertitle\', \'off\', ... %每两个为一组前者为属性后
\'Units\', \'Normalized\', ... %为属性定义,具体可以再figure属性中看。
\'Position\', [0.15 0.1 0.7 0.7], ...%定义窗口的位置。
\'Menubar\', \'none\'); %不需要菜单
edit_m = uicontrol(\'Parent\', fig_1, ... %在定义的figure
\'Style\', \'edit\', ... % fig_1的基础上添加该eidt
\'Units\', \'Normalized\', ...%类型的文本框。用来编写代码。
\'Position\', [0 0 1 1], ...
\'HorizontalAlignment\', \'left\', ...
\'Enable\', \'on\', ...
\'HandleVisibility\', \'on\', ...
\'Max\', 2);
menu_1 = uimenu(gcf, \'Label\', \'文本\'); gcf为figure返回的句柄值
menu_s = uimenu(menu_1, \'Label\', \'另存为\');在menu_1所创建的菜单下添加一个新的选项另存为。
handles.fig_1 = fig_1;用句柄hanles.fig_1来记录fig_1记录的返回值
handles.edit_m = edit_m; 用句柄hanles.edit_m来记录edit_m记录的返回值
handles.menu_1 = menu_1; 用句柄hanles.menu_1来记录menu_1记录的返回值
handles.menu_s = menu_s; 用句柄hanles.menu_s来记录menu_s记录的返回值
guidata(hObject, handles);更新hObject保存的handles结构体。
set( menu_s, \'Callback\', {@menu_s_Callback, handles}); 设定menu_s即保存功能的回调函数。
函数、脚本保存功能实现
函数功能:将在函数编写界面编写的函数(或脚本)进行保存(.m格式)
function menu_s_Callback(hObject, eventdata, handles)
% uiputfile用于保存文本的函数。file保存返回的文件名,path保存存储的路径。
[file, path, ~] = uiputfile(\'*.m\');
%如果取消则在变量定义中定义的eidt文本标题为result的文本框中输出”User clicked Cancel.”,该文本框用来输出结果。(如果用户指定有效的文件名并点击保存,MATLAB 将在 file 中返回该文件名。如果用户取消该对话框,MATLAB 会将 0 返回给 file。)
%否则打开该文件,把在handles.edit_m中编写的代码存入该文件中。
if isequal(file,0) || isequal(path,0)
set(handles.text_c, \'String\', \'User clicked Cancel.\');
else
fp=fopen(file, \'w+\');
str = get(handles.edit_m, \'String\')
[row,col] = size(str);
for i=1:row
fprintf(fp, \'%s\n\', str(i,:));
end
fclose(fp);
end
close;
效果图
观看视频功能实现
函数功能:打开本地视频(提前录制好的教程);取消时将在结果框输出用户取消操作(下模块同)。
function watch_Callback(hObject, eventdata, handles)
%打开一个视频文件
[file, path, c] = uigetfile(\'*.mp4\');
if isequal(file, 0) || isequal(path, 0)
set(handles.text_c, \'String\', \'User clicked Cancel.\');
else
h_1 = figure(\'Name\', file, ...
\'Numbertitle\', \'off\', ...
\'Units\', \'Normalized\', ...
\'Position\', [0.15 0.1 0.7 0.7], ...
\'color\', \'w\', ...
\'Menubar\', \'none\');
VidObj = VideoReader(file); %修改为需要读取的视频文件
nFrames = VidObj.NumberOfFrames; %获取视频总帧数
vidHeight = VidObj.Height; %获取视频高度
vidWidth = VidObj.Width; %获取视频宽度
for k = 1 : nFrames %遍历每一帧
I = read(VidObj, k); %读出当前帧
imshow(I); %显示当前帧。
pause(0.005); 暂停系统程序,是人眼可以分辨,这里暂停0.005秒。
end
end
close;
逐帧播放视频,无声音
查看图片功能实现
函数功能:插入多张图片并显示,单击图片显示下一张。
function pic_Callback(hObject, eventdata, handles)
%全局变量 cnt,pic,cur,cnt,
% answer = questdlg(quest) 创建一个模态对话框,其中提出问题并返回用户的回答 - \'Yes\'、\'No\'、\'Cancel\' 或 \'\'。
默认情况下,该对话框有三个标准按钮,其标签分别为是、否和取消。
如果用户点击其中一个按钮,则 answer 值与按下的按钮的标签相同。
如果用户点击对话框标题栏上的关闭按钮 (X) 或按下 Esc 键,则 answer 值为空字符向量 (\' \')。
如果用户按下 Return 键,则 answer 值与默认所选按钮的标签相同。在本例中,为 \'Yes\'。
global cnt pic cur_cnt
answer = \'Yes\';
file = 0;
path = 0;
answer = questdlg(\'是否要读入图片\',\'读入\');
while( strcmp(answer,\'Yes\')==1 )
cnt = cnt+1;
[file, path, c] = uigetfile(\'*.jpg\');
pic_name(cnt, :) = file;
answer = questdlg(\'是否要继续读人图片\',\'继续\');
end
if isequal(file,0) || isequal(path,0)
set(handles.text_c, \'String\', \'User clicked Cancel.\');
else
%创建一个figure把图片通过它显示。
pic = pic_name;
h_p = figure(\'Name\', \'图片浏览\', ...
\'Numbertitle\', \'off\', ...
\'Units\', \'Normalized\', ...
\'Position\', [0.15 0.1 0.7 0.7], ...
\'color\', \'w\', ...
\'Menubar\', \'none\');
handles.h_p = h_p;
guidata(hObject, handles);更新已有的handles数据结构。
set( h_p, \'WindowButtonDownFcn\',{@h_p_WindowButtonDownFcn, handles});%添加鼠标左键触发,切换下一张图片。
cur_cnt = cur_cnt+1;
imshow(pic(cur_cnt, :));展示图片。自动展示第一张,之后的靠单击鼠标展示。
end
选择图片
![](https://img2020.cnblogs.com/blog/1752536/202101/1752536-20210111092921153-1093847614.png)
![](https://img2020.cnblogs.com/blog/1752536/202101/1752536-20210111092930598-1099165534.png)
单击显示下一张图片:
function h_p_WindowButtonDownFcn(hObject, eventdata, handles)
global cur_cnt pic cnt %全局变量
if cur_cnt == cnt %如果当前是最后一张图片则关闭。
close;
else
cur_cnt = cur_cnt+1;
imshow(pic(cur_cnt, :));%显示图片
end
显示界面:显示图片在界面内单击鼠标左键即可显示下一张图片。
命令文本框功能实现
函数功能:在command中输入要运行的.m文件的前缀,运行该文件并将结果显示在Result区域,如果是函数绘图,会将图片在旁边的坐标区域显示;输入clc命令清空输出框,输入cla清空绘图区。
%命令文本框的Callback实现
function edit_c_Callback(hObject, eventdata, handles)
global cur_row cmd res pstr
cur_row = cur_row+1;
cmd = get(handles.edit_c, \'String\');%将输入的文件前缀转为字符串
%set(handles.text_c, \'String\', cmd(cur_row, :));
run(cmd(cur_row, :))%运行.m文件
to_String;
set(handles.text_c, \'String\', pstr);%将结果以字符串的格式复制到输出框
if strcmp(cmd(cur_row, 1:3),\'clc\') == 1
set(handles.text_c, \'String\', \'\');%输入clc以空格覆盖输出区域
end
将数值型元胞数组转为字符串数组
function to_String()
global res pcnt pstr
[res_r, res_c] = size(res);
for i=1:res_c
if strcmp(class(res{2,i}),\'double\') == 1
double_1 = num2str(res{2,i});
pstr(pcnt, 1:length(res{1,i})) = res{1,i};
pcnt = pcnt+1;
[c_r,c_c] = size(double_1);
for j=1:c_r
pstr(pcnt, 1:length(double_1(j, :))) = double_1(j, :)
pcnt = pcnt+1;
end
end
end
res = {};
帮助(弹窗提示功能)实现
函数功能:显示命令区使用指南。
f = msgbox(message) 创建一个消息对话框,该对话框可将 message 自动换行,以适应合适大小的图窗。如果您要在多个 App 窗口、MATLAB桌面或 Simulink 上显示消息对话框,并且在响应对话框之前仍能与它们进行交互,请使用此函数。
msg = msgbox(\'输入函数名称后按下CTRL+ENTER执行 \', \'帮助\');
效果展示
生成Word版实验功能实现
根据对话框输入指定信息,程序按指定的格式自动生成Word文档,并将算法推导过程作为附录引入
%此处删去了部分重复性代码
function edit_doc_Callback(hObject, eventdata, handles)
%原包数组,填写基本信息
handles.inf = inputdlg({\'请输入姓名\', \'请输入学号\', \'请输入班级\'}, ...
\'基本信息\', 1);
%填写实验目的
handles.pro = inputdlg(\'实验目的\', \'实验目的\', 2, ...
{\'\'}, \'on\');
tmp = char;
tmp = handles.pro{1};
%总结及自评
handles.con = inputdlg(\'总结\', \'总结\', 2, ...
{\'\'}, \'on\');
tmp_2 = char;
tmp_2 = handles.con{1};
guidata(hObject, handles);
其中生成Word排版的代码含有大量重复部分,此处仅列举一小部分(详见代码)
%利用MATLAB生成Word文档
filespec_user = [pwd \'\测试.doc\'];% 设定测试Word文件名和路径
% 判断Word是否已经打开,若已打开,就在打开的Word中进行操作,否则就打开Word
try
% 若Word服务器已经打开,返回其句柄Word
Word = actxGetRunningServer(\'Word.Application\');
catch
% 否则,创建一个Microsoft Word服务器,返回句柄Word
Word = actxserver(\'Word.Application\');
end;
Word.Visible = 1; % 或set(Word, \'Visible\', 1);
% 若测试文件存在,打开该测试文件,否则,新建一个文件,并保存,文件名为测试.doc
if exist(filespec_user,\'file\');
Document = Word.Documents.Open(filespec_user);
% Document = invoke(Word.Documents,\'Open\',filespec_user);
else
Document = Word.Documents.Add;
% Document = invoke(Word.Documents, \'Add\');
Document.SaveAs2(filespec_user);
end
% 设定光标位置从头开始
Content = Document.Content;
Selection = Word.Selection;
Paragraphformat = Selection.ParagraphFormat;
% 设定页面大小
Document.PageSetup.TopMargin = 60; % 单位像素
Document.PageSetup.BottomMargin = 45;
Document.PageSetup.LeftMargin = 45;
Document.PageSetup.RightMargin = 45;
% Content.InsertParagraphAfter;% 插入一段
% Content.Collapse=0; % 0为不覆盖
Content.Start = 0;
title = \' 实验 XXX(标题)\';
Content.Text = title; % 写入标题
Content.Font.Size = 18 ; % 字体大小
Content.Font.Bold = 4 ; % 加粗
Content.Paragraphs.Alignment = \'wdAlignParagraphLeft\';% 设定段落格式(居中操作)
Selection.Start = Content.end;% 定义开始的位置 (将光标移动到后面)
Selection.TypeParagraph; % 相当于enter键
Selection.Text = \' 学号:\';% 写入变量
Selection.Font.Size = 12; % 字体大小
Selection.Font.Bold = 0; % 取消加粗
Selection.MoveDown;
Selection.MoveRight;
Selection.Text = [\' \',handles.inf{2},\' \'];% 写入变量
Selection.Range.Underline = 1;
Selection.Font.Size = 12; % 字体大小
Selection.Font.Bold = 0; % 取消加粗
Selection.MoveDown;
……
Selection.InsertBreak(1);
%选择算法推导图片
[file, path, c] = uigetfile([\'*.jpg\']);
H=figure();
imshow(file);
print(H,\'-dbitmap\');%将图片发到剪切板
close;
Selection=Word.Selection;
Selection.Range.Paste;%在当前光标的位置插入图片
Selection.MoveDown;
Selection.TypeParagraph;
Document.Save; % 保存文档
%Document.Close; % 关闭文档
%Word.Quit; % 退出word服务器
效果展示
生成WORD如下
算法推导作为附录导入
总结
填写实验目的和总结应该使用弹窗使用单独的文本框。
附源码下载链接
请发表评论