在opencv中支持SVM分类器,过程就是:先训练再预测(python实现)


# svm 对于数据的要求: 所有的数据都要有label # [155,48] -- 0 女生 [152,53] ---1 男生 # 监督学习 0 负样本 1 正样本


步骤一:获取训练样本

#1.获取训练样本,2类
row = 30
data1 = np.ones((row,2))+np.random.rand(row,2)              #[1,2)       1.5为中心
data2 = np.ones((row,2))*(-2)+np.random.rand(row,2)         #[-2,-1)    -1.5为中心

plt.figure(1)
plt.plot(data1[:,0],data1[:,1],'o')
plt.plot(data2[:,0],data2[:,1],'o')

#data = np.vstack(data1, data2)                #报错
data = np.vstack((data1,data2))                #将两种训练样本合并,这里无法转float32格式,所以才有下一行代码
data = np.array(data,dtype='float32')          #将训练样本转换成要求的float32格式才可以

 

opencv分类速度 opencv svm分类器_数据

步骤二:获取训练标签

#2.获取标签
label_data1 = np.zeros((row,1),dtype='int32')           #将训练标签转换成要求的int32格式才可以
label_data2 = np.ones((row,1),dtype='int32')
label = np.vstack((label_data1,label_data2))            #行堆积,另起一行,得到一个60x2的数组
label = np.array(label,dtype='int32')                   #这句话可有可无,因为label_data1和label_data2已声明int32类型

步骤三:创建分类器

#3.创建分类器
svm = cv2.ml.SVM_create()
svm.setType(cv2.ml.SVM_C_SVC)
svm.setKernel(cv2.ml.SVM_LINEAR)
svm.setC(cv2.ml.SVM_C_SVC)

步骤四:进行训练

#4.进行训练
res = svm.train(data,cv2.ml.ROW_SAMPLE,label)
print("训练成功与否res的值",res)                            #输出:True

步骤五:进行预测

#5.进行预测
pre = np.random.rand(20,2)*4-2                              #测试样本:20个点[-2,2)
pre = np.array(pre,dtype='float32')                         #将测试样本转换成要求的float32格式才可以
(par1,res) = svm.predict(pre)                               #返回值两个参数
print("预测后结果res的值\n",res)                             #得到一个20x1的数组

输出:

预测后结果res的值
 [[1.]
 [0.]
 [0.]
 [1.]
 [1.]
 [1.]
 [1.]
 [1.]
 [0.]
 [1.]
 [0.]
 [1.]
 [0.]
 [1.]
 [1.]
 [0.]
 [0.]
 [1.]
 [1.]
 [1.]]

步骤六:结果绘图

predict通过res返回得到一个20x1的数组。每一行相应一个输入点,计算得到的值就是分类的序号,在这里是0和1我们取0.5为阈值进行分类并显示结果。
因为测试样本是20个[-2,2)范围的点,即20*2的数组为了方便比较,先将结果预测后结果res进行列堆积,由20*1转换成20*2的数组同型数组就可以进行比较输出。
#6.结果绘图
res = np.hstack((res,res))                                  #列堆积,另起一列,得到一个20x2的数组
pre0 = pre[res<0.5]                                         #后续详细解释
pre1 = pre[res>=0.5]
print("pre0\n",pre0)
print("pre1\n",pre1)
print("pre0.shape:",pre0.shape)                            #此时两者均为一列
print("pre1.shape:",pre1.shape)
pre0 = np.reshape(pre0,(int(pre0.shape[0]/2),2))            #为了显示绘图,将一列变二列
pre1 = np.reshape(pre1,(int(pre1.shape[0]/2),2))
plt.figure(2)
plt.plot(pre0[:,0],pre0[:,1],'o')                           #画图plt.plot(x坐标,y坐标,'线型')
plt.plot(pre1[:, 0], pre1[:, 1], 'o')
plt.show()

输出:

pre0.shape: (24,)
pre1.shape: (16,)

pre0
 [-0.33559075  1.3618486   1.7029347   0.04593408  0.3551418   1.3985409
  0.75370246 -0.13495038  0.18302129  0.46836114  0.42994153  0.3347996
 -0.05576663  1.3062311   1.9422737   1.8106563   0.5062942   0.6137762
  1.9550579  -0.65718     0.8673214   1.4073303   1.3502296   0.88142025]
pre1
 [-0.3959848  -0.9314422   0.12321403 -0.8255872  -1.9429276  -0.49432907
 -1.5003582  -0.20095745 -1.786253    1.0939165  -0.68006885 -0.40214399
 -1.3144214  -1.7472401  -0.6790464  -0.4059371 ]

opencv分类速度 opencv svm分类器_数据_02

完整代码

def svm_point():
    """
    以下出现的np.array(pre,dtype='float32')作用:
    指定数组或者矩阵内部数据的数据类型
    """
    row = 30
    #1.获取样本,2类
    data1 = np.ones((row,2))+np.random.rand(row,2)              #[1,2)       1.5为中心
    data2 = np.ones((row,2))*(-2)+np.random.rand(row,2)         #[-2,-1)    -1.5为中心
    plt.figure(1)
    plt.plot(data1[:,0],data1[:,1],'o')
    plt.plot(data2[:,0],data2[:,1],'o')
    # data = np.vstack(data1, data2)                            #报错
    data = np.vstack((data1,data2))                             #将两种训练样本合并,这里无法转float32格式,所以才有下一行代码
    data = np.array(data,dtype='float32')                       #将训练样本转换成要求的float32格式才可以
    #2.获取标签
    label_data1 = np.zeros((row,1),dtype='int32')               #将训练标签转换成要求的int32格式才可以
    label_data2 = np.ones((row,1),dtype='int32')
    label = np.vstack((label_data1,label_data2))                #行堆积,另起一行,得到一个60x2的数组
    label = np.array(label,dtype='int32')                       #这句话可有可无,因为label_data1和label_data2已声明int32类型
    #3.创建分类器
    svm = cv2.ml.SVM_create()
    svm.setType(cv2.ml.SVM_C_SVC)
    svm.setKernel(cv2.ml.SVM_LINEAR)
    svm.setC(cv2.ml.SVM_C_SVC)
    #4.训练样本
    res = svm.train(data,cv2.ml.ROW_SAMPLE,label)
    print("训练成功与否res的值",res)                            #输出:True
    #5.进行预测
    pre = np.random.rand(20,2)*4-2                              #测试样本:20个点[-2,2)
    pre = np.array(pre,dtype='float32')                         #将测试样本转换成要求的float32格式才可以
    (par1,res) = svm.predict(pre)                               #返回值两个参数
    print("预测后结果res的值\n",res)                            #得到一个20x1的数组
    """
    predict通过res返回得到一个20x1的数组。
    每一行相应一个输入点,计算得到的值就是分类的序号,在这里是0和1
    我们取0.5为阈值进行分类并显示结果
    """
    """
    因为测试样本是20个[-2,2)范围的点,即20*2的数组
    为了方便比较,先将结果预测后结果res进行列堆积,由20*1转换成20*2的数组
    同型数组就可以进行比较输出
    """
    #6.结果绘图
    res = np.hstack((res,res))                                  #列堆积,另起一列,得到一个20x2的数组
    pre0 = pre[res<0.5]                                         #后续详细解释
    pre1 = pre[res>=0.5]
    print("pre0.shape:",pre0.shape)                            #此时两者均为一列
    print("pre1.shape:",pre1.shape)
    pre0 = np.reshape(pre0,(int(pre0.shape[0]/2),2))            #为了显示绘图,将一列变二列
    pre1 = np.reshape(pre1,(int(pre1.shape[0]/2),2))
    plt.figure(2)
    plt.plot(pre0[:,0],pre0[:,1],'o')                           #画图plt.plot(x坐标,y坐标,'线型')
    plt.plot(pre1[:, 0], pre1[:, 1], 'o')
    plt.show()
# usePlot()
# reshape()
svm_point()

补充:解释pre0 = pre[res<0.5] 

前提:要由两个维度一样的才可以进行比赋值

def true_false():
    a = np.array([[1],[2],[3],[4],[5]])
    b = np.array([[1],[1],[1],[0],[0]])
    res1 = a[b==1]
    print(res1)
    res2 = a[b<0.5]
    print(res2)

true_false()

输出:

[1 2 3]
[4 5]