什么是图像增强:
在拍摄图像时,往往曝光不足,或曝光过分,导致图像模糊不清晰,某些我们感兴趣的画面不突出,我们就要把它改变一下,改变到清晰可见。
造成模糊的原因:
曝光采集时有干扰-噪音,散斑,运动模糊,
我么把图像进行修改,达到我们最想要的最清晰的,便于我们之后识别,人工处理。
不同问题采用不同方法,有的图像适合这种增强法,有的图像适合另一种。
没有一种统一方法能解决万物,所以用试验的方法。
增强和恢复:
有相同的部分:恢复也是让图像变得更接近原始的目标,更清晰。增强也是让他清晰
不同的地方:增强不一定要去逼近原图像,只要把我感兴趣的部分变亮,或对比度拉伸。恢复技术是尽可能地逼近原始图像,要恢复出来,和原始图像一样。
图像增强的手段
空间域法和频率域法
现在介绍空间域的处理技术,灰度变换技术属于空域里面对图像的增强。
包括拉伸对比度,提高亮度...一些手段。
后面几章是围绕图像增强的技术手段讲的。
在这一章介绍灰度变换技术。
逐个像素的颜色改变
上一章内容是图像的像素从一个区域移动到另一个区域,颜色不改变,这一章内容是取土中像素的颜色改变,可能比原来的数值大/小,用一系列手段方法改变它的数据值。
这种变换关系,比如按照倍数关系增大,或者把他的值取对数,范围压缩,或者取成指数,或者进行分段。所以它是逐点来改,逐个像素改。
逐点改变:
下面一章节中,图像平滑和锐化,一个像素是和流域相关的,如果流域很亮很白,而我独自的是黑像素,那可能要改。我周围的像素值改变是跟周围相关系的。逐点改变是跟周围没关系,不考虑流域像素的大小。
灰度变换就是改变灰度值,要么更亮要么更暗,所以画质改变。如果灰度分布在很窄的范围内,就可以把它拉宽一些,使得图像的显示效果更清晰。
用f(x,y)表示像素值。(x,y)是坐标值,f(x,y)是像素值。
点运算就研究变换函数,以变换函数为基础来研究它的处理方法,它是逐点经过运算的,没一点经过一个函数运算,函数描述了输入与输出之间的转换关系---一个灰度值变成另外一个灰度值。
但是不改变空间的位置。
结合变换是改变了它的位置,但是灰度值不改。
点运算和邻域不想关。
灰度变换的方法
线性变换,分段线性变换,对数非线性变换。
为了感兴趣的目标突出出来,可以进行分段线性变换
底下例子中:
对图像的数据区进行了三段分段像素变换。每一段分段线性变换的数按照刚才的方法写出来,就可以突出感兴趣的区间,抑制不感兴趣的区间,
其他地方都要保留原像素值,只有在区间里面用分段线性变换公式。
下面例子中:
60<f(x,y)<90之间变换,其他地方不变换
区间(a,b)映射到区间(c,d),是为线性变换。斜率为(d-c)/(b-a),
取对数:数据变小,数据区会被压缩
如果图像对比度过大,亮度范围过广,可进行压缩。
压缩的特点:
小于100的值,通过线性映射,映射到180左右,150到180,说明对数变换关系会对比较暗的图像进行提升,。
如果压缩500变为250,可以对亮的起到压缩作用。变暗。
底下为对数变换公式。
为何括号中有加1,因为灰度值可能取0,0是没有对数的。外面再乘以一个指定的系数。
注意:这里的对比是指x和y的对比,就是映射前和映射后。而不是函数的走势,不是x1和x2的对比或y1和y2的对比。因而单是看函数的某个值(x/y)的走势没用,要看x和函数映射后对应的y的比较。
所以可以使用系数为1的线性变换(函数映射前后对应的x和y值大小相等)来作为参照。
这里的对数函数核指数函数都是测算好的,不是我们理解的函数。比如可以保证对数函数核指数函数的x值和y值相等。
对数变换,从映射后的结果来看,低的变高了,高的变化不大,因而暗的变亮了,亮的相对就暗了。映射后的结果数值区域减小。
指数变换,低的变低了,高的也变低了。而且在后面x值越大,映射的值是直线上升的。前面的却是下降的,所以亮的更亮,暗的更暗了。映射后的结果数值区域增大。
下面的非线性变换:
给定阈值。
二值化,大于阈值的给定1,小于阈值的给定0.
分段,分阶段给数。
编程思路:
循环每一个像素,判断一个像素和一个域值(值得范围),经过一个变换公式来修改,
二值化是图像处理最基本最重要的方法,我们在做识别时候,我们要提取出来想要的目标物体,常常要做二值化。
就是说把背景置白,只保留我所需的内容,比如说汽车牌照,我把汽车车身去掉,只保留汽车牌照,那么就要用二值化法。
人脸识别,要把背景去掉,只保留人脸。
二值化的原理:
就是图像变为两个值,可以把背景置白,物体置黑,或者背景置黑,物体置白。就是想要目标物体是白还是黑,不影响后期的分析。
二值化有个阈值,小于阈值置黑,大于阈值置白。
黑白图像就可以进一步进行去噪处理,再去提取特征,
二值化的公式很简单,难度在于阈值的选取,如何去选取一幅图最好的阈值分割?
如果阈值过大,那目标就很小,阈值过小,那么噪音就都包含在目标里面了,进行分析就判断失误太多。
所以阈值分割最重要。往往很难找到一个适合各种情况下的阈值。
后续还要学习如何去找阈值?
如果阈值找的准确,就可以很快区别出人脸。
往往根据实际具体情况,根据一幅图片,做一些底层处理后,建立一些模型来取量。
指定了两个阈值,T1,T2.
<T1,置黑,>T2,置黑,T1<X<T2,置白,或者反过来。
对于实际图片来说,如果一个彩色图片,可以把红绿蓝分别作为一个8位的数据区,红、绿、蓝面板都提出来,它们的为平面每个颜色都是8位的。
现在想把某一个范围内的颜色保留,其他颜色不要,我把20-80之间的像素保留,其他置黑。
这个方法表面上只适合灰白图像,其实图像是真彩色的,分RGB三个分量,每个分量都是8位,所以每个分量仍然是一个跟灰度数据区一样。
给定2个阈值,小于阈值置黑,大于阈值置白,在两个阈值之间保持原来的灰度值不变,或者改变也行,自己编写一个变换的函数就行。
改变阈值参数就可以改变窗口的效果。
上面就是说:
有2个转折点,1(x1,y1),2(x2,y2),在这个范围内,在0-x1之间,变换0-到y1区间;在x1-x2之间,变换到y1-y2区间;大于x2,变换到y2-255区间。
所以可以看到,如果x1-x2之间很窄,y1-y2就给拉宽,所以可以把灰度值变得随心所欲修改拉伸变换。
三段对应三个函数。
经过直方图计算之后,把它显示出来,就知道数据的分布情况了。
直方图性质:
由于直方图是所含像素个数的累加,所以可以把一个图拆成几个不同的子图,岁每个子图求出直方图以后,把直方图累加求和,就是整个图的直方图。
首先,对直方图数组,直方图不是一个数,是每个灰度出现的个数,共有256种颜色,那就是0-255。L就是没有指定它的颜色的整个灰度的最大的容度,实际应用时都是256-1。
容度为0时候,颜色灰度值为0时,为1时先初始化。然后统计一下每个像素的颜色值,作为这个数组的下标,然后把它++。
比如读一个像素是10,那么中括号10++,又读像素又是10,那么p中括号10++,由一个变成2个,由2个变成3个。所以直方图下标是图像的颜色值。
这样就把所有像素循环一遍,就能计算出直方图了。
也可以不做归一化,因为在做比较时,除不除这个没关系,因为是个常数,
lena原图,层次感不太清晰;做直方图均衡化以后,它的层次拉开,亮的增亮。暗的增暗,图片更清晰醒目。
这两幅图的直方图不同,左边的直方图偏暗,特别集中在低值区域,右边的图把直方图拉伸开了,虽然不是恒为1,但是比起来原来这幅图,各种像素值所占的次数出现得比较均衡了,所以叫直方图均衡化。
变换后得到的新直方图不很平坦,理想中得到的应该是每个颜色出现的相等。
扩展了动态范围。原来很窄,现在给拉开了。
简并现象:灰度级减少,但是提高了我们视觉的接受力。均衡化是一种很好的方法。
下面例子:
说明均衡化如何计算。
比如有一幅图,只有8种颜色。列出这幅图每种颜色出现的概率就是直方图。用累积法,直方图它的转换函数依靠的是累积,累积它的概率密度。
如何累积:原始直方图-将原始直方图下一个与上一个相加,即得出累积值。
累积完之后,每个累积点乘以最大的灰度值,加上0.5取整,就得到转变后的颜色。 比如说,原来是0,转变后为0,原来是1,转变后也是0.原来是2,变成1;原来是3,变为2.以此类推。
所以灰度级,有的颜色就去掉了。这样就得到了这种映射关系。原来是什么值,现在改为什么值。下面表中第一行和第四行就是映射关系。
灰度变换就是把像素的值改变,改变的方法有灰度变换法,直方图法,直方图均衡化法。
逐点改变,有一个公式将像素值变大变小,跟周围的邻域没有关系,目的是改善画质,比如图像灰度太集中,可以把图像灰度拉伸一些,更加清晰。
主要运算是点运算。
例1点运算(遍历)对图像进行分段式灰度变换
%用点运算(遍历)对图像进行分段式灰度变换,
close all;
clear all;
clc;
R=imread('xiao-24.bmp'); %输入图像
J=rgb2gray(R); %灰度变换,先要将图像由彩色图变成灰度图
[M,N]=size(J); %获得图像的宽度与高度,即行列数M,N
x=1;y=1; %定义循环变量,行索引变量x,列索引变量y
%对灰度图像J进行分段处理,处理后的结果返回给矩阵H
%J(x,y),H(x,y)都是指示符,指定到该像素
for x=1:M; %从第一行到最后一行
for y=1:N; % 从第一列到最后一列
if(J(x,y)<35); % 对灰度图像J进行分段处理,对于小于35的
H(x,y)=J(x,y)*10;%对于小于35的,乘以10
elseif(J(x,y)>35&&J(x,y)<=75); %灰度范围在35到75之间
H(x,y)=(10/7)*[J(x,y)-5]+50; %用线性变换公式
elseif(J(x,y)>75); %大于75的
H(x,y)=(105/180)*[J(x,y)-75]+150;%用这个公式调整
end
end
end
%遍历完之后,矩阵H就形成了。矩阵J通过遍历将值赋予了矩阵H。因而不需要提前定义
%矩阵H
set(0,'defaultFigurePosition',[100,100,1000,500]);%修改图形图像位置的默认设置
set(0,'defaultFigureColor',[1 1 1])%修改图形背景颜色的设置
figure(1),
subplot(121),imshow(J);
subplot(122),imshow(H);
例2对图像进行非线性灰度变换
%对图像进行非线性灰度变换
close all;
clear all;
clc;
R=imread('xiao-24.bmp'); %输入图像
G=rgb2gray(R); %灰度变换先要将彩色图变成灰度图
J=im2double(G); %将数组转换为类double。
%像素数据类型转化为双精度型,便于后面取对数,做数学运算
%im2double(I),将强度图像I转换为双精度值,并根据需要重新调整数据.I可以是灰度
%强度图像、真彩色图像或二值图像。
H=(log(J+1))/10;%进行常用的对数非线性灰度变换,对数会压缩数据,让灰度值变大
%更密集
%虽然是点运算,但是这里直接用整个数组/矩阵作为操作对象,矩阵支持整体的数学运算
%只是要先将图像数组值转换为double型,否则图像数组型为uint8型,不支持数学运算
set(0,'defaultFigurePosition',[100,100,1000,500]);%修改图形图像位置的默认设置
set(0,'defaultFigureColor',[1 1 1])%修改图形背景颜色的设置
%imhist(G),Histogram of image data图像数据的统计直方图/柱状图。imhist(I)
%calculates the histogram for the grayscale image I. returns the histogram
%counts in counts and the bin locations in binLocations. The number of bins
%in the histogram is determined by the image type.
figure;
subplot(141);imshow(G);
subplot(142);imhist(G);
subplot(143);imshow(H);
subplot(144);imhist(H);
3遍历获取灰度图像直方图,利用L(k+1)=L(k+1)+1游标的指示作用
%方法1,通过点运算-遍历获取灰度图像直方图,利用L(k+1)=L(k+1)+1游标的指示作用
%方法2,直接调用函数imhist,画出直方图
close all;
clear all;
clc;
R=imread('lena.bmp');
[M,N]=size(R);
L=zeros(1,256); %开辟一个直方图数组矩阵,灰度图是256色:0-255,相应的,直方图数组也是
%256色.这个矩阵表示每个颜色出现的次数.matlab不以0位起点,是以1为起点.
%zeros,创建全零数组.X=zeros(sz1,...,szN)返回由零组成的
%sz1×...×szN数组,其中sz1,...,szN 指示每个维度的大小.例如,zeros(2,3) 将返回
%一个2×3矩阵。
%x=1;y=1; %是否在这里定义x,y都可以,地下循环中直接写入x,y,就是定义了x,y了。
%方法一:通过遍历统计画出直方图
for x=1:M;
for y=1:N;
%灰度为k的像素点个数放在数组L[k+1]里面
k=R(x,y); %将某个像素取出来,放在直方图矩阵的下标里
%matlab不以0位起点,是以1为起点.但是像素值还是以0位起点
L(k+1)=L(k+1)+1;%统计各个灰度值的像素,L(k+1)是索引下标,但是前面的
%L(k+1)就会指示到k+1位置上,后面的L(k+1)就指示位置上的内容。这就是游标的作用
end
end
set(0,'defaultFigurePosition',[100,100,1000,500]);%修改图形图像位置的默认设置
set(0,'defaultFigureColor',[1 1 1])%修改图形背景颜色的设置
figure(1),
subplot(121),imshow(R);
subplot(122),bar(L);%bar(L)创建一个条形图,y中的每个元素对应一个条形.如果y是
%矩阵,则bar根据y中的列对条形分组。
axis tight;%使得坐标系的最大值和最小值和你的数据一致
%axis设置坐标轴范围和纵横比.axis tight设置坐标轴显示范围为紧凑型,matlab画图
%会根据画图的数据范围自动调整坐标轴的范围,使得显示的图像或专者曲线可以全部显示
%出来.但有时侯,自动选择的画图范围会在边界处留较大的空白这个时候用axis tight
%可以让坐标轴调整到紧凑地显示图像或曲线,不属留边界的空白
例4通过数学公式调整灰度图像的灰度范围,图像数组整体用公式,不用遍
%通过数学公式调整灰度图像的灰度范围,图像数组整体用公式,不用遍历
close all;
clear all;
clc;
I=imread('lena.bmp');
%像素数据类型转化为双精度型,便于后面做数学运算
I=double(I);
J=(I-80)*255/70; %调整灰度
[M,N]=size(I); %或,M=size(I,1),N=size(I,2)
for x=1:M;
for y=1:N;
if (J(x,y)<0);
J(x,y)=0; %小于0的像素赋值为0.由于是double型,经过上面的J=(I-80)*255/70
%计算数组中的值有可能小于0或大于255。unit8范围是0-255,超出范围的取
%0或255.
elseif (J(x,y)>255);
J(x,y)=255; %大于255的像素赋值为1
end
end
end
set(0,'defaultFigurePosition',[100,100,1000,500]);%修改图形图像位置的默认设置
set(0,'defaultFigureColor',[1 1 1])%修改图形背景颜色的设置
% 如果不讲double型转换回数组unit8型,那图像不显示。图像数组必须是unit8。
% figure;
% subplot(141);imshow(I);
figure;
subplot(141);imshow(uint8(I));
subplot(142);imhist(uint8(I));
subplot(143);imshow(uint8(J));
subplot(144);imhist(uint8(J));
axis tight;%使得坐标系的最大值和最小值和你的数据一致
例5通过imjust()调整灰度图像的灰度范围
%通过imjust()调整灰度图像的灰度范围
close all;
clear all;
clc;
I=imread('lena.bmp');
%imadjust-Adjust image intensity values or colormap.maps the intensity values
%in grayscale image I to new values in J.将灰度图I中的亮度值映射到J中的新值.
%J = imadjust(I,[low_in; high_in],[low_out; high_out])
%即将low_in至high_in之间的值映射到low_out至high_out之间的值.low_in以下与
%high_in以上的值,即low_in以下的值映射到low_out,high_in以上的值映射到
%high_out。
J=imadjust(I,[0.2,0.8],[0.3,0.6]);%进行调整
K=imadjust(I,[0.2,0.8],[0.3,0.6],0.4); %最后一个参数小于1-增加亮度值输出,变亮
H=imadjust(I,[0.2,0.8],[0.3,0.6],4); %最后一个参数大于1-增加暗色值输出,变暗
set(0,'defaultFigurePosition',[100,100,1000,500]);%修改图形图像位置的默认设置
set(0,'defaultFigureColor',[1 1 1])%修改图形背景颜色的设置
figure(1);
subplot(141);imshow(I);
subplot(142);imhist(I)
subplot(143);imshow(J);
subplot(144);imhist(J)
figure(2),
subplot(141),imshow(K);
subplot(142);imhist(K)
subplot(143),imshow(H);
subplot(144);imhist(H)
axis tight;%使得坐标系的最大值和最小值和你的数据一致
通过imjust()调整彩色图像
%通过imjust()调整彩色图像的颜色强度
%imadjust-Adjust image intensity values or colormap.
%J=imadjust(I) maps the intensity values in grayscale image I to new values
%in J.By default,imadjust saturates(浸透使饱和) the bottom 1% and the top 1%
%of all pixel values.This operation increases the contrast of the output image J.
%J=imadjust(RGB,[low_in high_in],___)maps the values in truecolor image RGB
%to new values in J.You can apply the same mapping or unique mappings for
%each color channel.
close all;
clear all;
clc;
I=imread('12.jpg');
J=imadjust(I,[0.2,0.3,0;0.6,0.7,1],[]); %调整彩色图像,[]默认为最大范围
figure;
set(0,'defaultFigurePosition',[100,100,1000,500]);%修改图形图像位置的默认设置
set(0,'defaultFigureColor',[1 1 1])%修改图形背景颜色的设置
subplot(121);imshow(I);
subplot(122);imshow(J);
例6用brightn()调整图像亮度
%用brightn()调整图像亮度
%brightn()增亮或加深颜色图,调整当前图窗中使用颜色图的所有图形对象的颜色
%沿同一方向变换当前颜色图中所有颜色的强度.当beta介于0和1之间时,颜色变亮;当beta
%介于-1和0之间时,颜色变暗.变化的幅度与beta的幅值成正比。
close all;
clear all;
clc;
I=imread('lena.bmp');
figure;
imshow(I);
figure;
subplot(121);brighten(0.6);imshow(I);%大于0小于1,变亮
subplot(122);brighten(-0.6);imshow(I) %大于-1小于0,变暗
例7用stretchlim()寻找对比度拉伸图像的限制
%用stretchlim()和imadjust()增强
%Find limits to contrast stretch image寻找对比度拉伸图像的限制
%contrast,对比,颜色反差,图像阴暗对比度.stretch伸展,拉紧,拉伸
%lowhigh=stretchlim(I) computes the lower and upper limits that can be
%used for contrast stretching grayscale or RGB image I.The limits are
%returned in lowhigh.By default,the limits specify the bottom 1% and the
%top 1% of all pixel values.
close all;
clear all;
clc;
I=imread('xiao-24.bmp');
M=stretchlim(I);%获取最佳输入区间,stretchlim()可计算灰度图像的最佳输入区间
J=imadjust(I,M,[]); %调整灰度范围
figure;
subplot(121);
imshow(I);
subplot(122);
imshow(J);
例8imcomplement做灰度图像/二值图像/彩色图颜色的反转变换-反色变换
%用函数imcomplement做灰度图像/二值图像/彩色图颜色的反转变换
%complement补足,imcomplement(I),computes the complement of the image I.
%X=uint8([255 10 75;44 225 100]);X2=imcomplement(X),X2=uint8([0 245 180;211
%30 155)].这里是uint8型,数值范围是0-255,因而就是计算总数为256,数值的补足255的部分。。
%可用来Reverse Black and White in a Binary Image,Create the Complement of
%an Intensity Image.Create the Complement of a Color Image
close all;
clear all;
clc;
I=imread('lena.bmp');
J=imcomplement(I);
figure;
subplot(121);imshow(I);
subplot(122);imshow(J);
例9imhist()计算RGB彩色图像每种颜色的颜色直方图
%imhist()计算RGB彩色图像每种颜色的颜色直方图
close all;
clear all;
clc;
R=imread('xiao-24.bmp');
set(0,'defaultFigurePosition',[100,100,1000,500]);%修改图形图像位置的默认设置
set(0,'defaultFigureColor',[1 1 1])%修改图形背景颜色的设置
figure;
subplot(141),imshow(R);
subplot(142),imhist(R(:,:,1));
title('R直方图');
subplot(143),imhist(R(:,:,2));
title('G直方图');
subplot(144),imhist(R(:,:,3));
title('B直方图');
例10histeq()对图像做直方图均衡化处理
%函数histeq()对图像做直方图均衡化处理
close all;
clear all;
clc;
I=imread('lena.bmp');
J=histeq(I); %直方图均衡化
set(0,'defaultFigurePosition',[100,100,1000,500]);%修改图形图像位置的默认设置
set(0,'defaultFigureColor',[1 1 1])%修改图形背景颜色的设置
figure;
subplot(141),imshow(I);title('原图');
subplot(142),imshow(J);title('均衡化');
subplot(143),imhist(I,64);title('原图直方图');
subplot(144),imhist(J,64);title('均衡化直方图');
暗的部分变亮,亮的部分变暗,用255减去像素值就可以得到这个结果。
编程思路:
要得到原图的数据,在编程中就反映为数据区的指针
实验效果:
本来背景是暗色的,经过反色处理,到了右边,背景变为浅色,齿轮反之。在左边图中,越浅颜色地方,到了右侧图上,颜色越深。
现在情况是,第一阶段处理完的反色效果的图像将之保存为一个新的文件,现在到了第二阶段,打开第一阶段保存的反色效果文件,作为这次第二阶段的输入文件。
对上面的解释:
二值化:可以说是浅者让它越浅,深者就越深。
编程思路:
二值化的处理可以是一个更一般性的方法--窗口变换:
二值化处理可以看做一个窗口为0的窗口变换。一般的窗口变换窗口不是0.
窗口变换:设定上界和下界。其实是增强了两边的效果,像素强度处于中间的部分是不变的。
所以一般编程时不用编单独二值化处理的函数,只需要用窗口变换函数即可,将阈值上下界相等。
实验效果:
左侧 是原始图像,右侧是二值化处理后的图像。二值化后,深的部分变为黑色,浅的部分变为白色。
二值化的处理过程不是惟一的:选定的阈值不同,处理效果就不同。
灰度化处理方法不唯一
方法1:典型方法,应用最广泛,最符合科学结果。
红绿蓝颜色系统放到黑白电视机上会反映出一种亮度值,灰度计算其实就是通过红绿蓝的值进行相应的比例加权平均得到该像素的亮度值,这个亮度值就反映为我们日常对从白到黑,或从黑到白的灰度变化的感觉。
为什么底下把同一个亮度值赋值给三个变量?在存储的内存空间中,有一个像素是三个字节的,灰度图像在计算机中存储的bmp文件反映为的格式是rgb三个字节取得值完全相同,所以做这个处理计算完亮度之后,把该亮度值,同一个数值分别赋值给rgb的三个字节,那么该像素才能显示具体的亮度值。
这个方法是实数运算--加权求和,在具体运算中很耗时。如果我们在进行嵌入式系统设计师,嵌入式系统本身在单位时间内执行指令少,比较慢,执行性能要求高,那么就要降低执行每个指令所耗时间,那么就要用折中性方法--不那么科学的方法,
方法2:就是耗时较少同时又能达到一定效果的方法
没有实数运算,只有比较。