魏老师学生——Cecil:学习OpenCV-机器视觉之旅
SVM—线性数据分割
- 决定边界:使用f(x)=ax1+bx2+c 将数据分割到两个区域。
- 线性分割:使用一条直线将数据分成两组的方法。
- SVM:找到一条直线,并使这条直线到各组数据的最短距离最大。
- 支持向量:靠近决定边界的那部分数据。
- 支持平面:经过支持向量的直线。
- ωTx+b0 : ω是权重向量;x是特征向量;b0是截距。
- 权重向量影响决定边界走向,截距点影响决定边界的位置。
- 决定边界:两个超平面的中间线。表达式ωTx+b0=0.
- distance support vector = 1/ ||ω||:支持向量到决定边界的最短距离。边缘长度是其两倍。
- 需要使边缘长度最大,创建一个函数使其最小:
非线性数据分割
- 在低维空间不能线性分割的数据在高维空间有可能线性分割。
- 通常将d维数据映射到D维数据检测是否可以线性分割。从而通过对低维输入空间的计算获得高维空间的点积。
- 最大边缘最小错误分类的评判标准:
- ξi:训练样本到所属类的超平面的距离。
- C的取值:取决于训练数据。太大了边缘减小,错误也变少(数据噪声小使用);太小了边缘变大,错误升高(数据噪声大使用)。
使用SVM进行手写数据OCR
- KNN中直接使用像素的灰度值作为特征向量。SVM中使用方向梯度直方图HOG作为特征向量。
- 计算HOG前使用图片的二阶矩进行抗扭斜 deskew 处理。
#coding=utf-8
import cv2
import numpy as np
from matplotlib import pyplot as plt
def deskew(img):
m=cv2.moments(img)
if abs(m['mu02'])<1e-2:
return img.copy()
skew=m['mu11']/m['mu02']
M=np.float32([[1,skew,-0.5*SZ*skew],[0,1,0]])
img=cv2.warpAffiner(img,M,(SZ,SZ),flags=affine_flags)
return img
- 计算图像的HOG描述符。先计算图像X方向Y方向的Sobel导数,再计算每个像素的梯度方向与大小。
- 把梯度转换为16位整数。分图像为4个小方块,计算每个小方块的朝向直方图 16个bin,使用梯度大小做权重。使得每个小方块都得到含有16个成员的向量。
- 4个小方块的4个向量组成图像的特征向量,包含64个成员。
def hog(img):
gx=cv2.Sobel(img,cv2.CV_32F,1,0)
gy=cv2.Sobel(img,cv2.CV_32F,0,1)
mag,ang=cv2.cartToPolar(gx,gy)
bins=np.int32(bin_n*ang/(2*np.pi))
bin_cells=bins[:10,:10],bins[10:,:10],bins[:10,10:],bins[10:,10:]
mag_cells=mag[:10,:10],mag[10:,:10],mag[:10,10:],mag[10:,10:]
hists=[np.bincount(b.ravel(),m.ravel(),bin_n) for b,m in zip(bin_cells,mag_cells)]
hist=np.hstack(hists)
return hist
代码演示
将大图割成小图,使用一半数据集为训练数据,一半为测试数据。
#coding=utf-8
import cv2
import numpy as np
from matplotlib import pyplot as plt
SZ=20
bin_n=16
svm_params=dict(kernel_type=cv2.SVM_LINEAR,
svm_type=cv2.SVM_C_SVC,
C=2.67,gamma=5.383)
affine_flags=cv2.WARP_INVERSE_MAP|cv2.INTER_LINEAR
def deskew(img):
m=cv2.moments(img)
if abs(m['mu02'])<1e-2:
return img.copy()
skew=m['mu11']/m['mu02']
M=np.float32([[1,skew,-0.5*SZ*skew],[0,1,0]])
img=cv2.warpAffiner(img,M,(SZ,SZ),flags=affine_flags)
return img
def hog(img):
gx=cv2.Sobel(img,cv2.CV_32F,1,0)
gy=cv2.Sobel(img,cv2.CV_32F,0,1)
mag,ang=cv2.cartToPolar(gx,gy)
bins=np.int32(bin_n*ang/(2*np.pi))
bin_cells=bins[:10,:10],bins[10:,:10],bins[:10,10:],bins[10:,10:]
mag_cells=mag[:10,:10],mag[10:,:10],mag[:10,10:],mag[10:,10:]
hists=[np.bincount(b.ravel(),m.ravel(),bin_n) for b,m in zip(bin_cells,mag_cells)]
hist=np.hstack(hists)
return hist
img=cv2.imread('./image2/classification.jpg',0)
cells=[np.hsplit(row,100) for row in np.vsplit(img,50)]
train_cells=[i[:50] for i in cells]
test_cells=[i[50:] for i in cells]
#训练
deskewed=[map(deskew,row) for row in train_cells]
hogdata=[map(hog,row) for row in deskewed]
trainData=np.float32(hogdata).reshape(-1,64)
responses=np.float32(np.repeat(np.arange(10),250)[:,np.newaxis])
svm=cv2.SVM()
svm.train(trainData,responses,params=svm_params)
svm.save('svm_data.dat')
#测试
deskewed=[map(deskew,row) for row in test_cells]
hogdata=[map(hog,row) for row in deskewed]
testData=np.float32(hogdata).reshape(-1,bin_n*4)
result=svm.predict_all(testData)
#检测准确度
mask=result==responses
correct=np.count_nonzero(mask)
print(correct*100.0/result.size)
准确率可达到94%。