精华内容
下载资源
问答
  • 图像的特征提取

    2020-12-14 10:20:06
    在经过图像分割得到各种感兴趣区域之后,可以利用下面介绍一些简单区域描绘子作为代表该区域的特征。 MATLAB中,函数regionprops()是用于计算区域描绘子有力工具,语法如下: stats = regionprops(BW,...

    特征提取

    特征的评价标准

    1. 特征应当容易提取
    2. 选取的特征应对噪声和不相关转换不敏感
    3. 应试图寻找最具有区分能力的特征

    简单的区域描绘子及其MATLAB实现

    在经过图像分割得到的各种感兴趣的区域之后,可以利用下面介绍的一些简单的区域描绘子作为代表该区域的特征。

    MATLAB中,函数regionprops()是用于计算区域描绘子的有力工具,语法如下:

    stats = regionprops(BW,properties)
    stats = regionprops(CC,properties)
    stats = regionprops(L,properties)
    stats = regionprops(___,I,properties)
    stats = regionprops(output,___)
    
    1. L是一个标记矩阵,通过前面介绍的连通区标注函数bwlabel()得到。
    2. 返回值D是一个长度为max(L( : ))的结构数组,该结构的域表示每个区域的不同度量,具体取决于properties指定要提取的度量类型。

    ‘Area’ 图像各个区域中像素总个数
    ‘BoundingBox’ 包含相应区域的最小矩形
    ‘Centroid’ 每个区域的质心(重心)
    ‘MajorAxisLength’ 与区域具有相同标准二阶中心矩的椭圆的长轴长度(像素意义下)
    ‘MinorAxisLength’ 与区域具有相同标准二阶中心矩的椭圆的短轴长度(像素意义下)
    ‘Eccentricity’ 与区域具有相同标准二阶中心矩的椭圆的离心率(可作为特征)
    ‘Orientation’ 与区域具有相同标准二阶中心矩的椭圆的长轴与x轴的交角(度)
    ‘Image’ 与某区域具有相同大小的逻辑矩阵
    ‘FilledImage’ 与某区域具有相同大小的填充逻辑矩阵
    ‘FilledArea’ 填充区域图像中的on像素个数
    ‘ConvexHull’ 包含某区域的最小凸多边形
    ‘ConvexImage’ 画出上述区域最小凸多边形
    ‘ConvexArea’ 填充区域凸多边形图像中的on像素个数
    ‘EulerNumber’ 几何拓扑中的一个拓扑不变量——欧拉数
    ‘Extrema’ 八方向区域极值点
    ‘EquivDiameter’ 与区域具有相同面积的圆的直径
    ‘Solidity’ 同时在区域和其最小凸多边形中的像素比例
    ‘Extent’ 同时在区域和其最小边界矩形中的像素比例
    ‘PixelIdxList’ 存储区域像素的索引下标
    ‘PixelList’ 存储上述索引对应的像素坐标

    直方图及其统计特征

    直方图常用统计特征包括以下几种:

    1. 均值:纹理平均亮度的度量
    2. 标准方差:纹理平均对比度的度量
    3. 平滑度:纹理亮度的相对平滑度度量,对于灰度一致的区域,平滑度R等于1,对于灰度级的值有着较大差异的区域,R等于零。
    4. 三阶矩:直方图偏斜性的度量
    5. 一致性:当区域中所有灰度值相等时该度量最大并由此处开始减小
    6. 熵:随机性的度量。熵越大表明随机性越大,信息量也就越大;反之确定性越大,已经都确定当然信息量就越小。

    特征降维

    PCA的MATLAB实现

    coeff = pca(X)
    coeff = pca(X,Name,Value)
    [coeff,score,latent] = pca(___)
    [coeff,score,latent,tsquared] = pca(___)
    [coeff,score,latent,tsquared,explained,mu] = pca(___)
    

    参数说明;

    1. X为原始样本组成n*d的矩阵,其每一行是一个样本特征向量,每一列表示样本特征向量的一维,如X是一个8乘2的样本矩阵,总共又8个样本,每个样本2维。
    2. COEFF:主成分分量,即变换空间的那些基向量,也是样本协方差矩阵的本征向量。
    3. SCORE:主成分,X的低维表示,即X中的数据在主成分分量上的投影
    4. latent:一个包含着样本协方差矩阵本征值的向量

    快速PCA及其实现

    PCA的计算中最主要的工作量是计算样本协方差矩阵的本征值和本征向量,但是当矩阵很大的时候,就会导致MATLAB出现内存耗尽的错误,即使内存足够的话,也会花费很多时间的。

    MATLAB实现:

    function [pcaA V] = fastPCA( A, k )  
    % 快速PCA  
    % 输入:A --- 样本矩阵,每行为一个样本  
    %      k --- 降维至 k 维  
    % 输出:pcaA --- 降维后的 k 维样本特征向量组成的矩阵,每行一个样本,列数 k 为降维后的样本特征维数  
    %      V --- 主成分向量  
    [r c] = size(A);  
    % 样本均值  
    meanVec = mean(A);  
    % 计算协方差矩阵的转置 covMatT  
    Z = (A-repmat(meanVec, r, 1));  
    covMatT = Z * Z';  
    % 计算 covMatT 的前 k 个本征值和本征向量  
    [V D] = eigs(covMatT, k);  
    % 得到协方差矩阵 (covMatT)' 的本征向量  
    V = Z' * V;  
    % 本征向量归一化为单位本征向量  
    for i=1:k  
        V(:,i)=V(:,i)/norm(V(:,i));  
    end  
    % 线性变换(投影)降维至 k 维  
    pcaA = Z * V;  
    % 保存变换矩阵 V 和变换原点 meanVec  
    save('mat.m','V','meanVec');
    

    局部二进制模式

    局部二进制模式(Local Binary Patterns,LBP)最早作为一种有效的纹理描述算子提出的,由于其对图像局部纹理特征的卓越描绘能力而获得十分广泛的应用。LBP特征具有很强的分类能力(Highly Discriminative),较高的计算效率并且对于单调的灰度变化具有不变性。

    基本LBP

    在整个逐行扫描过程结束后,会得到一个LBP响应图像,这个响应图像的直方图被称为LBP统计直方图,或LBP直方图,它常常被最为后续识别工作的特征,因此也被成为LBP特征。

    LBP的主要思想是以某一点与其领域像素的相对灰度作为响应,正是这种相对机制使得LBP算子对于单带哦的灰度变化具有不变性,

    圆形邻域的LBP算子

    基本LBP算子可以被进一步推广为使用不同大小和形状的领域,采用圆形的邻域并结合双线性插值运算使操作者能够获得任意半径和任意数目的领域像素点,一个半径为2的8领域像素的圆形邻域,对于正好处于方格中心的邻域点(左,上,右,下)四个点,直接以该点所在方格的i像素值作为它的值;对于不在像素中心位置的邻域点(倾斜45度的四个黑点),通过双线性插值确定其值。

    统一化LBP算子

    由于LBP直方图大多是针对图像中的各个分区分别计算的,对于一个普通大小的分区区域,对于一个普通大小的分块区域,标准LBP算子得到的二进制模式数目(LBP直方图收集箱数目)较多,而实际的位于该分块区域的像素数目却相对的较少,这将会得到一个过于稀疏的直方图,从而使直方图失去统计意义。因此应该设法减少一些冗余的LBP模式,同时保留足够的具有重要意义描绘能力的模式。

    LBP算子具有一定的半径,类似于模板操作,这里同样要注意LBP算子应用过程的边界问题。由于一般关心的是LBP统计直方图,而不是响应图像的本身,因此实现中一般不需要向外填充边界,而是直接在计算中不包括图像的边界部分。

    应用LBP(u2)(8,2)算子到某个分块图像并获得直方图的实现程序如下:

    %getLBPFea.m  
    function [histLBP, MatLBP] = getLBPFea(I)  
    % 计算分区图像 I 的LBP特征,(8,2),uniform  
    %  
    % 输入:I --- 分区图像  
    %  
    % 返回值: MatLBP --- LBP响应矩阵  
    %               histLBP --- 1维行向量,LBP直方图  
      
    % 获得分块图像I的大小  
    [m n] = size(I);  
    rad = 2;  
    if (m <= 2*rad) || (n <= 2*rad)  
        error('I is too small to compute LBP feature!');  
    end  
      
    MatLBP = zeros(m-2*rad, n-2*rad);  
      
    % 读入 LBP 映射(像素灰度与直方图收集箱索引的映射)  
    load MatLBPMap.mat;  
      
    for ii = 1+rad : m-rad  
        for jj = 1+rad : n-rad  
            nCnt = 1;  
              
              
            % 计算(8,2)邻域的像素值,不在像素中心的点通过双线性插值获得其值  
            nbPT(nCnt) = I(ii, jj-rad);  
            nCnt = nCnt + 1;  
              
            horInterp1 = I(ii-2, jj-2) + 0.5858*( I(ii-2, jj-1) - I(ii-2, jj-2) ); % 水平方向插值  
            horInterp2 = I(ii-1, jj-2) + 0.5858*( I(ii-1, jj-1) - I(ii-1, jj-2) ); % 水平方向插值  
            verInterp = horInterp1 + 0.5858*( horInterp2 - horInterp1 ); % 竖直方向插值  
            nbPT(nCnt) = verInterp;  
            nCnt = nCnt + 1;  
              
            nbPT(nCnt) = I(ii-2, jj);  
            nCnt = nCnt + 1;  
              
            horInterp1 = I(ii-2, jj+1) + 0.4142*( I(ii-2, jj+2) - I(ii-2, jj+1) );  
            horInterp2 = I(ii-1, jj+1) + 0.4142*( I(ii-1, jj+2) - I(ii-1, jj+1) );  
            verInterp = horInterp1 + 0.5858*( horInterp2 - horInterp1 );  
            nbPT(nCnt) = verInterp;  
            nCnt = nCnt + 1;  
              
            nbPT(nCnt) = I(ii, jj+2);  
            nCnt = nCnt + 1;  
              
            horInterp1 = I(ii+1, jj+1) + 0.4142*( I(ii+1, jj+2) - I(ii+1, jj+1) );  
            horInterp2 = I(ii+2, jj+1) + 0.4142*( I(ii+2, jj+2) - I(ii+2, jj+1) );  
            verInterp = horInterp1 + 0.4142*( horInterp2 - horInterp1 );  
            nbPT(nCnt) = verInterp;  
            nCnt = nCnt + 1;  
              
            nbPT(nCnt) = I(ii+2, jj);  
            nCnt = nCnt + 1;  
              
            horInterp1 = I(ii+1, jj-2) + 0.5858*( I(ii+1, jj-1) - I(ii+1, jj-2) );  
            horInterp2 = I(ii+2, jj-2) + 0.5858*( I(ii+2, jj-1) - I(ii+2, jj-1) );  
            verInterp = horInterp1 + 0.4142*( horInterp2 - horInterp1 );  
            nbPT(nCnt) = verInterp;  
                      
              
            for iCnt = 1:nCnt  
                if( nbPT(iCnt) >= I(ii, jj) )  
                    MatLBP(ii-rad, jj-rad) = MatLBP(ii-rad, jj-rad) + 2^(nCnt-iCnt);  
                end  
            end  
        end  
    end  
     
    % 计算LBP直方图  
    histLBP = zeros(1, 59); % 对于(8,2)的uniform直方图共有59个收集箱  
      
    for ii = 1:m-2*rad  
        for jj = 1:n-2*rad  
            histLBP( vecLBPMap( MatLBP(ii, jj)+1 ) ) = histLBP( vecLBPMap( MatLBP(ii, jj)+1 ) ) + 1;  
        end  
    end  
    

    上述算法中围绕每一个中心点,从左侧开始,按照顺时针的顺序访问8个邻域,形成二进制模式位串。在计算直方图时借助vecLBPMap映射表将响应图像MatLBP中的像素灰度映射到其对应的收集箱编号。如灰度为gray(0<=gray<=255)的像素应落入第vecLBPMap(gray+1)号收集箱中。通过下面的函数makeLBPMap来获得映射表vecLBPMap。

    function vecLBPMap = makeLBPMap  
    % 生成(8,2)临域uniform LBP直方图的映射关系,即将256个灰度值映射到59个收集箱中,  
    % 所有的非 uniform 放入一个收集箱中  
      
    vecLBPMap = zeros(1, 256); %初始化映射表  
      
    bits = zeros(1, 8); %8位二进模式串  
      
    nCurBin = 1;  
      
    for ii = 0:255  
        num = ii;  
          
        nCnt = 0;  
          
        % 获得灰度num的二进制表示bits  
        while (num)  
            bits(8-nCnt) = mod(num, 2);  
            num = floor( num / 2 );  
            nCnt = nCnt + 1;  
        end  
          
        if IsUniform(bits) % 判断bits是不是uniform模式  
            vecLBPMap(ii+1) = nCurBin;% 每个uniform模式分配一个收集箱  
            nCurBin = nCurBin + 1;  
        else  
            vecLBPMap(ii+1) = 59;%所有非uniform模式都放入第59号收集箱          
        end  
          
    end  
      
    % 保存映射表  
    save('MatLBPMap.mat', 'vecLBPMap');
    

    函数makeLBPMap中调用了IsUniform(bits)方法来检查二进制模式串bits是否是统一化模式(Uniform Patterns),IsUniform方法的实现如下:

    function bUni = IsUniform(bits)  
    % 判断某一个位串模式 bits 是否是 uniform 模式  
    %  
    % 输入:bits --- 二进制LBP模式串  
    %  
    % 返回值:bUni --- =1,if bits 是uniform模式串;=2,if bits 不是uniform模式串  
      
    n = length(bits);  
      
    nJmp = 0; % 位跳变数(0->1 or 1->0)  
    for ii = 1 : (n-1)  
        if( bits(ii) ~= bits(ii+1) )  
            nJmp = nJmp+1;  
        end  
    end  
    if bits(n) ~= bits(1)  
        nJmp = nJmp+1;  
    end  
      
    if nJmp > 2  
        bUni = false;  
    else  
        bUni = true;  
    end  
    

    MB-LBP及其MATLAB实现

    理论基础

    前述的基于像素相对灰度比较的LBP算子可以很精细地描述图像局部地纹理信息。然而,也正是由于这种特征地局部化特点,使它容易受到噪声的干扰而不够强壮,缺乏对图像整体信息的粗粒度把握。因此MB-LBP被提出以弥补传统LBP的这一不足。起初MB-LBP被作为标准3*3LBP扩展而引入,随后也被用于与LBP算子结合使用。在MB-LBP的计算中,传统LBP算子像素之间的比较被像素块之间的平均灰度的比较所代替,不同的像素块大小代表着不同的观察和分析粒度。

    MATLAB实现

    算法getMBLBPFea()的输入blocksize为块的大小,其默认值为1,即一块仅为一个像素,对应传统的LBP算子。为了求得I中各个像素块的值,首先计算像素块中像素的平均灰度,而后以此灰度平均值作为灰度值,求得了I的低分辨率表示I_MB,此后的阈值化操作只需要对I_MB进行,阈值化的过程和getLMBFeature()中类似。

    function [histLBP, MatLBP, MatLBP_MB] = getMBLBPFea(I, blockSize) 
    % 计算分块区域I的LBP特征,(8,2),uniform 
    % 
    % 输入:I --- 分区图像
    %       blockSize --- MBLBP 中的分块大小,默认值为1 
    % 
    % 返回值: MatLBP --- LBP 响应矩阵
    %        histLBP --- 行向量LBP直方图
    %        MatLBP_MB --- MBLBP的像素块低分辨率显示
     
    if nargin < 2 
        blockSize = 1; 
    end 
     
    %获得分块图像I的大小
    [m n] = size(I); 
     
    %将原始图像依据blockSize分块,计算每块的平均灰度值,对应保存在映射矩阵I_MB中
    mSub = floor(m / blockSize); 
    nSub = floor(n / blockSize); 
     
    mRem = mod(m, blockSize); 
    nRem = mod(n, blockSize); 
    mRem = round(mRem / 2); 
    nRem = round(nRem / 2); 
     
    I_MB = zeros(mSub, nSub); 
     
    for ii = 1:mSub 
        for jj = 1:nSub 
            I_center = I( 1+mRem:mRem+mSub*blockSize, 1+nRem:nRem+nSub*blockSize ); % 取中心区域,不够分出整块的留在两边
            SubRgn = I_center( (ii-1)*blockSize+1 : ii*blockSize, (jj-1)*blockSize+1 : jj*blockSize ); 
            I_MB(ii, jj) = mean( SubRgn(:) ); 
        end 
    end 
     
     
     
    % 剩下的任务就是对分块矩阵的映射I_MB计算blockSize = 1的uniform (8, 2) LBP特征了 
    rad = 2; 
    if (mSub <= 2*rad) || (nSub <= 2*rad) 
        error('I is too small to compute LBP feature!'); 
    end 
     
    MatLBP_MB = zeros(mSub-2*rad, nSub-2*rad); 
     
    % 读入LBP映射(像素灰度与直方图收集箱索引的映射) 
    load Mat/LBPMap.mat; 
     
    for ii = 1+rad : mSub-rad 
        for jj = 1+rad : nSub-rad 
            nCnt = 1; 
             
             
            % 计算(8,2)邻域的像素值,不在像素中心的点通过双线性插值获得其值
            nbPT(nCnt) = I_MB(ii, jj-rad); 
            nCnt = nCnt + 1; 
             
            horInterp1 = I_MB(ii-2, jj-2) + 0.5858*( I_MB(ii-2, jj-1) - I_MB(ii-2, jj-2) ); % 水平方向插值
            horInterp2 = I_MB(ii-1, jj-2) + 0.5858*( I_MB(ii-1, jj-1) - I_MB(ii-1, jj-2) ); % 水平方向插值
            verInterp = horInterp1 + 0.5858*( horInterp2 - horInterp1 ); % 竖直方向插值
            nbPT(nCnt) = verInterp; 
            nCnt = nCnt + 1; 
             
            nbPT(nCnt) = I_MB(ii-2, jj); 
            nCnt = nCnt + 1; 
             
            horInterp1 = I_MB(ii-2, jj+1) + 0.4142*( I_MB(ii-2, jj+2) - I_MB(ii-2, jj+1) ); 
            horInterp2 = I_MB(ii-1, jj+1) + 0.4142*( I_MB(ii-1, jj+2) - I_MB(ii-1, jj+1) ); 
            verInterp = horInterp1 + 0.5858*( horInterp2 - horInterp1 ); 
            nbPT(nCnt) = verInterp; 
            nCnt = nCnt + 1; 
             
            nbPT(nCnt) = I_MB(ii, jj+2); 
            nCnt = nCnt + 1; 
             
            horInterp1 = I_MB(ii+1, jj+1) + 0.4142*( I_MB(ii+1, jj+2) - I_MB(ii+1, jj+1) ); 
            horInterp2 = I_MB(ii+2, jj+1) + 0.4142*( I_MB(ii+2, jj+2) - I_MB(ii+2, jj+1) ); 
            verInterp = horInterp1 + 0.4142*( horInterp2 - horInterp1 ); 
            nbPT(nCnt) = verInterp; 
            nCnt = nCnt + 1; 
             
            nbPT(nCnt) = I_MB(ii+2, jj); 
            nCnt = nCnt + 1; 
             
            horInterp1 = I_MB(ii+1, jj-2) + 0.5858*( I_MB(ii+1, jj-1) - I_MB(ii+1, jj-2) ); 
            horInterp2 = I_MB(ii+2, jj-2) + 0.5858*( I_MB(ii+2, jj-1) - I_MB(ii+2, jj-1) ); 
            verInterp = horInterp1 + 0.4142*( horInterp2 - horInterp1 ); 
            nbPT(nCnt) = verInterp; 
                     
             
            for iCnt = 1:nCnt 
                if( nbPT(iCnt) >= I_MB(ii, jj) ) 
                    MatLBP_MB(ii-rad, jj-rad) = MatLBP_MB(ii-rad, jj-rad) + 2^(nCnt-iCnt); 
                end 
            end 
        end 
    end 
     
    % 还原MatLBP_MB 
    MatLBP = zeros(m-2*rad*blockSize, n-2*rad*blockSize); 
    for ii = 1:mSub-2*rad 
        for jj = 1:nSub-2*rad 
            MatLBP( mRem+(ii-1)*blockSize+1 : mRem+ii*blockSize, nRem+(jj-1)*blockSize+1 : nRem+jj*blockSize ) = MatLBP_MB(ii, jj); 
        end 
    end 
     
     
    % 计算LBP直方图
    histLBP = zeros(1, 59); % 对(8,2)的uniform直方图共有59个收集箱 
     
    for ii = 1:mSub-2*rad 
        for jj = 1:nSub-2*rad 
            histLBP( vecLBPMap( MatLBP_MB(ii, jj)+1 ) ) = histLBP( vecLBPMap( MatLBP_MB(ii, jj)+1 ) ) + 1; 
        end 
    end 
    

    提取MB-LMP特征

    function [histLBP, MatLBP, MatLBP_MB] = getMBLBPFea_33(I, blockSize) 
    % 计算分区图像 I 的LBP特征,3*3,uniform 
    % return value: MatLBP --- LBP 响应矩阵 
    %               histLBP --- 行向量,LBP直方图 
    %               blockSize --- MBLBP中的分块大小,默认值为1
    % 
    % 输入:I --- 分区图像 
    %       blockSize --- 块的大小
    % 
    % 返回值: MatLBP --- LBP 响应矩阵 
    %        histLBP --- 行向量,LBP直方图 
    %        MatLBP_MB --- MBLBP的像素块低分辨率表示 
     
    if nargin < 2 
        blockSize = 1; 
    end 
     
    % 获得分块图像I的大小
    [m n] = size(I); 
     
     
    %将原始图像依据blockSize分块,计算每块的平均灰度值,对应保存在映射矩阵I_MB中
    mSub = floor(m / blockSize); 
    nSub = floor(n / blockSize); 
     
    mRem = mod(m, blockSize); 
    nRem = mod(n, blockSize); 
    mRem = round(mRem / 2); 
    nRem = round(nRem / 2); 
     
    I_MB = zeros(mSub, nSub); 
     
    for ii = 1:mSub 
        for jj = 1:nSub 
            I_center = I( 1+mRem:mRem+mSub*blockSize, 1+nRem:nRem+nSub*blockSize ); % 取中心区域,不够分出整块的留在两边
            SubRgn = I_center( (ii-1)*blockSize+1 : ii*blockSize, (jj-1)*blockSize+1 : jj*blockSize ); 
            I_MB(ii, jj) = mean( SubRgn(:) ); 
        end 
    end 
     
     
     
    % 剩下的任务就是对分块矩阵的映射I_MB计算blockSize = 1的uniform 3*3 LBP特征了 
    rad = 1; 
    if (mSub <= 2*rad) || (nSub <= 2*rad) 
        error('I is too small to compute LBP feature!'); 
    end 
     
    MatLBP_MB = zeros(mSub-2*rad, nSub-2*rad); 
     
    % 读入LBP映射(像素灰度与直方图收集箱索引的映射) 
    load Mat/LBPMap.mat; 
     
    for ii = 1+rad : mSub-rad 
        for jj = 1+rad : nSub-rad 
            nCnt = 1; 
             
             
            % 计算3*3邻域的像素值
            nbPT(nCnt) = I_MB(ii-rad, jj-rad); 
            nCnt = nCnt + 1; 
             
            nbPT(nCnt) = I_MB(ii-rad, jj); 
            nCnt = nCnt + 1; 
             
            nbPT(nCnt) = I_MB(ii-rad, jj+rad); 
            nCnt = nCnt + 1; 
             
            nbPT(nCnt) = I_MB(ii, jj+rad); 
            nCnt = nCnt + 1; 
             
            nbPT(nCnt) = I_MB(ii+rad, jj+rad); 
            nCnt = nCnt + 1; 
             
            nbPT(nCnt) = I_MB(ii+rad, jj); 
            nCnt = nCnt + 1; 
     
            nbPT(nCnt) = I_MB(ii+rad, jj-rad); 
            nCnt = nCnt + 1; 
     
            nbPT(nCnt) = I_MB(ii, jj-rad); 
     
                     
             
            for iCnt = 1:nCnt 
                if( nbPT(iCnt) >= I_MB(ii, jj) ) 
                    MatLBP_MB(ii-rad, jj-rad) = MatLBP_MB(ii-rad, jj-rad) + 2^(nCnt-iCnt); 
                end 
            end 
        end 
    end 
     
    % 还原MatLBP_MB 
    MatLBP = zeros(m-2*rad*blockSize, n-2*rad*blockSize); 
    for ii = 1:mSub-2*rad 
        for jj = 1:nSub-2*rad 
            MatLBP( mRem+(ii-1)*blockSize+1 : mRem+ii*blockSize, nRem+(jj-1)*blockSize+1 : nRem+jj*blockSize ) = MatLBP_MB(ii, jj); 
        end 
    end 
     
     
    % 计算LBP直方图 
    histLBP = zeros(1, 59); % 对于(8,2)的uniform直方图共有59个收集箱 
     
    for ii = 1:mSub-2*rad 
        for jj = 1:nSub-2*rad 
            histLBP( vecLBPMap( MatLBP_MB(ii, jj)+1 ) ) = histLBP( vecLBPMap( MatLBP_MB(ii, jj)+1 ) ) + 1; 
        end 
    end 
    

    图像分区以及MATLAB实现

    直方图无法描述图像的结构信息,而图像的各个区域的局部特征往往差异较大,如果仅对整个图像生成一个LBP直方图,这些局部差异信息就会丢失。分区LBP特征可有效解决这一问题。

    具体的方法是将一幅图适当的划分为P*Q个分区,然后分别计算每个图像分区的直方图特征,最后再将所有块的直方图特征连接成一个复合的特征向量作为代表整个图像的LBP直方图特征。

    编写的函数用来提取图像I的分区LBP特征。其输入r和c分别代表的是分区的行数和列数,nMB给出MB-LBP像素块的大小。函数返回一个向量,它是图像I的复合LBP特征。

    function histLBP = getLBPHist(I, r, c, nMB) 
    % 取得I的分区LBP直方图 
    % 
    % 输入:r,c --- r*c个分区
    %       nMB --- MB-LBP 中块的大小
    % 
    % 返回值:histLBP ---  连接 I 的各个分块LBP直方图而形成的代表 I 的LBP复合特征向量 
     
    [m n] = size(I); 
     
    % 计算分区的大小
    mPartitionSize = floor(m / r); 
    nPartitionSize = floor(n / c); 
     
    for ii = 1:r-1 
        for jj = 1:c-1 
            Sub = I( (ii-1)*mPartitionSize+1:ii*mPartitionSize, (jj-1)*nPartitionSize+1:jj*nPartitionSize ); 
    %        hist{ii}{jj} = getMBLBPFea( Sub, nMB );  %如需提取3*3LBP,请注释此行
            hist{ii}{jj} = getMBLBPFea_33( Sub, nMB );   %如需提取3*3LBP,请打开此注释
        end 
    end 
     
     
    % 处理最后一行和最后一列
    clear Sub 
    for ii = 1:r-1 
        Sub = I( (ii-1)*mPartitionSize+1:ii*mPartitionSize, (c-1)*nPartitionSize+1:n ); 
    %    hist{ii}{c} = getMBLBPFea(Sub, nMB); 
        hist{ii}{c} = getMBLBPFea_33( Sub, nMB ); 
    end 
    clear Sub 
     
    for jj = 1:c-1 
        Sub = I( (r-1)*mPartitionSize+1:m, (jj-1)*nPartitionSize+1:jj*nPartitionSize ); 
    %    hist{r}{jj} = getMBLBPFea(Sub, nMB); 
        hist{r}{jj} = getMBLBPFea_33( Sub, nMB ); 
    end 
    clear Sub 
     
    Sub = I((r-1)*mPartitionSize+1:m, (c-1)*nPartitionSize+1:n); 
    %hist{r}{c} = getMBLBPFea(Sub, nMB); 
    hist{r}{c} = getMBLBPFea_33( Sub, nMB ); 
     
     
    % 连接各个分块的LBP直方图形成复合特征向量
    histLBP = zeros(1, 0); 
    for ii = 1:r 
        for jj = 1:c 
            histLBP = [histLBP hist{ii}{jj}]; 
        end 
    end 
    

    在默认的情况下函数getLBPHist()提取(8,2)圆形邻域的LBP特征。如果需要提取3*3的LBP特征,可以将代码中的getMBLBPFea的调用替换为getMBLBPFea_33的调用。

    展开全文
  • 底层次的特征需要任何形状信息(空间关系信息)就可以从图像中自动提取的特征,这样看来,阈值方法就是作为点处理一种低层次特征提取方式,所有低层次方法都可以作为高层次特征提取预处理,从而在图像中...

    目录

    一阶边缘检测

    基本一阶差分算子

    Robert算子

    Prewitt算子

    Sobel算子

    Canny算子

     二阶边缘检测

    拉普拉斯算子

    LoG算子

    各种边缘检测算子的比较


     低层次的特征是不需要任何形状信息(空间关系的信息)就可以从图像中自动提取的特征,所有低层次方法都可以作为高层次特征提取的预处理,从而在图像中找到形状(边缘)。

    边缘是一组相连的像素集合,边缘周围像素的灰度值存在强烈的反差。边缘是图像的最基本特征,是图像局部特性不连续的结果,广泛存在于物体与背景之间、物体与物体之间、基元与基元之间,既是图像分割所依赖的重要特征,也是纹理特征的重要信息源和形状特征的基础。边缘检测在计算机视觉、图像分析等应用中起着重要的作用,是图像分析与识别的重要环节。

    常见的边缘类型主要有:屋顶状边缘(它位于灰度值从增加到减少的变化转折点)、阶跃型边缘(两边的像素的灰度值有着显著的不同)、斜坡边缘、脉冲型边缘等几种,如下图所示。

    经典的边缘检测算法利用空间域滤波方法考察图像中每个像素在其邻域内的灰度变化,利用轮廓处图像灰度值局部不连续性和邻域相似性的特点,求取图像局部梯度来判断图像变化的剧烈程度。

    边缘检测包括一阶边缘检测和二阶边缘检测。

    一阶边缘检测

    图像边界发生亮度级的阶梯变化,边缘是阶梯变化的位置,一阶微分可以使阶梯变化增强,而当信号没有变化时,一阶微分不响应。

    一阶边缘检测算子是具有方向依赖性的,即水平边缘检测算子在水平方向上的差分(差分模拟微分)为0,形成水平相邻像素的插值,可以用于检测垂直边缘而不能检测水平边缘。

    水平边缘检测算子用于检测垂直边缘:

    Ex(x,y) = |Px,y - Px+1, y|  (1)

    注意,水平边缘检测算子检测到的是垂直方向上的边缘,垂直边缘算子检测到的是水平方向上的边缘。

    垂直边缘检测算子:

    Ey(x,y) = |Px,y - Px, y+1|  (2)

    将两个算子相结合,即可得到同时检测水平边缘和垂直边缘的算子:

    Ex,y = |2*Px,y - Px+1, y - Px, y+1|  (3)

    卷积核如下图所示:

    利用这个算子的边缘检测实现很简单,伪代码如下:

    edge(pix) 
        newpic = zeros(pic)
    
        for x : 0...rows(pic)-2
                for y : 0...cols(pic)-2
                    newpic(x,y) = |2*pic(x,y) - pic(x,y+1) - pic(x+1,y)|
        return newpic

    边缘检测完成后,经常会使用阈值方法选取最亮点,得到优化的边缘。阈值的选取决定最亮点的数量,阈值越大选取得到的点越少,阈值的选取可以凭经验,也可以由边缘数据自动的选取。

    基本一阶差分算子(梯度算子)

    在实际的图像处理中,为了降低计算量,微分运算都用差分来近似,两个相邻点的灰度差分可近似表示为微分运算。

    由泰勒展开式可得以下两式:

    f(x + \triangle x) = f(x) + \triangle x*f{}'(x) + \triangle x^2 / 2 * f{}''(x) + O(\triangle x^3)  (4)

    f{}'(x) = \frac{f(x+\triangle x)-f(x))}{\triangle x} - O(\triangle x)  (5)

    由此可得,相邻两点的差值是一阶导数的估算值,O(\triangle x)决定了估算误差,减小误差的一个办法是:在相邻的像素间插入一个新的像素来实现。

    f{}'(x) = \frac{f(x+\triangle x)-f(x-\triangle x))}{2\triangle x} - O(\triangle x^2)  (6)

    \triangle x < 1的情况下,差分模拟微分的误差大大减小,一阶差分模板就如下所示:

    水平差分算子
    垂直差分算子

    Robert算子

    Robert交叉算子(Robert,1965)是最早期的边缘检测算子,利用两个模板,计算对角线上的差值,这两个模板如下图所示。

                                                           

    实现过程中,利用这些模板卷积得到的最大值作为边缘存储值,边缘点Ex,y是在图像点Px,y对这两个模板进行卷积得到的两个值中的较大者。

    (7)

    Robert交叉算子检测到的边缘结果如图所示。

    Prewitt算子

    Prewitt边缘检测算子,是在基本差分算子上扩展得到的,由于它检测的是变化,必然对噪声及图像亮度的阶梯式变化有所响应(功能上相当于频域中的高通滤波器)。

    Prewitt算子如下图所示。

    水平Prewitt算子
    垂直Prewitt算子

    Prewitt算子给出两个结果,沿x、y两个坐标轴的亮度变化率,两个向量的和就是该点的边缘向量,向量包括强度和方向。

    图像的局部梯度可以用来判断图像变化的剧烈程度,对一个连续图像函数f(x,y)它在位置(x,y)的梯度可表示为一个矢量:

        (8)

    上式中Gx和Gy分别沿x方向和y方向的偏导数,这个矢量的幅度(∇f)和方向角φ(x,y)分别为: 

      (9)

    方向角可以用于确定边缘方向。

    在实际的图像处理中,为了降低计算量,微分运算都用差分来近似,两个相邻点的灰度差分可近似表示为微分运算:

      (11)

    即∇xf近似∂f/∂x,∇yf近似∂f/ ∂y 。将式(11)代入式(9)得梯度

      (12)

    以Prewitt水平算子为例,边缘检测的实现伪代码如下:

    Prewitt_x(pic) = - \sum pic(0,y) + \sum(2,y) 

    Prewitt_y(pic) = - \sum pic(x,0) + \sum(x,2) 

    我们把Pewitt算子应用于正方形图像[参见图(a),就可以得到边缘强度和方向,分别如图(b)和图(d)所示,其中(d)中没有包括边界点,只有执行点的边缘方向。图(d)所示的边缘方向显示的是度数,其中0°和360°表示水平方向,朝右方向,而90°表示垂直方向,朝上方向。

    由于该算子的均值处理特性,虽然边缘点的区域较宽,但边缘数据比前面介绍的一阶算子更清晰,使亮度变化明显的区域得到加强。边缘方向以图像方式表示显得不太清晰,利用的向量方式表示更好,如图(c)所示。利用向量方式,正方形角点处的边缘方向数据显然无法很好表示(由于一阶导数在这些点不连续)。 

    Sobel算子

    Sobel边缘检测算子是Prewitt检测算子的扩展,在中心像素位置取权重2,由向量方式确定边缘的两个掩码mask组成的,Sobel算子曾长期是最受欢迎的边缘检测算子,比Prewitt算子的检测性能好(最明显的优点是抑制噪声的性能)。

    水平Sobel算子
    垂直Sobel算子

    如图所示,Sobel 边缘检测算子也是分两个方向的,分别计算偏x方向的梯度分量Gx,偏y方向的梯度分量Gy,求绝对值,压缩到 [0, 255]区间,然后合并梯度G(x, y) = Gx + Gy,就是sobel边缘检测后的图像了。 将Sobel算子的边缘检测实现划分为五个步骤:

    (1) 计算Gx与Gy与模板每行的卷积。

    (2) 两个3x3矩阵的卷积即将每一行每一列对应相乘然后相加。

    (3) 求得3*3模板运算后的Gx、Gy。

    (4) 求Gx^2 + Gy^2的平方根或者直接对Gx和Gy取绝对值后求和。

    (5)设置一个阈值,运算后的像素值大于该阈值输出为全1,小于该阈值输出为全0。

    顺便提一下5阶Sobel模板(不常用):

    基于Sobel算子的边缘检测效果:

    Canny算子

    Canny算子是在Sobel算子的基础上进行优化的,Canny在考察了边缘检测算子在边缘检测中的应用后,提出了边缘检测的三个原则:  

    (1)  准确性,无附加响应的最优检测(减少噪声响应),即对轮廓的误检率要尽可能低,主要包括两方面,一方面在原始图像中边缘出现的位置应该都能在检测结果中有对应的边缘点;另一方面轮廓检测结果也没有虚假的边缘。 

    通过最优化平滑处理来实现,最常用的是高斯滤波(Canny认为),高斯滤波可能会将边缘放大(区域变宽)。

    (2)  精确性,即对边缘的定位要精确,检测到的边缘位置要和原始图像上对应边缘的中心位置充分接近,尽量保证检测到的轮廓线的中心就是原始图像轮廓的中心;

    可以通过非极大值抑制(相当于峰值检测)来实现,非极大值抑制只返回项脊处的点,其他的点会被抑制掉。这其实是一种细化处理:返回的是正确位置上的边缘点连成的更细的边缘线,尽量使边缘的宽度变成1个像素,这个像素在梯度方向上的梯度值是最大的。如果一个点两侧的梯度小于该点上的梯度,那么它就是极大值,所以我们需要先得到边缘法线上的梯度值。

    (3)  单边响应,即对同一边缘要有低的响应次数,理想状态是原始图像上只有一个边缘点时,检测出来的边缘也只保持一个点。

    Canny算子的计算步骤如下:

    1. 高斯滤波器平滑图像,去除噪声;
    2. 一阶差分偏导计算梯度值和方向,通过Sobel算子实现;
    3. 对梯度值不是极大值的地方进行抑制,把不是极值的点,全部置0,去掉了大部分弱的边缘,所以图像边缘会变细;
    4. 用双阈值连接图上的联通点,设置双阈值 t1, t2, t1 <= t2 大于 t2 的点肯定是边缘;小于 t1 的点肯定不是边缘;在 t1, t2 之间的点,通过已确定的边缘点,发起8领域方向的搜索(广搜),图中可达的是边缘,不可达的点不是边缘。最后得出 canny 边缘图。

     二阶边缘检测

    拉普拉斯算子

    Prewitt梯度算子利用一阶差分:f '(x) = f(x) - f(x - 1)得到内核模板,对于二阶差分,有

                                                                   f '(x) = (f(x + 1) - f(x)) - (f(x) - f(x - 1))

    化简后:f '(x) = f(x - 1) - 2 f(x)) + f(x + 1)。

    提取前面的系数:[1, -2, 1],二维的情况下,同理可得f '(x, y) = -4 f(x, y) + f(x-1, y) + f(x+1, y) + f(x, y-1) + f(x, y+1)提取各个系数,得到模板的形式

    图像函数的拉普拉斯变换定义为:

    计算公式:

     考虑写对角线上像素的情况下的改进型拉普拉斯算子模板为:

    梯度计算公式:

    与原图卷积运算即可求出边缘。 

    拉普拉斯算子作为一个二阶算子,它的优点是:

    • 可以利用零交叉的性质进行边缘定位
    • 可以确定一个像素是在边缘暗的一边还是亮的一边

    跟Sobel梯度算子相比,它的缺点是:

    • 不能抑制噪声(对噪声敏感)
    • 不能检测边缘的方向(模板不带方向信息)。

    LoG算子

    边缘检测关注的是像素变化明显的边缘而非细节,而且某些边缘检测算子对噪声敏感,所以,在进行边缘检测之前,一般都通过选定的空间滤波器进行平滑去噪,在保持图像边缘信息的前提下,减少图像的细节和噪声。

    试想一种科学的边缘提取方案:

    1)高斯滤波对图像进行平滑去噪

    2)利用拉普拉斯算子进行滤波

    进而进化出了另外一种提取边缘的算法:对高斯滤波函数进行二阶求导,拿高斯二阶导数生成的模板再去进行图像滤波。这种方式就是拉普拉斯算子与高斯平滑过程一起利用零交叉找边缘。

    已知高斯函数模型:

    计算得到高斯函数的拉普拉斯算子为:

    上式称为高斯型拉普拉斯算子LoG。

    近似的5✖5阶LoG模板:

    高斯型函数的目的是对图像进行平滑处理,平滑处理减少了噪声的影响,拉普拉斯算子的目的是提供一幅用零交叉确定边缘位置的图像。

    缺点

    • 边缘由许多闭合环的零交叉点决定
    • 零交叉点的计算比较复杂

    优点

    • 零交叉点图像中的边缘比梯度边缘细
    • 抑制噪声的能力和反干扰性能

    尽管LoG的诸多优点,但是Sobel算子依然是被更多应用的边缘检测算子。

    各种边缘检测算子的比较

    选取特定的边缘检测算子取决于应用本身,许多应用并不要求复杂的高级算子。

    通过对比一阶微分算子和二阶微分算子的处理效果发现:一阶微分处理通常会产生较宽的边缘,二阶微分处理对细节有较强的响应,如细线和孤立点,一阶微分处理一般对灰度阶跃有较强的响应,而二阶微分处理对灰度级阶梯变化产生双响应,二阶微分在图像灰度值变化相似时,对线的响应要比对灰度阶梯变化强,而且对点的响应比线响应强。因此,在图像中应用二阶微分处理比一阶微分处理形成增强细节的能力更好,而一阶微分处理主要应用于图像的边缘增强和提取。 

    展开全文
  • 图像特征词典原理及实现 原理 一.Bag of features: 基础流程 特征提取 2. 学习 “视觉词典(visual vocabulary)” 3. 针对输入特征集,根据视觉词典进行量化 聚类是实现 visual vocabulary /codebook关 键 ...

    图像特征词典原理及实现

    原理

    一.Bag of features: 基础流程

    1. 特征提取在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述2. 学习 “视觉词典(visual vocabulary)”在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述3. 针对输入特征集,根据视觉词典进行量化

    聚类是实现 visual vocabulary /codebook的关

    • 无监督学习策略
    • k-means 算法获取的聚类中心作为 codevector
    • Codebook 可以通过不同的训练集协同训练获得
    • 一旦训练集准备足够充分, 训练出来的码本( codebook)将
    具有普适性

    码本/字典用于对输入图片的特征集进行量化
    • 对于输入特征,量化的过程是将该特征映射到距离其最接近
    的 codevector ,并实现计数
    • 码本 = 视觉词典
    • Codevector = 视觉单词

    在这里插入图片描述
    4.把输入图像转化成视觉单词(visual words)
    的频率直方图在这里插入图片描述

    5.构造特征到图像的倒排表,通过倒排表快速索引相关图像

    给定图像的bag-of-features直方图特征,如何
    实现图像分类/检索?
    在这里插入图片描述
    给定输入图像的BOW直方图, 在数据库中查找 k 个最近邻
    的图像
    对于图像分类问题,可以根据这k个近邻图像的分类标签,
    投票获得分类结果
    当训练数据足以表述所有图像的时候,检索/分类效果良

    6.根据索引结果进行直方图匹配

    代码及实现

    1.生成词典
    .`# -- coding: utf-8 --
    import pickle
    from PCV.imagesearch import vocabulary
    from PCV.tools.imtools import get_imlist
    from PCV.localdescriptors import sift
    ##要记得将PCV放置在对应的路径下
    #获取图像列表
    imlist = get_imlist(‘D:/Visual_Studio_Code/data/first1000/’) ###要记得改成自己的路径
    nbr_images = len(imlist)
    #获取特征列表
    featlist = [imlist[i][:-3]+‘sift’ for i in range(nbr_images)]
    #提取文件夹下图像的sift特征
    for i in range(nbr_images):
    sift.process_image(imlist[i], featlist[i])
    #生成词汇
    voc = vocabulary.Vocabulary(‘ukbenchtest’)
    voc.train(featlist, 1000, 10)
    #保存词汇
    #saving vocabulary
    with open(r’D:\Visual_Studio_Code\data\first1000\vocabulary.pkl’, ‘wb’) as f:
    pickle.dump(voc, f)
    print (‘vocabulary is:’, voc.name, voc.nbr_words)

    2把数据导入数据库

    # -*- coding: utf-8 -*-
    import pickle
    from PCV.imagesearch import imagesearch
    from PCV.localdescriptors import sift
    from sqlite3 import dbapi2 as sqlite
    from PCV.tools.imtools import get_imlist
    ##要记得将PCV放置在对应的路径下
    #获取图像列表
    imlist = get_imlist('D:/Visual_Studio_Code/data/first1000/')##记得改成自己的路径
    nbr_images = len(imlist)
    #获取特征列表
    featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]
    # load vocabulary
    #载入词汇
    with open(r'D:\Visual_Studio_Code\data\first1000\vocabulary.pkl', 'rb') as f:
        voc = pickle.load(f)
    #创建索引
    indx = imagesearch.Indexer('testImaAdd.db',voc)
    indx.create_tables()
    # go through all images, project features on vocabulary and insert
    #遍历所有的图像,并将它们的特征投影到词汇上
    for i in range(nbr_images)[:1000]:
        locs,descr = sift.read_features_from_file(featlist[i])
        indx.add_to_index(imlist[i],descr)
    # commit to database
    #提交到数据库
    indx.db_commit()
    con = sqlite.connect('testImaAdd.db')
    print (con.execute('select count (filename) from imlist').fetchone())
    print (con.execute('select * from imlist').fetchone())
    
    

    3。实现
    .`# -- coding: utf-8 --
    import pickle
    from PCV.localdescriptors import sift
    from PCV.imagesearch import imagesearch
    from PCV.geometry import homography
    from PCV.tools.imtools import get_imlist

    load image list and vocabulary
    #载入图像列表
    imlist = get_imlist(‘first1000/’)
    nbr_images = len(imlist)
    #载入特征列表
    featlist = [imlist[i][:-3]+‘sift’ for i in range(nbr_images)]

    #载入词汇
    with open(‘first1000/vocabulary.pkl’, ‘rb’) as f:
    voc = pickle.load(f)

    src = imagesearch.Searcher(‘testImaAdd.db’,voc)

    #index of query image and number of results to return
    #查询图像索引和查询返回的图像数
    q_ind = 0
    nbr_results = 20

    regular query
    #常规查询(按欧式距离对结果排序)
    res_reg = [w[1] for w in src.query(imlist[q_ind])[:nbr_results]]
    print (‘top matches (regular):’, res_reg)

    #load image features for query image
    #载入查询图像特征
    q_locs,q_descr = sift.read_features_from_file(featlist[q_ind])
    fp = homography.make_homog(q_locs[:,:2].T)

    #RANSAC model for homography fitting
    #用单应性进行拟合建立RANSAC模型
    model = homography.RansacModel()
    rank = {}

    load image features for result
    #载入候选图像的特征
    for ndx in res_reg[1:]:
    locs,descr = sift.read_features_from_file(featlist[ndx]) # because ‘ndx’ is a rowid of the DB that starts at 1
    # get matches
    matches = sift.match(q_descr,descr)
    ind = matches.nonzero()[0]
    ind2 = matches[ind]
    tp = homography.make_homog(locs[:,:2].T)
    # compute homography, count inliers. if not enough matches return empty list
    try:
    H,inliers = homography.H_from_ransac(fp[:,ind],tp[:,ind2],model,match_theshold=4)
    except:
    inliers = []
    # store inlier count
    rank[ndx] = len(inliers)

    #sort dictionary to get the most inliers first
    sorted_rank = sorted(rank.items(), key=lambda t: t[1], reverse=True)
    res_geom = [res_reg[0]]+[s[0] for s in sorted_rank]
    print (‘top matches (homography):’, res_geom)

    #显示查询结果
    imagesearch.plot_results(src,res_reg[:8]) #常规查询
    imagesearch.plot_results(src,res_geom[:8]) #重排后的结果

    展开全文
  • 1 - 引言 在我们进行图像识别时候,往往是将图片中的特征来表示整张图片让计算机进行识别,基本上表示一...无论哪种情形,选择用来作为描绘子的特征都应尽可能地对大小、平移和旋转敏感 2 - 表示 图像分割技...

    1 - 引言

    在我们进行图像识别的时候,往往是将图片中的特征来表示整张图片让计算机进行识别,基本上表示一个区域涉及两种选择:

    1. 外部特征
    2. 内部特征

    下一步就是基于所选择的表示来描述区域

    当我们关注的重点是形状特征时,可选择一种外部表示;而当关注的重点是内部属性如颜色和纹理时,可以选择一种内部表示。无论哪种情形,选择用来作为描绘子的特征都应尽可能地对大小、平移和旋转不敏感

    2 - 表示

    图像分割技术以沿着边界或包含在区域中的像素的形式产生原始数据,标准做法是使用某种方案将分割后的数据精简为更便于描绘子计算的表示。下面让我们学习一下各种表示方法

    2.1 - 边界追踪算法

    该算法输出的是排序后的点序列,我们假设:

    1. 处理的是二值图像,其目标和背景点分别标位1和0
    2. 图像已使用值为0的边界填充,因而消除了目标与图像边界合并的可能性

    给定一个二值区域R或其边界,追踪R的边界或给定边界的算法由如下步骤组成:

    1. 令起始点b0b_0为图像中左上角标记为1的点。使用c0c_0表示b0b_0西侧的邻点。从c0c_0开始按顺时针方向考察b0b_0的8个邻点。令b1b_1表示所遇到的值为1的第一个邻点,并直接令c1c_1是序列中b1b_1之前的点。存储b0b_0b1b_1的位置,以便在步骤5中使用
    2. b=b1b=b_1c=c1c=c_1
    3. 从c开始按顺时针方向行进,令b的8个邻点为n1,n2,,n8n_1,n_2,\dots,n_8找到标记为1的第一个nkn_k
    4. b=nkb=n_kc=nk1c=n_{k-1}
    5. 重复步骤3和步骤4
      当算法停止时,所找到的b点的序列就构成了排列后的边界点的集合

    在这里插入图片描述

    2.2 - 佛雷曼(Freeman)链码

    链码用于表示由顺次连接的具有指定长度和方向的直线段组成的边界。这种表示基于这些线段的4连接或8连接。每个线段的方向使用一种数字编号方案编码,如图所示,以这种方向性数字序列表示的编码称为佛雷曼(Freeman)链码。
    链码的一次差分为,通过计算链码中分隔两个相邻像素的方向变化的数(按逆时针方向计算前一个数字变化到后一个数字所需的步数),其中第一元素是通过使用链码的最后一个元素和第一个元素间的转变来计算得到的。例如,4方向链码0231,得到的一次差分为3212,其中3为1逆时针转到0需3步;2为0逆时针转到2需2步;1为2逆时针转到3需1步;2为3逆时针转到1需2步。

    在这里插入图片描述

    2.3 - 使用最小周长多边形的多边形近似(MPP)

    一副图像我们可以用多边形拟合它的形状。
    在这里插入图片描述
    我们的目的就是使用合适的最大可能单元大小,以最少的定点数来生产MPP,并且我们可以发现构成边界的多边形每个转向要么是一个凸定点,要么是一个凹顶点。
    注意的是凹顶点(黑色)有一个对应的“镜像”顶点,位于凹顶点的对角处
    在这里插入图片描述
    因此,我们的算法就只需要关注这些顶点

    MPP算法

    令W(白)和B(黑)分别表示凸顶点镜像凹顶点
    寻找MMP的算法使用两个“爬行”点:

    • 白色的爬行垫(WcW_c):WcW_c沿凸顶点(w)爬行
    • 黑色的爬行垫(BcB_c):BcB_c沿镜像凹顶点(B)爬行。

    算法首先令Wc=Bc=V0W_c=B_c=V_0v0v_0是一个MPP顶点),VLV_L表示最后一个MPP顶点,VkV_k表示正在考察的当前顶点。
    sgn(a,b,c)det(A)sgn(a,b,c)\equiv det(A)
    (det(A)是A的行列式)
    VL,VkV_L,V_k和两个爬行点之间存在如下三个条件之一:

    1. VkV_k位于通过VL,Wc(V_L,W_c)的直线的正的一侧,即sgn(WL,Wc,Vk)&gt;0sgn(W_L,W_c,V_k)&gt;0
    2. VkV_k位于通过VL,Wc(V_L,W_c)的直线的负的一侧,或者VkV_kVL,Wc(V_L,W_c)共线,即sgn(WL,Wc,Vk)0sgn(W_L,W_c,V_k)\leq 0。同时,VkV_k位于通过(VL,Bc)(V_L,B_c)的直线的正的一侧,或者VkV_k(VL,Bc)(V_L,B_c)共线,即sgn(VL,Bc,Vk)0sgn(V_L,B_c,V_k)\geq 0
    3. VkV_k位于通过VL,Bc(V_L,B_c)的直线的负的一侧,即sgn(VL,Bc,Vk)&lt;0sgn(V_L,B_c,V_k)&lt;0

    如果条件1成立,则下一个MPP顶点是WCW_C并且我们令VL=WcV_L=W_c;然后我们令Wc=Bc=VLW_c=B_c=V_L来重新初始化该算法,并在VLV_L之后的下一个顶点继续执行算法

    如果条件2成立,则VkV_k编程一个候选的MPP顶点。在这种情况下,如果VkV_k是凸顶点,则令Wc=VkW_c=V_k;否则,我们置Bc=VkB_c=V_k然后,我们使用列表中的下一顶点继续执行算法

    如果条件3成立,则下一个MPP顶点是BcB_c,并且令VL=BcV_L=B_c;然后我们令Wc=Bc=VLW_c=B_c=V_L来重新初始化该算法,并用VLV_L之后的下一个顶点继续执行算法

    当算法再次到达第一个顶点时,算法结束,此时算法已经处理了多边形中的所有顶点。

    3 - 边界描绘子

    3.1 - 一些简单的描述子

    1. 边界的长度
      边界的长度是最简的描述子之一。一条边界上的像素数量可以给出其长度的粗略近似。
    2. 边界的长轴与短轴
      边界B的直径定义为
      Diam(B)=maxij[D(pi,pj)]Diam(B)=max_{ij}[D(p_i,p_j)]
      pi,pjp_i,p_j是边界上的点,Dpj,pjD(p_j,p_j)是定义pip_ipjp_j之间的距离。直径的值和连接组成该直径两个端点的直线段(该直线称为边界的长轴)的方向是边界的有用描述子,边界的短轴定义为与长轴垂直的直线,且由边界与两个轴相交的4个外部点所组成的方框(该方框称为基本矩形),可以全完包围该边界
    3. 边界的偏向率
      长轴与短轴之比成为边界的偏心率

    3.2 - 形状数

    链码边界的一次差分取决于起始点。一条基于链码的边界的形状数,定义为最小量级的一次差分,即对链码的一次差分进行循环,得到的值最小的差分码为形状数。

    3.3 - 傅里叶描述子

    下图显示了xy平面内的一个K点数字边界,从任意点x0y0(x_0,y_0)开始,以逆时针方向在该边界上行进时,会遇到坐标对x0,y0,(x1,y1),(x2,y2),,(xk1,yk1)(x_0,y_0),(x_1,y_1),(x_2,y_2),\dots,(x_{k-1},y_{k-1})这些坐标可以表示为x(k)=xk,y(k)=ykx(k)=x_k,y(k)=y_k的形式,此外,每个坐标都可当做一个复数来处理

    s(k)=x(k)+jy(k)s(k)=x(k)+jy(k)
    式中有k=0,1,2,,K1k=0,1,2,\dots,K-1
    s(k)的傅里叶变换为
    a(u)=k=0K1s(k)ej2πuk/Ka(u)=\sum_{k=0}^{K-1}s(k)e^{-j2\pi uk/K}
    式中u=0,1,2,,K1u=0,1,2,\dots,K-1复系数a(u)a(u)称为边界的傅里叶描述子。这些系数的傅里叶反变换可恢复s(k)
    s(k)=1Ku=0K1a(u)ej2πuk/Ks(k)=\frac{1}{K}\sum_{u=0}^{K-1}a(u)e^{j2\pi uk/K}

    然而,假设仅使用前P个傅里叶系数而不使用所有系数,等同于上式中令a(u)=0,u&gt;P1a(u)=0,u&gt;P-1结果s(k)s(k)的如下近似:
    s^(k)=1Ku=0P1a(u)ej2πuk/P\hat s(k)=\frac{1}{K}\sum_{u=0}^{P-1}a(u)e^{j2\pi uk/P}

    尽管求s^(k)\hat s(k)的每个成分时仅使用了P项,但k的范围仍然是从0到K-1,也就是说,在近似边界中存在同样数量的点,但项数不像在每个点的重建中那么多

    由于高频成分说明精细细节,而低频成分决定全局形状,因此P越小,边界丢失的细节就越多

    在这里插入图片描述

    3.4 - 统计矩

    如图(a),它显示了一段边界,图(b)显示了以任意变量rr的一维函数g(r)g(r)描述的线段,该函数是这样获得的:先将该线段的两个端点连接,然后旋转该直线,直至其为水平线段,此时所有的点的坐标也旋转同样的角度

    g(r)g(r)归一化为单位面积,并把它当作直方图来处理,换句话说,g(ri)g(r_i)现在作为值rir_i出现的概率来处理,此时,r为一个随机变量,故n阶矩为
    un(r)=i=0K1(rim)ng(ri)u_n(r)=\sum_{i=0}^{K-1}(r_i-m)^ng(r_i)
    式中,m=i=0K1rig(ri)m = \sum_{i=0}^{K-1}r_ig(r_i)

    K是边界上的点数,un(r)u_n(r)直接与g(r)g(r)的形状相关。例如,二阶矩u2(r)u_2(r)度量曲线关于r的均值扩展程度,而三阶矩u3ru_3(r)度量曲线关于均值的对称性

    在这里插入图片描述

    4 - 区域描述子

    4.1 - 简单的区域描述子

    1. 区域的面积
      区域的面积定义为该区域中像素的数量
    2. 区域的周长
      区域的周长是其边界的长度
    3. 致密性
      致密性定义为(周长)2/^2/面积
    4. 圆周率
      圆周率即一个区域的面积与具有相同周长的一个圆(最致密形状)的面积之比。周长为P的一个圆的面积P2/4πP^2/4\pi。因此,圆周率RcR_c由下式给出:
      Rc=4πAp2R_c=\frac{4\pi A}{p^2}
      A是所讨论的区域面积,P是其周长
    5. 其他
      用作区域描述子的其他简单测度包括灰度值的均值和中值,最小灰度值和最大灰度值,以及其高于和低于均值的像素数

    4.2 - 拓扑描述子

    拓扑学研究未受任何变形影响的图形的特质,前提是该图形未被撕裂或粘连。
    例如,图(a)显示了一个带有两个孔洞的区域。如果一个拓扑描述子由该区域内的孔洞数量来定义,那么这种性质明显不受拉伸或旋转变换的影响。
    另一个对区域描述有用的拓扑特性是连通分量的数量。如图4(b)显示了一个具有3个连通分量的区域。

    在这里插入图片描述

    图形中孔洞的数量 H 和连通分量的数量 C ,可用于定义欧拉数 E :E = C - H

    欧拉数也是一种拓扑特性。例如,图所示的区域有分别等于 0 和 −1 的欧拉数。
    在这里插入图片描述

    4.3 - 纹理

    描绘区域的一种总要方法是量化该区域的纹理内容

    出现处理中用于描述区域纹理的三种主要方法是:

    1. 统计方法(平滑、粗糙、粒状的等纹理特征)
    2. 结构方法(像元的排列,如基于规则间距平行线的纹理描述)
    3. 频谱方法(基于傅里叶频谱特性,主要用于检测图像中的全局周期性,方法是识别频谱中的高能量的窄波峰)

    4.3.1 - 统计方法

    描述纹理的最简单方法之一是使用一副图像或一个区域的灰度级直方图的统计矩。令Z是表示灰度的一个随机变量,并令p(zi),i=0,1,2,,L1p(z_i),i=0,1,2,\dots,L-1为相应的直方图,其中L是不同灰度级的数量,关于其均值的Z的第n阶矩为
    un(z)=i=0L1(zim)np(zi)u_n(z)=\sum_{i=0}^{L-1}(z_i-m)^np(z_i)
    m是z的均值(平均灰度)
    m=i=0L1zip(zi)m=\sum_{i=0}^{L-1}z_ip(z_i)

    注意u0=1,u1=0u_0=1,u_1=0二阶矩[方差σ2(z)=uz(z)\sigma^2(z)=u_z(z)]在纹理描述中特别重要。它是灰度对比度的度量,可用于建立相对平灰度的描述子,例如度量
    R(z)=111+σ2(z)R(z)=1-\frac{1}{1+\sigma^2(z)}
    对于恒定灰度区域为0(该区域方差为0),而对于较大的sigma2(z)sigma^2(z)值,其接近于1,因为对灰度级图像方差值增大而增大的。

    三阶矩是直方图偏斜度的度量,而四阶矩是直方图相对平坦度的度量,五阶矩和更高阶矩不容易与直方图形状联系起来,但它们的确提供了纹理内容的进一步量化辨别。

    在这里插入图片描述

    使用直方图计算得到的纹理度量不懈怠像素彼此之间的相对位置的信息,但是这个信息很重要,所以我们使用一种方法叫共生矩阵

    令Q是定义两个像素彼此相对位置的一个算子,并考虑一副具有L个可能灰度级的图像f,令G为一个矩阵,其元素gijg_{ij}是灰度为ziz_izjz_j的像素对出现在f中有Q所指定的位置处的次数,按照这种方法形成的矩阵成为灰度共生矩阵

    在这里插入图片描述

    在这里插入图片描述

    4.3.2 - 结构方法

    结构法的基本思想是,一个简单的“纹理基元”可借助一些规则用于形成更复杂的纹理模式,这些规则限制基元(或这些基元)的可能排列的数量。

    4.3.3 - 频谱方法

    对纹理描述有用的傅里叶频谱的三个特征:

    1. 频谱中突出的尖峰给出纹理模式的主要方向;
    2. 频率平面中尖峰的位置给出模式的基本空间周期;
    3. 采用滤波方法消除任何周期成分而留下非周期性图像元素,然后采用统计技术来描述。
    展开全文
  • 在介绍算法前我们首先放一张效果图来看一看(SURF算法的使用效果),同时这篇文章我们更多的是要讲清楚原理,并关心具体的数学推导和意义所在,所以文中尽可能省略整个算法中的数学部分,可以作为算法入门的一个...
  • 纹理是灰度在空间以一定的形式变换产生的图案,直方图是描述图像中像素灰度级分布的工具,可以用直方图或其统计特征作为图像的纹理特征。 其中最常用的是灰度直方图,英文灰度具有一定的稳定性,对大小、方向都...
  • 灰度变化较大地方,因为ORB特征定义就是与周围点一样点,与转换成LBP图谱类似,以某点为圆心,选择合适点数作为比较值,在总数目范围内规定一个阈值,一样点数超过这个阈值,即为特征点。...
  • 但是,在使用它们之前,必须对这些数字图像进行处理 - 分析和操作,以提高其质量或提取一些可以使用信息。 常见的图像处理任务包括显示; 基本操作如裁剪,翻转,旋转等;;图像分割,分类和特征提取;图像恢复;...
  • 图像处理——图像

    2020-10-16 11:05:42
    图像的一维熵可以表示图像灰度分布的聚集特征,却能反映图像灰度分布的空间特征; 为了表征这种空间特征,在一维熵的基础上引入能够反映灰度分布空间特征的特征量来组成图像的二维熵; 选择图像的邻域灰度均值作为...
  • 自然事物可以被模拟信号作为载体直接传输或者处理,比如声音和图像,这里声音就是振动而图像识别本质就是光感受,我们可以通过声波和光波来传输声音和图像,虽然这两种方式不是那么统一。实际上完全可以用...
  •  图像灰度化处理可以作为图像处理预处理步骤,为之后图像分割、图像识别和图像分析等上层操作做准备。 意义: 很多简单识别算法对于颜色依赖性强,灰度化之后矩阵维数下降,运算速度大幅度提高,并且...
  • 利用SAR遥感手段,可以对地物实现多极化、多波段、多视角观测,获得的图像特征信息丰富,含有幅度、相位和极化等多种信息,弥补了可见光、红外等其它成像方式不足。在SAR海洋应用中,利用SAR图像进行舰船目标...
  • 该模型引入了变化域非局部自相似性作为图像重建先验信息,同时在八邻域空间计算多方向广义全变分正则化约束,从而更好地保护了图像结构特征,进一步地,使用增广拉格朗日理论对模型进行去约束化、求解,提出了...
  • 低层次特征需要任何形状/空间关系信息就可以图像中自动提取基本特征,如:常用地阈值方法就是作为点处理一种低层次特征提方式。所有低层次方法都可以应用于高层次特征提取,从而在图像中找到形状。在...
  • 实际上全参考和无参考的界限是非常明显的无论是基于,手工设计的特征,还是基于深度网络自适应的特征的方法都只用到失真图像的信息的可以视为无参考的方法。而全参考则可以获取参考图像的信息的方法。但介于二者之间...
  • 这篇文章主要介绍了python 基于opencv 绘制图像轮廓示例,帮助大家更好利用pythonopencv库处理图像...其实边缘主要是作为图像的特征使用,比如可以用边缘特征可以区分脸和手;而轮廓主要用来分析物体形态,...
  • 在低质量指纹图像,特别是存在较严重非线性形变指纹图像中,细节点方向属性不够可靠,使得以细节点对作为参考对齐局部方向场图像的方法效果佳。提出一种改进局部方向场图像对齐和匹配方法,能够明显改善局部对齐...
  • 为了克服传统照片图像拼接方法中利用特征线进行不同照片之间公共交界线定位准确缺点,提出一种“几何模型切分”人脸纹理图像生成算法。通过对人脸几何模型进行切分,以切分后模型图片轮廓作为...
  • 用实验方法研究了光致聚合物中全息存储再现图像质量动态特性,以信噪比损失作为图像质量变化衡量指标,进行了暗增长和均匀后曝光过程监测图像实验。实验结果表明,在暗增长和均匀后曝光过程中,再现图像强度和...
  • 摘 要:指纹图像采集过程常会造成对比度强等非线性失真,基于模糊逻辑处理方法常用于改善指纹图像质量。研究了模糊特征平面增强算法和基于广义模糊算子的图像增强算法,将两种算法应用于指纹图像对比度增强,并对...
  • (反应图像特征的点) **图像的角点(corner point)**作为图像关键的局部结构特征,通常被描述成灰度强度变化连续的点,被称为灰度图像上的奇异特征点。 角点属于特征点,而特征点包括了角点以及其他点。因此可以...
  • 但是,在使用它们之前,必须对这些数字图像进行处理 - 分析和操作,以提高其质量或提取一些可以使用信息。常见的图像处理任务包括显示; 基本操作如裁剪,翻转,旋转等;;图像分割,分类和特征提取;图像恢复;...
  • 实际上,在进行目标特征计算时,这些小块往往是完整的目标,特征的计算可能会有误差。利用输入图像作为掩模图像,输入图像与其边界交集作为标记图像,便可提取出与图像边界连接的目标。标记图像包含每一个与图像...
  • 其实边缘主要是作为图像的特征使用,比如可以用边缘特征可以区分脸和手;而轮廓主要用来分析物体形态,比如物体周长和面积等,可以说边缘包括轮廓。寻找轮廓操作一般用于二值图像,所以通常会使用阈值分割或...
  • 4.0图像分割概述

    2018-08-04 15:50:08
    图像分割是图像分析过程中最重要步骤之一,分割处区域可以作为后续特征提取目标对象。 图像分割分类  图像分割算法方法和种类非常多,一般基于图像灰度值的不连续性或其相似性。连续性是基于图像灰度...
  • 针对在此图像中选取对应块,实现车辆速度实时检测问题,分析了车身的特征图像中车道线倾斜角度,选择车灯作为对应块,选取车灯存在候选区域;然后根据车灯对称性强度筛选车灯带,实现车灯准确定位,并把...
  • 事情起因是这样,我们可以利用模型检测人脸关键点,利用这些关键点就可以作为特征输入模型进行一些处理。但是视频中人动来动去,因为人在视频中位置,远近,角度都有可能一样。Procrustes analysis[1]...
  • 对于监控对象身高,衣着等特征可以在较模糊图像中获得,但是对人脸部分特征,却必须要清晰的图像才能获得[1]。如果可以对人脸进行针对性监视,就可以使得应用安全监控部门获得更多安全保证。而人脸自动...
  • 图像理解

    2020-02-26 13:48:46
    做目标检测有一段时间了,今天看着论文突发奇想,私以为对目标检测仿佛可以归结为两个大方面: (1)直观物理概念 ...将图像作为矩阵来处理,数学意义纯粹矩阵,表征为灰度特征。通过分析数据差异,低秩...

空空如也

空空如也

1 2 3 4 5 ... 14
收藏数 274
精华内容 109
关键字:

不可以作为图像特征的是