图像特征提取方法
LBP方法
Local Binary Pattern,局部二值化模式,具有灰度不变性和旋转不变性,计算简单,常用在人脸检测上。
计算方式
原始LBP算子为3x3大小的kernel,以被3x3领域覆盖的中心像素值作为阈值,从左到右,从上到下,以此填充0(小于阈值)和1(大于阈值),然后按顺时针读取二进制值作为中心元素的新的像素值。如下图示意:

OpenCV中原始代码:通过位运算提高运算速度获取中心元素的值。
template <typename _tp>
void getOriginLBPFeature(InputArray _src,OutputArray _dst)
{
Mat src = _src.getMat();
_dst.create(src.rows-2,src.cols-2,CV_8UC1);
Mat dst = _dst.getMat();
dst.setTo(0);
for(int i=1;i<src.rows-1;i++)
{
for(int j=1;j<src.cols-1;j++)
{
_tp center = src.at<_tp>(i,j);
unsigned char lbpCode = 0;
lbpCode |= (src.at<_tp>(i-1,j-1) > center) << 7;
lbpCode |= (src.at<_tp>(i-1,j ) > center) << 6;
lbpCode |= (src.at<_tp>(i-1,j+1) > center) << 5;
lbpCode |= (src.at<_tp>(i ,j+1) > center) << 4;
lbpCode |= (src.at<_tp>(i+1,j+1) > center) << 3;
lbpCode |= (src.at<_tp>(i+1,j ) > center) << 2;
lbpCode |= (src.at<_tp>(i+1,j-1) > center) << 1;
lbpCode |= (src.at<_tp>(i ,j-1) > center) << 0;
dst.at<uchar>(i-1,j-1) = lbpCode;
}
}
}
改进
3x3正方形的kernel不满足灰度不变性和旋转不变性,原因在于原始的LBP算子只能覆盖一个固定的正方形区域,当尺寸改变时不能正确地反应像素点周围的纹理信息。为了适应不同尺度的纹理特征,将3x3正方形区域修改成圆形领域,对圆形领域内的点进行采样获取,便具备灰度不变性,对于光照有很强的鲁棒性。但此时还不具备旋转不变性,需要通过旋转LBP圆形领域获取不同的LBP特征值,选取最小值作为中心像素值即可,这样无论如何旋转图片,取得LBP特征值总是一样的。

还有其他LBP模式,如Uniform Pattern LBP特征等等,详情可看这篇文章
HOG
Histogram of Oriented Gradient,方向梯度直方图,常用在行人检测中,利用HOG+SVM分类器。HOG主要通过计算统计局部区域的梯度方向直方图构成特征量,将其作为SVM分类的输入。具有光照不变性。
计算过程
- 灰度化
- 使用Gamma矫正进行进行归一化,调节图像的对比度,降低图像局部阴影和光照变化的影响,抑制噪声
- 计算每个像素的梯度,获取轮廓信息,像素点(x,y)处的梯度计算
- 将图像划分为几个小区域(cell),统计每个小区域的梯度直方图,将几个小区域(cell)组合成大区域(block),做归一化,再作为特征量
- 将图像中几个Block的特征量串联起来,作为最终可供分类使用的特征向量
更详细过程,请看参考文章
Haar特征提取
Haar特征常和AdaBoost结合使用,用于检测人脸。Haar主要使用特征模板进行检测任务,特征模板有四类:边缘特征,线性特征,中心特征和对角线特征。
特征值的计算是白色区域减去黑色区域,反应了灰度变化情况,举例如边缘特征,因为如果区域无明显变化的话,白色减黑色区域像素值为0,否则会产生较大差值。
参考文章 :图像算法之八:特征提取算法之Haar
Harris角点检测
Harris角点检测,利用滑动窗口在图像上进行滑动,比较滑动前后灰度变化,当存在灰度较大变化,就认为存在角点。
具体数学过程:参考这篇文章,主要我理解的过于简单,没想到背后数学原理要这么复杂,一时还不知道该怎么描述。
LoG
LoG(Laplacian of Gaussian)边缘检测算子,是二阶拉普拉斯-高斯边缘提取算法,先进行高斯滤波然后拉普拉斯边缘加测,高斯滤波去除噪声,拉普拉斯算子对边缘进行进行检测。
Canny边缘检测
canny边缘检测流程:详细可参考这篇文章
- 去噪:对图像进行去噪平滑处理
- 计算图像梯度:通过Robert算子(2x2)或Sobel算子(3x3),计算X向和Y向一阶偏导数(应该叫差分),梯度幅值和梯度方向,找到最大梯度信息
- 非极大值抑制:通过梯度幅值矩阵最大值处寻找像素点局部最大值,将非极大值点置为0,去除大部分非边缘的
- 双边阈值判断:梯度大于maxval的则为强边缘,小于maxval大于minVal则为弱边缘点,小于minval则为抑制点
- 联通边缘:把强边缘和软边缘连接起来
除了Sobel和Robert边缘检测算子外,还有一个通过二阶微分的Laplacian算子,通过零点寻找边缘位置信息(忽略均匀零点的位置)。Log算子在其基础上,先进行高斯滤波去噪,然后采用二阶导数Laplacian算子,最后判断二阶导数为0及其对应一阶导数是否为极大值判断边缘。