图像处理——Haar特征

Haar特征最初是用来进行人脸特征的表示的,最近重新看了SURF算法,发现在生成特征点描述子的时候也有用到Haar特征。查看了一些博文,自己整理一些,方便以后复习。
Haar特征分为三类:边缘特征、线性特征、中心特征和对角线特征,组合成特征模型。特征模板有黑白两种颜色,且定义模板的特征值为模板中 白色区域的像素总和 减去 黑色区域的像素总和。这里还涉及到积分图像的应用。Haar特征反应的是图像的灰度变化情况。但是矩形特征只对一些简单的图形结构,如边缘、线段比较敏感,所以只能描述特定走向(水平、垂直、对角)的结构。
积分图像
积分图像是一种能够描述全局信息的矩阵表示方法,他的构造方式 是积分图中某个点的值表示该点左上角所有像素之和,具体方式如下所示:
1) 用 s(i,j)表示行方向的累加和,即第i行前j列像素之和,初始化为s(i,-1)=0
2) 用 T(i,j)表示一个积分图像,初始化为T(-1,j)=0
3) 逐行扫描图像,递归计算每个像素(i,j)行方向的累加和s(i,j) 与(i,j)左上角方向积分图的累加和
s(i,j) = s(i,j-1) + I(i,j)
T(i,j) = T(i-1,j) + s(i,j)
如下图所示:
图像处理——Haar特征_第1张图片
在上述积分图像中,若要得到 A区域的像素和,则需要T(4) , B区域的像素和为T(12) - T(11) ,区域C的像素和为 T(16) - T(14), 区域D的像素和为 T(8) + T(5) - T(6) - T(7)
Haar特征的模板有如下几种
图像处理——Haar特征_第2张图片
关于一幅图像有多少个特征数量可以参考这个博客
特征模板数量计算参考
图像处理——Haar特征_第3张图片

import cv2
#积分图
def intergralMat(input=[],weight=0,height=0):
    output=[]
    #output.clear()
    columnSum = [0 for i in range(weight)] #[0, 0, 0, 0, 0, 0, 0, 0, 0]
    for i in range(height):
        output.append([0 for x in range(weight)])
        for j in range(weight):
            if j==0:
                columnSum[j] = int(input[i][j])
            else:
                columnSum[j]=columnSum[j-1] + int(input[i][j])
            if i==0:
                output[i][j]=columnSum[j]
            else:
                output[i][j]=output[i-1][j]+columnSum[j]
    return output


#Haar特征 默认size=1 ,deep=2
def wHaar(interM = [],weigth = 0,height = 0,size = 1,deep = 2):
    dst = []
    for i in range(height - deep + 1):
        dst.append([0 for x in range(weigth - size)])
        for j in range(weigth - 2*size +1):
            white,black = (0,0)
            if j == 0 and i==0:
                white = int(interM[i+deep-1][j+size-1])
            elif i!=0 and j==0:
                white = int(interM[i + deep - 1][j + size - 1]) - int(interM[i - 1][j + size -1])
            elif i == 0 and j != 0:
                white = int(interM[i+deep-1][j+size-1]) - int(interM[i+deep-1][j-1])
            else:
                white = int(interM[i+deep-1][j+size-1]) + int(interM[i+deep-3][j+size-2]) - int(interM[i+deep-1][j+size-2]) - int(interM[i+deep-3][j+ size -1])
            _i = i
            _j = j + size
            if _i == 0:
                black = int(interM[_i+deep-1][_j+size-1]) - int(interM[_i+deep-1][_j+size-2])
            else:
                black = int(interM[_i+deep-1][_j+size-1]) + int(interM[_i+deep-3][_j+size-2]) - int(interM[_i+deep-1][_j+size-2]) - int(interM[i+deep-3][_j+size-1])
            dst[i][j] = black - white
    return dst

if __name__ == '__main__':
    src = cv2.imread(r'D:\Python Code\picture\cat1.jpg')
    tmp = src.copy()
    b,g,r = cv2.split(src)
    _w = len(g[0]) #图像的宽 391
    _h = len(g)   #图像的长220
    #print _w , _h
    #g通道
    in_g = intergralMat(g,_w,_h)  #返回积分图像
    Haar_g = wHaar(in_g,_w,_h)  #返回Haar特征
    #b通道
    in_b = intergralMat(b,_w,_h)  #返回积分图像
    Haar_b = wHaar(in_b,_w,_h)  #返回Haar特征
    #r通道
    in_r = intergralMat(r,_w,_h)  #返回积分图像
    Haar_r = wHaar(in_r,_w,_h)  #返回Haar特征
    dst1 = []
    dst2 = []
    dst3 = []
    #print len(Haar_b), len(Haar_b[0])
    for x in range(len(Haar_g)): #219
        dst1.append([])
        dst2.append([])
        dst3.append([])
        for y in range(len(Haar_g[0])): #390
            if Haar_g[x][y] > 0:
                dst2[x].append(255)
            else:
                dst2[x].append(0)
            if Haar_b[x][y] > 0:
                dst1[x].append(255)
            else:
                dst1[x].append(0)
            if Haar_r[x][y] > 0:
                dst3[x].append(255)
            else:
                dst3[x].append(0)
    for x in range(len(dst1)):
        for y in range(len(dst1[0])):
            f1 = dst1[x][y]
            f2 = dst2[x][y]
            f3 = dst3[x][y]
            tmp[x,y] = [f1,f2,f3]

    cv2.imshow('src',src)
    cv2.imshow('test',tmp)
    cv2.waitKey(0)

参考的别人的博客,只用了竖直方向的模板,模板如上图所示。其他模板也类似,旋转45度的可能有点难度,具体可以参考这篇文献
Empirical Analysis of Detection Cascades of Boosted Classifiers for Rapid Object Detection

你可能感兴趣的:(图像处理,python)