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};
============================找指导老师布置任务吧==============================