三、均匀LBP算子的matlab代码(含旋转不变形)
均匀模式改进的LBP算法,能有效的将256维度的灰度影像降为59维,原始的LBP算子最终是生成8位二进制数LBP码,每个二进制位有两种变化情况,则经过原始LBP算子处理后的类型应有-1种,即256种(“0”也算是一种)。对于半径为R的圆形区域内含有P个邻域点,类型总数的计算则为-1,其计算复杂度达到o(2n)。邻域点P个数的选择,对整个过程的处理影响是非常大的。前人在后续的研究中提出了一种“等价模式”(Uniform Pattern)的LBP算子,该算子可以有效地对复杂的-1种类型中降低维度。他们认为,在实际的处理当中,绝大多数LBP模式的8进制编码中从0到1或者从1到0的跳变次数不会超过两次。每一次0到1或者1到0的跳变都可以表示纹理发生明显变化。均匀模式LBP算子,就是对一个二进制序列的约束,符合该模式下的二进制编码从0到1或者从1到0的跳变次数不超过2次。该LBP算子极大的提高编码的运算,可有效提高建筑物信息的提取。均匀模式的LBP算子跳变次数的计算公式如式2-6所示。
其中,s(x)为上述提及的符号函数,I(n)表示第n个点对应的灰度值,I(c)为中心像素对应的灰度值,P表示有P种类别。如果计算出的跳变次数小于等于2,则分别代表一类,跳变次数大于2的其他情况则不属于纹理特征变化,则应归为一类,次数大于2所得到的结果设为。加入了旋转不变性的的计算公式如式2-7所示。
其中,ROR(LBP,i)是用来计算LBP值向左或者向右移i位的结果。
function out=LBP(image)%均匀模式下用
%构建LBP图像
%使用圆形邻域,等分选取n点
%构造移位前后lbp映射表
%n为邻域个数
h = findobj('Tag','edit5');
edit5_string = get(h,'String');
n=str2double(edit5_string);
map=mapOfP2shiftedP(n);
%global RGB_image;
lbp=R_LBP(image);
[height,width]=size(lbp);
for i=1:height
for j=1:width
lbp(i,j)=map(lbp(i,j));
end
end
out=lbp;
end
map映射函数:
function map=mapOfP2shiftedP(n)
%构建由移位前LBP值到最小移位LBP值的map
Key=num2cell(0:2^n-1);
mat_Val=zeros(2^n,1);
NoneUniform=0;
for i=0:n-1
isEven=mod(i,2);
NoneUniform=NoneUniform+isEven*2^i; %构造一个非均匀模式
end
for i=0:2^n-1
min_num=uint8(i);
number=uint8(i);
for j=1:n-1
if min_num>=number
min_num=number;
end
temp=number;
number=bitshift(number, 1); %循环左移找到最小LBP值(旋转不变性)
if temp>=(2^(n-1))
number=number+1;
end
end
if isUniformMode(min_num,n)
mat_Val(i+1)=min_num;
else
mat_Val(i+1)=NoneUniform; %非均匀模式统一为一种模式 第59种
end
end
Val=num2cell(mat_Val);
map=containers.Map(Key,Val);
%end
这里把二进制序列放到整形数组中,方便处理,有点粗暴。
function flag=isUniformMode(x,n)
flag=1; %是否均匀模式
S=zeros(n+1,1);
m=x; %余数
for j=n-1:-1:0 %对比特位的循环放在外层可以提升效率,这里这样写是为可读性起见
if m<2^j
S(j+2)=0;
else
S(j+2)=1;
m=m-2^j;
end
end
S(1)=S(n+1);
num=0;
for j=1:n
if S(j+1)~=S(j)
num=num+1;
end
if num>2
flag=0;
break;
end
end
%end
均匀模式的LBP算子可以在原始LBP算子或者圆形LBP算子的基础上进行改进,以下代码需要设计好GUI界面之后才能有效运行。
function [Uniform_LBP_image]=Uniform_LBP(img)
global LBP_image RGB_image;
%img=RGB_image;
h = findobj('Tag','popupmenu3');
popupmenu3_string = get(h,'String');
popupmenu3_value = get(h, 'Value');
current_option = popupmenu3_string{popupmenu3_value};
lbp=0;
if strcmp(current_option,"均匀模式的原始LBP算子")
map=mapOfP2shiftedP(8);
%global RGB_image;
lbp=LBP_origin(RGB_image);
[height,width]=size(lbp);
for i=1:height
for j=1:width
lbp(i,j)=map(lbp(i,j));
end
end
elseif strcmp(current_option,"均匀模式的圆形8领域LBP算子")
lbp=LBP(img);
else
msgbox("没有该算法!");
return;
end
%lbp=R_LBP(img);
n=8;
%LBP_image=lbp/(2^n-1);
%Uniform_LBP_image=LBP_image;
Uniform_LBP_image=lbp;
LBP_image=lbp;
figure,imshow(LBP_image);
end
在设计GUI界面的代码当中,每一个function 函数的最后一行其实不需要加end,这里为了方便理解,就全加上了。