简单的图像处理-matlab版

查看图片的基本信息

使用到的工具箱函数有imfinfo,它会返回一连串的内容,有关图片的尺寸、图片类型等等。在使用的时候要注意,不能通过imread打开图片后直接调用它,调用它的时候需要传入文件名,而不是一个变量
在所有的返回信息中,有一个最近常用到的,就是色彩信息(BitDepth),如果是普通的彩色图,返回的是unit24,如果是灰度图,返回的是unit8
当然,检验图片是否是灰度图不仅是这种方法(事实上,也不推荐使用这个函数来判断是否为灰度图)

判断一张图片是否为灰度图

可以根据用户的自己选择,有多个方法:

  • 工具箱函数 这里用到的工具箱函数有isrgb(arg):假如arg是RGB图像就返回1;isgray(arg):类似前面那个

  • 直接判断imread返回的变量 通过imread读取图后,会显示读取的图像的矩阵,如果是灰度图,那么就是a*b,彩色图是a*b*3

  • 自定义方法

rgb=imread(file); %读入图像
mysize=size(rgb);
if numel(mysize)>2
  A=rgb2gray(rgb); %将彩色图像转换为灰度图像
else
A=rgb;
end

上述内容参考自:http://www.cnblogs.com/wxl845235800/p/7488482.html

图片的基本处理

读取一张图

pic = imread('test.jpg')

彩色图转为灰度图

  • 工具箱函数 gray = rgb2gray('test.jpg')

  • 自定义函数 彩色图转灰度图有基本的公式:gray = R*0.299 + G*0.587 + B*0.114,这也就是rgb2gray内部实现的算法。

function gray=rgbtogray(img);
[m,n,h] = size(img);
if h == 1
    gray = img;
end

gray = zeros(m,n);
for i = 1:m
    for j = 1:n
        gray(i,j) = 0.299*img(i,j,1) + 0.587*img(i,j,2) + 0.114*img(i,j,3);
    end
end
gray = uint8(gray);
end

显示直方图

imhist(gray)

直方图均衡化

eqImage = histeq(gray)
在这里说明一下直方图均衡化的概念

有一些图像的对比度不高,灰度分布不均匀,动态范围较低,这时,直方图均衡化可以使图像的灰度比较均衡,对比度能得到一定增强。
对于离散的灰度级来说,变换后的图像的灰度其实是变换前图像灰度的密度函数的累积和。这里灰度都预先归一化到范围[0-1]内。因为密度函数的累积和是一个递增的函数并且最后的值是1,所以变换前图像的灰度就被映射到[0,1]内,图像的灰度分布范围就被扩大了。

  • 数学原理

直方图均衡化原理

上图搬运自:histeq从用法到原理——Matlab直方图均衡化函数

二值化

阈值分割

利用图像中要提取的目标区域与其背景在灰度特性上的差异,把图像看做具有不同灰度级的两类区域(目标区域和背景区域)的组合,选取一个比较合理的阈值,以确定图像中每个像素点应该属于目标区域还是背景区域,从而产生相应的二值图像(0/1或0/255)

一般地,我们将感兴趣的区域或目标成为前景(foreground),在分割后的图像中常用白色表示,其他部分成为背景(background),用黑色表示。图像分割也可以看做是一个二值化过程

二值化的相关函数:im2bw(gray,level)
在做二值化之前,需要传递一个二值化的阈值参数level,对于这个变量level,我们可以通过很多方法来获取,有otsu、最大熵、迭代、自适应、手动迭代、基本全局阈值法。这里我们先介绍otsu算法。

  • otsu大津法

otsu的数学原理:
阈值T将整幅图像分成前景和背景两部分,当两类的类间方差最大时,此时前景和背景的差别最大,二值化效果最好。因为方差是灰度分布均匀性的一种度量,当部分目标错分为背景或部分背景错分为目标都会导致两部分差别变小,因此使用类间方差最大的分割阈值意味着错分概率最小

otsu的局限性:
它产生的是单一阈值,当物体目标与背景灰度差不明显时,会出现无法忍受的大块黑色区域,甚至丢失整幅图像的信息。

otsu算法有一个固定的公式,用户可以根据公式来实现一个自定义的函数。MATLAB工具箱内有一个自动生成阈值的otsu函数,即为graythreshlevel=graythresh(gray)。自动生成的阈值并不代表最优解,用户在二值化前选取阈值时,需要根据灰度直方图的波峰来判断最佳阈值。我们一般是去两个波峰之间的波谷作为阈值(im2bw要求传入的阈值是归一化的,所以在读直方图时需要将横坐标的值除以255)。假如有多个波谷,那么我们将多个波谷值作为阈值进行调试,直到测试到最佳的阈值

level = graythresh(gray);
BW = im2bw(gray,level);
  • 局部自适应阈值分割

局部自适应阈值是根据中心像素领域内像素值分布来确定像素位置上的二值化阈值。每个像素的二值化阈值不是固定不变的,而是由周围邻域像素的分布来决定的。亮度较高的图像区域的二值化阈值通常会较高,而亮度较低的图像区域的二值化阈值则会相适应地变小。不同亮度、对比度的局部图像区域将拥有相对应的局部二值化阈值。

matlab的相关工具箱函数:
adaptthresh:详细内容参考官方文档 - adaptthresh

imbinarize:详细内容参考官方文档 - imbinarize

自己实现的一个局部自适应函数:


% adaptivethreshold.m

% from https://ww2.mathworks.cn/matlabcentral/fileexchange/8647-local-adaptive-thresholding

function bw=adaptivethreshold(IM,ws,C,tm);;

if (nargin < 3)
    error('You must provide the image IM, the window size ws, and C');
elseif (nargin == 3)
    tm = 0;
elseif (tm~=0 && tm~=1)
    error('tm must be 0 or 1');
end 

IM = mat2gray(IM);
if tm == 0
    mIM = imfilter(IM, fspecial('average', ws), 'replicate');
else 
    mIM = medfilt2(IM, [ws ws]);
end 
sIM = mIM - IM - C;
bw = im2bw(sIM, 0);
bw = imcomplement(bw);

%main.m
img1 = imread('mg.jpg');
img2 = imread('mg.jpg');
bwimg1 = adaptivethreshold(img1,5,0.03,0);  % 自己调参数
bwimg2 = adaptivethreshold(img2,15,0.02,0);
subplot(221),imshow(img1),title('im1');
subplot(222),imshow(bwimg1),title('bwimg1');
subplot(223),imshow(img2),title('img2');
subplot(224),imshow(bwimg2),title('bwimg2');

形态学

形态学图像处理
mathworks - 形态学处理中常用的工具箱函数

形态学处理的一些案例

清除图片中的混杂:https://blogs.mathworks.com/steve/2007/12/07/cleaning-up-scanned-text/
取一张图片上的某些特征的文字:https://blogs.mathworks.com/steve/2008/07/14/opening-by-reconstruction/#