本文主要是为了更好地理解图像特征,理解各方法的原理。
转载请注明出处 https://mp.csdn.net/console/editor/html/105090183
图像模式识别的一般步骤为:输入图像--图像预处理--特征提取--特征选择--图像分类--输出结果。
图像特征主要有:颜色特征、形状特征、纹理特征和空间关系特征。
本文主要介绍颜色特征,并给出matlab上实现的demo。
颜色特征
颜色特征是一种全局特征,描述了图像或图像区域内所对应景物的表面性质。一般颜色特征是基于像素点的特征,所有的像素点对该图像或图像区域都有贡献。由于颜色对图像的方向、大小等变化不敏感,不能很好地捕获对象的局部特征。
颜色特征描述可分为:颜色直方图、颜色矩(颜色分布)、颜色集、颜色聚合向量和颜色相关图。
颜色直方图
能简单描述图像中颜色的全局分布,即不同颜色在图像中所占的比例,不受图像旋转和平移变化的影响,特别适用于描述难以自动分割的图像和不需要考虑物体空间位置的图像。其缺点在于:无法描述图像中颜色的局部分布及每种色彩所处的空间位置,即无法描述图像中某一具体的对象或物体。
最常用的颜色空间:RGB颜色空间、HSV颜色空间。
颜色直方图特征匹配方法:直方图相交法、距离法、中心距法、参考颜色表法、累加颜色直方图法。
lena = importdata('lena512color.tiff');
nBins = 256;
%% matlab的程序
% 绘制直方图
rHist_M = imhist( lena(:,:,1),nBins );
gHist_M = imhist( lena(:,:,2),nBins );
bHist_M = imhist( lena(:,:,3),nBins );
figure;
% % 将直方图曲线绘制到同一张图上
% plot(1:nBins, rHist_M, 'r', 1:nBins, gHist_M, 'g', 1:nBins, bHist_M, 'b'); axis([0,255, -inf, inf])
subplot(131); bar( 0:255, rHist_M, 'r' ); title('R直方图'); xlabel('灰度值'); ylabel('出现的频次')
subplot(132); bar( 0:255, gHist_M, 'g' ); title('G直方图'); xlabel('灰度值'); ylabel('出现的频次')
subplot(133); bar( 0:255, bHist_M, 'b' ); title('B直方图'); xlabel('灰度值'); ylabel('出现的频次')
hist_M = rHist_M+gHist_M+bHist_M;
figure; bar(0:255, hist_M); title('matlab得到的总直方图'); xlabel('灰度值'); ylabel('出现的频次')
%% 根据原理编写
% 绘制直方图
[m,n,~] = size(lena);
rHist_S = zeros(1,nBins);
for k = 0:255
rHist_S(k+1) = length( find(lena(:,:,1)==k) );
end
gHist_S = zeros(1,nBins);
for k = 0:255
gHist_S(k+1) = length( find(lena(:,:,2)==k) );
end
bHist_S = zeros(1,nBins);
for k = 0:255
bHist_S(k+1) = length( find(lena(:,:,3)==k) );
end
figure;
subplot(131); bar( 0:255, rHist_S, 'r' ); title('R直方图'); xlabel('灰度值'); ylabel('出现的频次')
subplot(132); bar( 0:255, gHist_S, 'g' ); title('G直方图'); xlabel('灰度值'); ylabel('出现的频次')
subplot(133); bar( 0:255, bHist_S, 'b' ); title('B直方图'); xlabel('灰度值'); ylabel('出现的频次')
hist_S = rHist_S+gHist_S+bHist_S;
figure; bar(0:255, hist_S); title('自编程序的总直方图'); xlabel('灰度值'); ylabel('出现的频次')
颜色矩
颜色矩以数学方法为基础,通过计算矩来描述颜色分布。是AMA Stricker和M Orengo提出的,一种简单有效的颜色特征表示方法。由于颜色信息主要分布在低阶矩中,所以用一阶矩、二阶矩和三阶矩足以表达图像的颜色分布。该方法的优点是:不需要颜色空间量化,特征向量维数低;但是该方法的检索效率比较低,实际应用中常用来过滤图像,以缩小检索范围。
三个颜色矩的数学定义:
其中,表示彩色图像第j个像素的第i个颜色分量,N表示图像中的像素个数。
RGB图像的前三阶颜色矩组成一个9维直方图向量,即图像的颜色特征表示为:
function vectors = FcnColorMoments(img)
hsv = rgb2hsv(img);
hImg = hsv(:,:,1);
sImg = hsv(:,:,2);
vImg = hsv(:,:,3);
[m,n] = size(hImg);
N = m*n;
% 求一阶矩-均值
hMean = mean2( hImg );
sMean = mean2( sImg );
vMean = mean2( vImg );
% 求二阶矩-方差
hSig = sqrt( sum(sum((hImg-hMean).^2))/N );
sSig = sqrt( sum(sum((sImg-sMean).^2))/N );
vSig = sqrt( sum(sum((vImg-vMean).^2))/N );
% 求三阶矩-斜度
h3 = sum( sum( (hImg-hMean).^3 ) );
hSke = ( h3/N )^(1/3);
s3 = sum( sum( (sImg-sMean).^3 ) );
sSke = ( s3/N )^(1/3);
v3 = sum( sum( (vImg-vMean).^3 ) );
vSke = ( v3/N )^(1/3);
vectors = [ hMean, hSig, hSke, sMean, sSig, sSke, vMean, vSig, vSke ];
end
颜色集
颜色集是对颜色直方图的一种近似,首先将图像从RGB颜色空间转换为视觉均衡的颜色空间(如HSV空间),并将颜色空间量化为若干个bins。然后,用色彩自动分割技术将图像分为若干个区域,每个区域用颜色空间的某个颜色分量来索引,将图像表达为一个二进制的颜色索引集。在图像匹配中,比较不同颜色集之间的距离和色彩区域的空间关系。
颜色集同时考虑了颜色空间的选择和颜色空间的划分,通常使用HSL空间。
颜色聚合向量
针对颜色直方图和颜色矩无法表达图像色彩的空间位置,Pass提出图像的颜色聚合向量。将属于直方图每个bin的像素分为两部分,如果该bin内的某些像素所占的连续区域面积大于给定的阈值,则该区域内的像素作为聚合像素,否则为非聚合像素。
假设分别表达直方图第i个bin中聚合像素和非聚合像素的个数,图像的颜色聚合向量可表达为
,而
是该图像的直方图。颜色聚合向量中包含了颜色分布的空间信息,因此会有更好的检索效果。
使用https://blog.csdn.net/u014655590/article/details/25108297给的示例进行matlab实验操作:
- 量化:一般采用均匀量化;
- 划分连通区域:对重新量化后的像素值矩阵,根据像素间的连通性把图像划分为若干个连通区域(可视为一个最大的像素集合)。对于一个区域C,任意两个像素点p,p'∈C,且p=p1,p2,…,..pn=p',在区域C中p,p'之间都存在一个通路。
- 判断聚合性:统计每个独立的连通域C中的像素数,并设定一个阈值t(一般为总像素的1%),来判断C中的像素是聚合的还是非聚合的。按照判断依据分别统计各连通区域中聚合像素的总数和非聚合像素的总数。
- 得到结果:假设
分别代表重新量化后的第i个颜色分量重聚合像素和非聚合像素的总书,则(αi,βi)称为第i个颜色分量的像素对,则图像的颜色聚合向量(即该图像的颜色特征)可表示为:
% 需要提前给定的数据:图像,量化个数(此处为3),阈值
img = [ 22 10 21 22 15 16
24 21 13 20 14 17
23 17 38 23 17 16
25 25 22 14 15 14
27 22 12 11 17 18
24 21 10 12 15 19];
thresh = 4;
% 第一步:量化
% 实质是降维,使特征更加紧凑。10-19对应1,20-29对应2,30-39对应3
img( img>9 & img <20 ) = 1;
img( img>19 & img <30 ) = 2;
img( img>29 & img <40 ) = 3;
% 第二步:划分连通区域
maxV = max( img(:) );
minV = max( min(img(:)),1 );
result = zeros( size(img) );
curNum = 0;
colorArea = {1,2,3}; % 实际,已知会分为3类
for i = minV: maxV
curImg = bwlabel( img==i ); % 对每个数字的二值图像进行连通域的查找
for j = 1:max( curImg(:) )
curImg(curImg==j) = curNum + j; % 将当前二值图像的连通值+之前的连通值
end
colorArea{i}= (curNum+1):(curNum+j);
curNum = curNum + length( unique(curImg) )-1; % 记录当前连通值
result = result + curImg; % 将所得连通图像相加,为最后的连通图像
end
% 第三步: 判断聚合性
labelSum = zeros( 1,curNum );
for i = 1:curNum
labelSum(1,i) = sum( result(:)==i );
end
labelSumBool = labelSum>thresh; % 查找符合条件的连通域索引,非连通域索引
colorVector = zeros( 2,3 ); % 已知会分为3个,第一行为聚合像素数,第二行为非聚合像素数
for i = 1:curNum
% 先判断是第几类的
for j = 1:3
aa = colorArea{j};
if ismember(i,aa)
if labelSumBool(i) == 1
colorVector(1,j) = colorVector(1,j)+labelSum(i);
else
colorVector(2,j) = colorVector(2,j)+labelSum(i);
end
break;
end
end
end
% 第四步:得到结果
vecots = [ colorVector(:,1)', colorVector(:,2)', colorVector(:,3)' ];
颜色相关图
颜色相关图是图像颜色分布的另一种表达方式,不但刻画了某种颜色的像素占比,还表达了颜色随距离变换的空间关系,反映了颜色之间的空间关系。如果考虑任何颜色之间的相关性,颜色相关图会非常复杂庞大。一种简化方式是颜色自动相关图,仅仅考虑具有相同颜色的像素之间的空间关系。
图像中某像素记为I(x,y),包含的颜色有。假设两种颜色之间的距离为d,将生成这样的直方图:
(1)bin的个数为n的平方(颜色的组合数目);
(2)对于每个bin,大小为,其中*
表示像素值为
的两个像素的空间距离,统计这样的像素个数;
(3)若要设置不同的距(共D个),bin的维数为(m*n*D);
(4)只考虑相同颜色之间关系,就称为颜色自相关图,bin的维数为(n*D)。
颜色相关图可视为用颜色对<x,y>索引的表,其中<x,y>的第k个分量表示颜色为c(x)的像素和颜色为c(y)的像素之间的距离小于k的概率。
示例使用灰度共生矩阵来求解,参考文献【灰度共生矩阵和颜色自相关矩阵的matlab实现-菅小艳】。具体操作步骤及涉及原理如下:
- 每个通道bin的个数设为2,则bins个数为(2^2)* (2^2)* (2^2)=64,对图像进行量化处理;
- 设两像素的空间距离为2,计算满足条件的所有像素个数;
图中,(0,0)为当前颜色对,蓝色像素为满足空间距离为2的像素。此处采用灰度共生矩阵来计算
close all; clear; clc;
img = imread('lena.tiff');
out = FcnColorCorrelogram(img, 2);
%% 颜色自相关图矩阵的计算
% 将RGB图像量化为4*4*4的二维图像I
function output = FcnColorCorrelogram(img, d)
% 图像的量化
imgR = img(:,:,1);
imgG = img(:,:,2);
imgB = img(:,:,3);
bitR = 2; % bit量化数
bitG = 2;
bitB = 2;
sizeColor = (2^bitR) * (2^bitG) * (2^bitB); % 包含的颜色种数:4*4*4
R1 = bitshift(imgR, -(8-bitR)); % 移位操作
G1 = bitshift(imgG, -(8-bitG));
B1 = bitshift(imgB, -(8-bitB));
I = R1 + G1*2^bitR + B1*2^bitR*2^bitB; % 量化后的图像,包含4*4*4=64种颜色
% 计算距离为d的颜色自相关图向量
temp = zeros( sizeColor, 1 );
os = Offset(d);
s = size(os);
for i = 1:s(1)
offset = os(i,:);
glm = GLCMatrix(I, offset, sizeColor);
temp = temp + glm;
end
hc = zeros( sizeColor, 1 );
for j = 0:sizeColor-1
hc(j+1) = numel( I(I==j) ); % 统计量化图像中,每个量化值的像素个数
end
output = temp./(hc+eps); % eps是一个随机数,避免分母为零而报错
output = output/(8*d);
end
%======= 求所有距离的偏移量 =======
function os = Offset(d)
[r,c] = meshgrid( -d:d, -d:d );
r = r(:); % 向量化
c = c(:);
os = [r c];
bad = max( abs(r), abs(c) ) ~= d; % 只要最大的满足d便是满足条件的
os(bad, :) = [];
end
%% 灰度共生矩阵--纹理特征
function out = GLCMatrix(img, offset, n1)
% 输入: img:输入图像
% offset:偏移量
% n1:图像中包含的像素值个数
s = size(img);
[r, c] = meshgrid( 1:s(1), 1:s(2) );
r = r(:);
c = c(:);
r2 = r + offset(1);
c2 = c + offset(2);
% 去掉下表超出图像边界的像素和他的邻接像素
bad = c2<1 | c2>s(2) | r2<1 | r2>s(1) ;
index = [ r c r2 c2 ];
index(bad, :) = [];
% 分别以(r,c)和(r2,c2)为索引扎到图像img中对应的像素值向量(v1, v2)
v1 = img( sub2ind(s, index(:,1), index(:,2)) );
v2 = img( sub2ind(s, index(:,3), index(:,4)) );
v1 = v1(:);
v2 = v2(:);
ind = [v1 v2];
bad = v1~=v2 ; % 去掉像素值不相同的行
ind(bad, :) = [];
if isempty(ind)
oneGLCM2 = zeros(n1);
else
% 计算v1和v2相同的像素对数,并用n1*n1矩阵列出来
oneGLCM2 = accumarray( ind+1, 1, [n1, n1] );
end
out = [];
for i = 1:n1
out = [ out oneGLCM2(i,i) ];
end
% 输出:偏移量为offset的灰度共生矩阵
out = out(:);
end