matlab图像处理的基本练习
求黑色背景中红球的球心位置
思路1:先二值化,然后求红球的外接矩形,其中心就是红球的中心
I = imread("redBallInBlack.jpg"); I_red = I(:,:,1);%直接取红色分量 I_bw = I_red>150;% 二值化 [m,n]= size(I_bw);%求高度和宽度 %假设红球的外接矩形的四个边分别为row_upper、row_lower、column_left、column_right row_upper = 1;%先让row_upper移动到图像的上边缘 while sum(I_bw(row_upper,:))==0 %对图像的row_upper这一行求和,只要为0,就下移 row_upper = row_upper+1; %当不为0时,循环退出,表示碰到了球的上边界 end row_lower = m; %先让row_lower移动到图像的下边缘 while sum(I_bw(row_lower,:))==0 row_lower = row_lower-1; end column_left = 1; while sum(I_bw(:,column_left))==0 column_left = column_left+1; end column_right = n; while sum(I_bw(:,column_right))==0 column_right = column_right-1; end row_center = (row_upper+ row_lower)/2; column_center = (column_left+ column_right)/2;
思路2:先二值化,然后求图像中所有白点的坐标,其平均值就是红球的中心坐标
I = imread("redBallInBlack.jpg"); I_red = I(:,:,1);%直接取红色分量 I_bw = I_red>150;% 二值化 [rows,columns] = find(I_bw); row_center = mean(rows); column_center = mean(column);
字符的切割和识别
切割思路:让一个竖线从左到右扫描,碰到白色的字的时候就是这个字的左边界,继续往右走,当右面竖线全是黑的时候就是右边界
%主函数 clc;clear all; I = imread("img.jpg"); I_gray=rgb2gray(I); I_bw = I_gray<150;% 二值化后字符是白色的 result = {I_bw}; flag_stop = 0; direction = 0; while ~flag_stop flag_stop = 1; for i = 1:size(n_result,2)%扫描result中的每一个元素 if(class(result{i})~= 'char')%如果该元素不是字符(未被识别) result{i} = reg(result{i});%尝试识别该元素 if(class(result{i})~= 'char')%如果不能识别 result = {result{1:i-1},cut(result{i},direction),result{i+1:end}};%进行切割,并插入原位置 flag_stop = 0;%需要进行下一轮识别 end end end direction = ~direction;%改变切割方向 end
切割的函数
function result = cut(I_bw,direction) %功能,切割一个字符矩阵一次 %direction:0从左往右切割,1从上到下切割 [m,n]= size(I_bw);%求高度和宽度 result = {};%定义一个cell用来存储结果和切割矩阵 %左右切割的情况 if direction == 0 column = 1;%定义一个竖扫描线,最开始为1,表示在最左边 column_left=1;%定义一个竖线,用来记录字符左边的位置 while column < n %如果这个竖线是全黑的,但右边的线有白的,表示右边的线就是字符的左边界 if sum(I_bw(:,column))==0 && sum(I_bw(:,column+1))>0 column_left = column+1; end %反之,就是右边界,这时就可以把这段截下来,放到cell里 if sum(I_bw(:,column))>0 && sum(I_bw(:,column+1))==0 result{end +1} = trim(I_bw(:,column_left:column)); end column = column + 1; end end %上下切割的情况 if direction == 1 row = 1; row_upper=1; while row < m if sum(I_bw(row,:))==0 && sum(I_bw(row+1,:))>0 row_upper = row_upper+1; end if sum(I_bw(row,:))>0 && sum(I_bw(row+1,:))==0 result{end +1} = trim(I_bw(row_upper:row,:)); end row = row + 1; end end
里面有个trim的子函数,用来切除图片的黑边
function I_trim = trim(I) %此文件必须保存为trim.m %功能:切除灰度或者二值化图片的黑边 [m,n]=size(I); row_upper = 1;%先让row_upper移动到图像的上边缘 while sum(I(row_upper,:))==0 %对图像的row_upper这一行求和,只要为0,就下移 row_upper = row_upper+1; %当不为0时,循环退出,表示碰到了球的上边界 end row_lower = m; %先让row_lower移动到图像的下边缘 while sum(I(row_lower,:))==0 row_lower = row_lower-1; end column_left = 1; while sum(I(:,column_left))==0 column_left = column_left+1; end column_right = n; while sum(I(:,column_right))==0 column_right = column_right-1; end I_trim= I(row_upper:row_lower,column_left:column_right);
识别思路:把所有字母和符号图片预先存到文件夹里(简单其间,我们假设只有x.jpg,y.jpg,z.jpg三张图片)
name_lib = {'x','y','z'};%名称库 %根据名称库生成矩阵库 mat_lib = {}; [m_lib,n_lib] = size(name_lib); for i = 1: n_lib I1 = imread([name_lib{i},'.jpg']); I1_gray = rgb2gray(I1); I1_bw = I1_gray < 150;%进行相同的预处理,黑底白字 I1_trim = trim(I1_bw); mat_lib{end+1} = I1_trim;%把生成的矩阵放到矩阵库的末尾 end %用目标矩阵I_trim和库矩阵逐个相减,其模最小的就是识别结果 compare = []; for i = 1: n_lib %相减之前必须让两个矩阵大小相同,统一调整为40*40 compare(end+1) = norm(resize(I_trim,40,40) - resize(mat_lib{i},40,40)); end pos = find(compare == min(compare)); result_reg = name_lib{pos};============================找指导老师布置任务吧==============================