当前位置:   article > 正文

【实战类】Hog SVM进行图像分类任务_hog-svm

hog-svm

目录

一、训练数据准备:cifar转图像操作

二、训练和验证部分

三、hog梯度图可视化


案例训练数据:cifar 10

图像下载地址(后面我们要用这批数据作为训练数据):CIFAR-10 and CIFAR-100 datasetsicon-default.png?t=N7T8http://www.cs.toronto.edu/~kriz/cifar.html本文参考链接:HOG + SVM 进行图片分类(python)_程序员的点滴-CSDN博客_svm图片二分类pythonicon-default.png?t=N7T8https://blog.csdn.net/q1242027878/article/details/74271694什么是HOG:

一文讲解方向梯度直方图(hog)icon-default.png?t=N7T8https://zhuanlan.zhihu.com/p/85829145

特征描述符就是通过提取图像的有用信息,并且丢弃无关信息来简化图像的表示。HOG特征描述符可以将3通道的彩色图像转换成一定长度的特征向量。

HOG特征描述符中,梯度方向的分布,也就是梯度方向的直方图被视作特征。图像的梯度(x和y导数)非常有用,因为边缘和拐角(强度突变的区域)周围的梯度幅度很大,并且边缘和拐角比平坦区域包含更多关于物体形状的信息。

图像处理——梯度直方图HOG_lanling1996的博客-CSDN博客_梯度直方图                          图像处理之特征提取:HOG特征简单梳理              HOG方向梯度直方图,这里分解为方向梯度与直方图。 一、方向梯度 梯度:在向量微积分中,标量...https://blog.csdn.net/lanling1996/article/details/112589519HOG主要应用于行人检测方面,以行人照片为例:

完整代码、数据处理和样例,可去这里下载:基于Hog 的 SVM Pytorch图像分类任务

一、训练数据准备:cifar转图像操作

案例操作中使用的训练数据是cifar10的数据,这里我们需要先把原始数据,转为图像数据,进行本地化保存,下载好数据后,进行转图操作,转图代码如下:

  1. import cv2
  2. import numpy as np
  3. import os
  4. def unpickle(file):
  5. import _pickle as cPickle
  6. with open(file, 'rb') as f:
  7. dict = cPickle.load(f, encoding='iso-8859-1')
  8. return dict
  9. def main(cifar10_data_dir):
  10. train_txt=[]
  11. test_txt=[]
  12. for i in range(1, 2):
  13. train_data_file = os.path.join(cifar10_data_dir, 'data_batch_' + str(i))
  14. print(train_data_file)
  15. data = unpickle(train_data_file)
  16. print('unpickle done', data)
  17. for j in range(10000):
  18. img = np.reshape(data['data'][j], (3, 32, 32))
  19. img = img.transpose(1, 2, 0)
  20. img_name = 'train/' + str(data['labels'][j]) + '_' + str(j + (i - 1) * 10000) + '.jpg'
  21. cv2.imwrite(os.path.join(cifar10_data_dir, img_name), img)
  22. train_txt.append(str(data['labels'][j]) + '_' + str(j + (i - 1) * 10000) + '.jpg' + ' ' + str(data['labels'][j]))
  23. np.savetxt(r"./train.txt", np.reshape(train_txt, -1), delimiter=',', fmt='%5s')
  24. test_data_file = os.path.join(cifar10_data_dir, 'test_batch')
  25. data = unpickle(test_data_file)
  26. for i in range(10000):
  27. img = np.reshape(data['data'][i], (3, 32, 32))
  28. img = img.transpose(1, 2, 0)
  29. img_name = 'test/' + str(data['labels'][i]) + '_' + str(i) + '.jpg'
  30. cv2.imwrite(os.path.join(cifar10_data_dir, img_name), img)
  31. test_txt.append(str(data['labels'][i]) + '_' + str(i) + '.jpg' + ' ' + str(data['labels'][i]))
  32. np.savetxt(r"./test.txt", np.reshape(test_txt, -1), delimiter=',', fmt='%5s')
  33. if __name__ == "__main__":
  34. main('cifar-10-batches-py')

如果遇到这个问题:

python 3以上版本使用pickle.load读取文件报UnicodeDecodeError: 'ascii' codec can't decode byte 0x8b in position 6

 可参考这里解决:python 3以上版本使用pickle.load读取文件报UnicodeDecodeError: 'ascii' codec can't decode byte 0x8b in position 6_IT人生-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_33144323/article/details/80042273

二、训练和验证部分

直接方代码,边训练边学习这段代码的含义,主要思路就是一下几点:

  1. 原图转hog梯度图
  2. 加载特征和标签进行训练
  3. 测试评估
  1. # -*- coding=utf-8 -*-
  2. import glob
  3. import platform
  4. import time
  5. from PIL import Image
  6. from skimage.feature import hog
  7. import numpy as np
  8. import os
  9. import joblib
  10. from sklearn.svm import LinearSVC
  11. import shutil
  12. import sys
  13. # 第一个是你的类别 第二个是类别对应的名称 输出结果的时候方便查看
  14. label_map = {0: 'airplane',
  15. 1: 'automobile',
  16. 2: 'bird',
  17. 3: 'cat',
  18. 4: 'deer',
  19. 5: 'dog',
  20. 6: 'frog',
  21. 7: 'horse',
  22. 8: 'ship',
  23. 9: 'truck,'
  24. }
  25. # 训练集图片的位置
  26. train_image_path = './database/train'
  27. # 测试集图片的位置
  28. test_image_path = './database/test'
  29. # 训练集标签的位置
  30. train_label_path = os.path.join('./labels', 'train.txt')
  31. # 测试集标签的位置
  32. test_label_path = os.path.join('./labels', 'test.txt')
  33. image_height = 32
  34. image_width = 32
  35. train_feat_path = './feature/train/'
  36. test_feat_path = './feature/test/'
  37. model_path = 'model/'
  38. # 获得图片列表
  39. def get_image_list(filePath, nameList):
  40. print('read image from ', filePath)
  41. img_list = []
  42. for name in nameList:
  43. temp = Image.open(os.path.join(filePath, name))
  44. img_list.append(temp.copy())
  45. temp.close()
  46. return img_list
  47. # 提取特征并保存
  48. def get_feat(image_list, name_list, label_list, savePath):
  49. i = 0
  50. for image in image_list:
  51. try:
  52. # 如果是灰度图片 把3改为-1
  53. image = np.reshape(image, (image_height, image_width, -1))
  54. except:
  55. print('发送了异常,图片大小size不满足要求:', name_list[i])
  56. continue
  57. #gray = rgb2gray(image) / 255.0
  58. # 如果直接就是灰度图
  59. gray = image
  60. # 这句话根据你的尺寸改改
  61. fd = hog(gray, orientations=12, block_norm='L1', pixels_per_cell=[8, 8], cells_per_block=[4, 4], visualize=False,
  62. transform_sqrt=True)
  63. fd = np.concatenate((fd, [label_list[i]]))
  64. fd_name = name_list[i] + '.feat'
  65. fd_path = os.path.join(savePath, fd_name)
  66. joblib.dump(fd, fd_path)
  67. i += 1
  68. print("Test features are extracted and saved.")
  69. # 变成灰度图片
  70. def rgb2gray(im):
  71. gray = im[:, :, 0] * 0.2989 + im[:, :, 1] * 0.5870 + im[:, :, 2] * 0.1140
  72. return gray
  73. # 获得图片名称与对应的类别
  74. def get_name_label(file_path):
  75. print("read label from ", file_path)
  76. name_list = []
  77. label_list = []
  78. with open(file_path) as f:
  79. for line in f.readlines():
  80. #一般是name label 三部分,所以至少长度为3 所以可以通过这个忽略空白行
  81. if len(line) >= 3:
  82. name_list.append(line.split(' ')[0])
  83. label_list.append(line.split(' ')[1].replace('\n','').replace('\r',''))
  84. if not str(label_list[-1]).isdigit():
  85. print("label必须为数字,得到的是:",label_list[-1], "程序终止,请检查文件")
  86. exit(1)
  87. return name_list, label_list
  88. # 提取特征
  89. def extra_feat():
  90. train_name, train_label = get_name_label(train_label_path)
  91. test_name, test_label = get_name_label(test_label_path)
  92. train_image = get_image_list(train_image_path, train_name)
  93. test_image = get_image_list(test_image_path, test_name)
  94. get_feat(train_image, train_name, train_label, train_feat_path)
  95. get_feat(test_image, test_name, test_label, test_feat_path)
  96. # 创建存放特征的文件夹
  97. def mkdir():
  98. if not os.path.exists(train_feat_path):
  99. os.mkdir(train_feat_path)
  100. if not os.path.exists(test_feat_path):
  101. os.mkdir(test_feat_path)
  102. # 训练和测试
  103. def train_and_test():
  104. t0 = time.time()
  105. features = []
  106. labels = []
  107. correct_number = 0
  108. total = 0
  109. for feat_path in glob.glob(os.path.join(train_feat_path, '*.feat')):
  110. data = joblib.load(feat_path)
  111. features.append(data[:-1])
  112. labels.append(data[-1])
  113. ############ 训练部分 ############
  114. """
  115. print("Training a Linear LinearSVM Classifier.")
  116. clf = LinearSVC()
  117. clf.fit(features, labels)
  118. # 下面的代码是保存模型的
  119. if not os.path.exists(model_path):
  120. os.makedirs(model_path)
  121. joblib.dump(clf, model_path + 'model')
  122. """
  123. ############ 训练完验证部分 ############
  124. # 下面的代码是加载模型 可以注释上面的代码 直接进行加载模型 不进行训练
  125. clf = joblib.load(model_path+'model')
  126. print("训练之后的模型存放在model文件夹中")
  127. # exit()
  128. result_list = []
  129. for feat_path in glob.glob(os.path.join(test_feat_path, '*.feat')):
  130. total += 1
  131. if platform.system() == 'Windows':
  132. symbol = '\\'
  133. else:
  134. symbol = '/'
  135. image_name = feat_path.split(symbol)[1].split('.feat')[0]
  136. data_test = joblib.load(feat_path)
  137. data_test_feat = data_test[:-1].reshape((1, -1)).astype(np.float64)
  138. result = clf.predict(data_test_feat)
  139. print(result)
  140. result_list.append(image_name + ' ' + str(result[0]) + '\n')
  141. if int(result[0]) == int(data_test[-1]):
  142. correct_number += 1
  143. write_to_txt(result_list)
  144. rate = float(correct_number) / total
  145. t1 = time.time()
  146. print('准确率是: %f' % rate)
  147. print('耗时是 : %f' % (t1 - t0))
  148. def write_to_txt(list):
  149. with open('result.txt', 'w') as f:
  150. f.writelines(list)
  151. print('每张图片的识别结果存放在result.txt里面')
  152. if __name__ == '__main__':
  153. mkdir() # 不存在文件夹就创建
  154. # need_input = input('是否手动输入各个信息?y/n\n')
  155. if sys.version_info < (3,):
  156. need_extra_feat = input('是否需要重新获取特征?y/n\n')
  157. else:
  158. need_extra_feat = input('是否需要重新获取特征?y/n\n')
  159. if need_extra_feat == 'y':
  160. shutil.rmtree(train_feat_path)
  161. shutil.rmtree(test_feat_path)
  162. mkdir()
  163. extra_feat()
  164. train_and_test()

cifar10的训练和测试结果,如下:

  1. 是否需要重新获取特征?y/n
  2. y
  3. read label from ./labels\train.txt
  4. read label from ./labels\test.txt
  5. read image from ./database/train
  6. read image from ./database/test
  7. Test features are extracted and saved.
  8. Test features are extracted and saved.
  9. Training a Linear LinearSVM Classifier.
  10. 训练之后的模型存放在model文件夹中
  11. 每张图片的识别结果存放在result.txt里面
  12. 准确率是: 0.460400
  13. 耗时是 : 12.241030

三、hog梯度图可视化

直观的查看下hog梯度方向直方图的样式,以一张其它图像为例进行展示,你也可以替换为你自己的图像,如下:

  1. from skimage.feature import hog
  2. from skimage import io
  3. from PIL import Image
  4. import cv2
  5. img = cv2.cvtColor(cv2.imread('./database/train_medical/DRCrop_3.png'), cv2.COLOR_BGR2GRAY)
  6. print(img.shape)
  7. normalised_blocks, hog_image = hog(img, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(8, 8),
  8. block_norm='L2-Hys', visualize=True)
  9. io.imshow(hog_image)
  10. io.show()

 参考文档:使用skimage提取图像hog特征_人工智能讲师团-CSDN博客_skimage.feature.hogicon-default.png?t=N7T8https://blog.csdn.net/mago2015/article/details/85320347

 四、SVM

支持向量机(Support Vector Machine, SVM)是一种监督学习算法,常用于分类和回归问题。它的基本思想是在训练数据集中找到一个超平面,使得超平面尽可能地将不同类别的数据分开,同时尽量缩小超平面与数据点之间的间隔。

在分类问题中,支持向量机通常使用线性分类器,即找到一个超平面使得其将数据点分为两个类别。在非线性分类问题中,支持向量机可以通过将数据映射到高维空间,再在高维空间中找到超平面,来解决非线性分类问题。

在回归问题中,支持向量机使用支持向量回归(Support Vector Regression, SVR)来预测连续型输出变量。SVR的基本思想是找到一条拟合数据的直线或曲线,使得直线或曲线与数据点之间的误差尽可能小。

支持向量机具有许多优点,例如:
1. 泛化能力强、
2. 不需要太多的训练数据(因为最终的解仅由少数支持向量决定)
3. 可以解决高维问题等。

但是,支持向量机也有一些缺点,例如:
1. 对缺失数据敏感、
2. 对参数调整敏感等。

问:分类间隔是由所有训练集样本所决定的吗?
答:不是!分类间隔是由距离分类决策边界最近的那些少量样本决定的。而比这些样本距离分类决策边界更远的大量样本,其实都不会影响到最优权向量的求取。这些作用十分特殊的样本,就被称为“支持向量(Support Vector)”,表示是他们支撑起了线性分类器在最大分类间隔意义下的最优解。这也是为什么这种算法被称为“支持向量机(Support Vector Machine,SVM)”的原因。

推荐更详尽的学习链接,强烈推荐:

  1. 【线性分类器】(四)万字长文解释拉格朗日乘子与支持向量机
  2. 【机器学习】支持向量机 SVM(非常详细)

如果最后测试阶段的准确率不好,可以调整核函数,可以参考这个函数,对核函数进行修改:SVMicon-default.png?t=N7T8https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html#sklearn.svm.SVC

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/581912
推荐阅读
相关标签
  

闽ICP备14008679号