基础知识
1、不用事先对变量的类型进行定义或说明 ,系
统会根据变量被赋值的类型自动进行类型识别
2、元胞数组
{ }大括号,用于cell型的数组的分配或引用。
(1)创建:
方法一:{}
>> a={[2 4 7;3 9 6;1 8 5], 'Li Si',2+3i,1:2:10}
a =[3x3 double] ‘Li Si’ [2.0000 + 3.0000i] [1x5 double]
方法二:利用 cell 函数创建元胞数组
>> a=cell(3,3)
a = [] [] []
[] [] []
[] [] []
>>a=cell(1,4);a={'winter',123,'coming','哈哈'};
(2)组成它的元素是元胞 (cell)
(3)元胞数组的每个单元可以储存不同的数据类型。
(4)操作——提取、删除、转换、显示
A.提取
访问元胞:利用元素地址
>> a{1,2}
%查看元胞数组第 1行第 2 列的元胞元素
查看元胞内容:deal 函数
>> [a b c d]=deal(a{:})
%用 deal 函数查看元胞数组内容
%对于矩阵,冒号表示该维度上的所有元素。
a = winter
b =123
c = coming
d = 哈哈
B.删除
对单元数组向量下标赋空值即可删除单元数组的行或列
C.转换
num2cell 函数
mat2cell 函数
D.显示
显示单元内容 : celldisp 函数
与普通矩阵,数组的主要区别在于:通过()访问cell数组时访问到的是cell单元,通过{}访问cell数组时访问到的是cell单元储存的内容
视频的笔记
!!!多注释多讲解预警
总体的思路:
第一步 数字的识别(有数字填入数字,没有数字就填入0)
第二步 计算
第三步 数字的回填
对每一块代码的讲解,在代码块之后
壹、
%%清屏
clear;clc;close all
%%进入工作目录
cd F:\科技树\MustbeDone\2020.02.06_线上课程\11_2020.02.22
XBD = imread('simple.jpg');%实验成功了
函数语法
[…] = imread(filename)
贰
%%数独图片标准化
Original_Size=[441,441];%标准化数独9*9大小,有时候会小一点点
XBD=imresize(XBD,Original_Size);%标准化
imshow(XBD)
title('原始图像');
imshow(I,[low high]) 显示灰度图像 I,以二元素向量 [low high] 形式指定显示范围。
叁
%%二值化提取特征
V_thresh = graythresh(XBD);%自动阈值
im_2v=im2bw(XBD,V_thresh);
imshow(im_2v);
title('二值化图像');
对每一行进行切割
一行切9块,每块大小相等
矩阵,二值化。黑色代表0,白色代表1
没有数的矩阵,就是全为1的矩阵,对应的是空矩阵。
有数的矩阵,矩阵不全为1。
判断矩阵中,是否有数字。意义:有数字的位置就可以确定了。
不能太大,会碰到边界,边界是1。
im2bw:基于阈值,将图像转变成二进制图像。
BW = im2bw(I, level):将灰度图像I转变成二级制图像BW
level:阈值等级,取值范围【0,1】
BW: 逻辑型
肆
%%分割图像,图像存储在Img_num_all,对应位置存储在Index_sudo
H=size(im_2v,1);
L=size(im_2v,2);
Img_num_all={'' };%数字图像存储
Index_sudo=[]%数独中数字对应的位置 n行2列,n是数字的个数
count_space = 0;%记录有几个空的宫格
count_num = 1;%存储位置
adj_n=8;
for i=1:9
for j=1:9
in_num=im_2v(floor(H/9)*(i-1)+adj_n:floor(H/9)*i-adj_n,floor(L/9)*(j-1)+adj_n:floor(L/9)*j-adj_n);%见讲解一
imshow(im_num)%见讲解二
if all(im_num(:)==1)%表示为空,没有数字
count_space=count_space+1;
else
[a,b]=find(im_num == 0)%找出数字对应范围
Min_a = min(a);Max_a = max(a);
Min_b = min(b);Max_a = max(b);
Img_num_s = im_num([Min_a:Max_a],[Min_b:Max_b]);%见讲解三
Index_num_all{count_num,1} = Img_num_s;%存储所有数字,但是又重复,需要删除
Index_sudo = [Index_sudo;i j];%记录对应宫格位置
count_num = count_num + 1;
end
end
close all;
讲解一
行
floor(H/9)*(i-1)+adj_n
floor(H/9)i-adj_n
列
floor(L/9)(j-1)+adj_n
floor(L/9)*j-adj_n
i=1,j=1时,即第一行第一列
floor(H/9)*(i-1)+adj_n = 8
floor(H/9)*i-adj_n =41
全满时1-49,此时是8-41
i=1,j=2时,即第一行第二列
讲解二
只有两种格子,一种带数字,一种是白的
白的 all(im_num(:)==1)的结果是是
带数字 all(im_num(:)==1)的结果是否
讲解三
Img_num_s这个矩阵,存下了带数字的小格子,存的是图像
count_num 起始为1
讲解四
Index_sudo存的是对应的位置
伍
%%样本simple.jpg查看,看完关掉,主要是方面确定
Num_simples = size(Img_num_all,1);
for i=1:Num_simples%查看样本
subplot(5,8,i)
imshow(Img_num_all{i,1})
size(Img_num_all{i,1})%大致查看了所有数字对应的矩阵大小,指定一个统一规格
end
陆
%%数字对应索引位置,提取1到9的样本图片,运行一次就好
Num_simple_index = [16 11 7 4 15 1 2 8 9];%对应的是
for i=1:9%查看样本,1和6位是重复的可以进行试验
subplot(3,3,i)
imshow(Img_num_all{Num_simple_index(i),1});title(['数字样本:',num2str(i)])
size(Img_num_all{Num_simple_index(i),1})
imwrite(Img_num_all{Num_simple_index(i),1},[num2str(i),'.jpg'])%存储样本,运行一次就好
end
Num_simple_index(i)索引的位置
Nun_simple_index中,
第一个16代表着,第16个是1
第二个11代表着,第11个是2
第三个7代表着,第7个是3
第四个4代表着,第4个是4
第五个15代表着,第15个是5
第六个1代表着,第1个是6
第七个2代表着,第2个是7
第八个8代表着,第8个是8
第九个9代表着,第9个是9
执行完这段代码之后,就能够知道每一个数字的图像是什么样子了,为之后的比对做准备。
柒
%%数独矩阵化
0 imshow(Img_num_all{2,1})
1 Index_sudo;%数独中数字对应的位置
2 picSize=[26,20];%标准化大小,经过实验测定
3 SUDO = zeros(9,9);%数独矩阵初始化
4 for i_sudo=1:size(Img_num_all,1)
5 matchrs=[];
6 p = Img_num_all{i_sudo};
7 p = imresize(p,picSize);%需要识别的数独中数字匹配矩阵标准化
8 imshow(p)%和下面for循环中的数,要进行比较
9 for i_simple=1:9
10 q=imread([num2str(i_simple),'.jpg]);
11 q=imresize(q,picSize);%标记后样本数字标准化
12 imshow(p)
13 matchrs(i_simple)=corr2(p,q);
14 end
15 [m,n]=max;%获取最大值m和对应位置n,n对应1到9
16 SUDO(Index_sudo(i_sudo,1),Index_sudo(i_sudo,2)) = n;
17 end
%标准化大小
Img_num_all;%数字图像存储
Index_sudo;%对应宫格坐标
Img_num_all、Index_sudo一一对应
第7行和第11行进行标准化,是为了使用corr2函数,p和q都得是m行n列
corr2(A,B)相关系数越接近1相关性越大,相关系数越接近-1相关性越小
15行
m是相关系数中最大的值;n是几当前的数字就是几。
16行
把i行 Index_sudo(i_sudo,1)j列 Index_sudo(i_sudo,2)
捌
%%利用SUDO作为基础解算数据,解算数独,调用函数sodoku
S=sodoku(SUDO);%用育有的函数解算数独
%%填写结算数据到对应位置,用到Index_sudo函数
%1)获取所有空格位置索引Sudo_index
B_exclude=sub2ind(size(S),Index_sudo(:,1),Index_sudo(:,2));%sub2ind函数是matlab中对矩阵索引号检索的函数
[row col]=ind2sub([9 9], 1:81);%利用ind2sub构造行列坐标,[9 9]表示9行9列,1:81对应索引数字9*9=81
%ind2sub把数组或者矩阵的线性索引转化为相应的下标
%sub2ind则正好相反,将下标转化为线性索引
S_index=[row' col'];
k=ismember(S_index,Index_sudo,'rows');%判断Index_sudo在S_index中的位置,Index_sudo是有数字的
kr=not(k);%0和1呼唤,针对01矩阵
Sudo_index=S_index(kr,:);%对应的是所有空格子位置索引
%2)填入数字像素到test.jpg图像XBD中
Blue_num=[0 0 255];%数字颜色
Background=[255 255 0];%数字背景颜色
%%存储1到9数字图像,变换颜色
Color_NUM={''};
for i_n=1:9
Img_num=imread([num2str(i_n),'.jpg']);%灰度图
imshow(Img_num);
matrix=(Img_num<50);%选择黑色像素点,逻辑值为1,之前选择60没扣干净
[a,b]=find(matix==1);%找出所有黑色像素位置索引a,b
Img_color_num=Img_num;
for i = 1:size(a)
Img_color_num(a(i),b(i),1) = 0;
Img_color_num(a(i),b(i),2) = 0;
Img_color_num(a(i),b(i),3) = 255;%纯蓝
end
imshow(Img_color_num);
[a,b]=find(matix==1);%找出所有黑色像素位置索引a,b
for i = 1:size(a)
Img_color_num(a(i),b(i),1) = 255;
Img_color_num(a(i),b(i),2) = 255;%纯黄
Img_color_num(a(i),b(i),3) = 0;
end
imshow(Img_color_num);%完成数字颜色置换
Color_NUM={i_n,1}=Img_color_num;%获取所有的换色1到9图像(RGB)
end
%%插入Color_NUM中图像,用到位置Sudo_index与数值
for i_last=1:size(Sudo_index,1)
i=Sudo_index(i_last,1);j=Sudo_index(i_last,2);%对那个数独的行列坐标
H_a=size(XBD,1);L_a=size(XBD_cell,2);
XBD_cell=XBD(floor(H_a/9)*(i-1)+1:floor(H_a/9)*i,floor(L_a/9)*(j-1)+1:floor(L_a/9)*j,:);%获取对应空
H=size(XBD_cell,1);L=size(XBD_cell,2);%大方格行列范围
num_input=Color_NUM{S(i,j),1};%插入需要的数字图像
h1=ceil((H-size(num_input,1))/2);%向上取整,行对应位置1,近似让数字图像位于中间
h2=floor((H-size(num_input,1))/2);%向下取整,行对应位置2
l1=ceil((L-size(num_input,2))/2);
l2=floor((L-size(num_input,2));
XBD_cell(h1+1:H-h2,l1+1,L-l2,:)=num_input;%插入图像
XBD(floor(H_a/9)*(i-1)+1:floor(H_a/9)*i,floor(L_a/9)*(j-1)+1:floor(L_a/9)*j,:)=XBD_cell;%插入回去
end
close all
imshow(XBD)
function S = sodoku(M,S)
%[S,Mout] = sodoku(M,[S])
%
%A recursive program that solves 'sodoku' puzzles.
%
%Inputs: M partially filled 9x9 matrix with zeros in 'blank' cells
% S list of solutions (only used during recursive calls)
%
%Outputs: S list of solutions
%
%Example:
%
%M = [0,0,1,9,0,0,0,0,8;6,0,0,0,8,5,0,3,0;0,0,7,0,6,0,1,0,0;...
% 0,3,4,0,9,0,0,0,0;0,0,0,5,0,4,0,0,0;0,0,0,0,1,0,4,2,0;...
% 0,0,5,0,7,0,9,0,0;0,1,0,8,4,0,0,0,7;7,0,0,0,0,9,2,0,0];
%
%S = sodoku(M)
%
%Written by G.M. Boynton, 6/3/05
%If this is the first call, then zero out the solution matrix
if ~exist('S','var')
S = zeros([size(M),0]);
end
%find the first blank cell, or zero
firstId = find(M(:)==0, 1 );
if isempty(firstId) %If there aren't any zeros, then we have a solution!
S(:,:,size(S,3)+1) = M; %save it
else %calculate the list of all valid numbers that can go into this cell
[i,j] = ind2sub([9,9],firstId);
for k=1:9 %loop through all 9 possibilities
ii = (ceil(i/3)-1)*3+1;
jj = (ceil(j/3)-1)*3+1;
mm = M(ii:ii+2,jj:jj+2); %these are the indices into the 3x3 block containing that cell
if sum(M(i,:)==k)==0 && sum(M(:,j)==k)==0 && sum(mm(:)==k)==0 %OK for column, row, and 3x3 block
M(i,j) = k; %put this number in,
S = sodoku(M,S); %and call this function recursively!
end
end
end
第一运行完,这两个部分需要关掉