使用HOG对卫星图像中的船舶进行分类
我在浏览Kaggle数据集时发现了这个有趣的机器学习数据集(https://www.kaggle.com/rhammell/ships-in-satellite-imagery)。该机器学习数据集包括从卫星图像中提取的船舶图像以及一些负面实例。查看此机器学习数据集,我们就可以看到正实例被裁剪为具有相同的宽度和高度。
卫星捕获船舶的图像
这些数据的一个明显应用将是训练一种“船舶探测器”,这种探测器可以从更大的卫星图像上利用计算机视觉探测船舶。
我们可以训练机器学习模型来检测大型卫星图像中的船只
为了实现这一目标,我想到了一种基于方向梯度直方图(HOG)的方法,这是传统机器学习方法中使用的一种特征表示方法。
机器学习数据集由2000个图像样本组成。我们可以使用HOG特征和SVM实现分类器,可以提供相当好的结果。由于船舶的外观统一、简单,所以我们无需依靠复杂的模型就能得到良好的结果。
方向梯度直方图
方向梯度的直方图,也称为HOG,在计算机视觉任务中被大量使用,特别是在检测行人和类似任务时
Hala特征表示由Dalal和Triggs引入,作为行人检测任务的表示方法。该方法建立在图像的局部强度梯度或边缘方向可以表征局部物体外观的思想的基础上。HOG特征在行人检测等各种目标识别任务中都取得了成功。当我们考虑将其用作开发更复杂的特征方法(如DPM)的基础时,该方法的重要性是显而易见的。
图像被分成小单元,例如8×8像素。在单元内的每个像素处计算梯度向量。梯度向量被分类为直方图。梯度向量的方向决定了它将落入哪个区域。向量的大小有助于直方图的频率。因此,梯度越大,对直方图值的影响越大。
块归一化
在原始论文中,作者提出了一种归一化方法,使该表示方法对光照具有更强的不变性。该方法是通过组合多个单元来创建块,即:可以通过组合两行和两列单元来创建块。将单元的直方图连接在一起,并通过将直方图除以连接的矢量的大小来归一化。以这样的方式创建块:在两个块之间存在一行或一列单元的重叠。
实现HOG特征分类器
出于我们的目的,让我们使用scikit-image中的hog实现,因为我们可以在其他分类器中使用计算的HOG特征。
import numpy as np import json from matplotlib import pyplot as plt from skimage.feature import hog from skimage import color,img_as_float from skimage.io import imread from sklearn import svm from sklearn.metrics import classification_report,accuracy_score from skimage.transform import pyramid_gaussian #This portion deals with extracting the code from the kaggle dataset f = open(r'../input/shipsnet.json') dataset = json.load(f) f.close() data = np.array(dataset['data']).astype('uint8') img_length = 80 #Bit of reshaping to get the dataset in order data = data.reshape(-1,3,img_length,img_length).transpose([0,2,3,1])
为了使用图像来计算hog特征,我们需要将图像转换为灰度。转换后的图像用于计算直方图。
#Convert the images to grayscale data_gray = [ color.rgb2gray(i) for i in data] #pixels per cell ppc = 16 hog_images = [] hog_features = [] for image in data_gray: fd,hog_image = hog(image, orientations=8, pixels_per_cell=(ppc,ppc),cells_per_block=(4, 4),block_norm= 'L2',visualise=True) hog_images.append(hog_image) hog_features.append(fd)
hog函数返回两个值。存储在fd变量中的HOG特征和可用于表示图像的HOG特征的图像,其存储在hog_image变量中。如果您不想显示图像,只需将visualise参数设置为False,即可将其关闭 。
如果我们可视化hog_images对应于之前的图像,我们将得到这样的结果
在下一节中,我们准备我们的训练和测试数据集,比例为80:20。然后我们训练支持向量机来分类图像是否包含船。Python代码如下:
#Extract the labels from the dataset labels = np.array(dataset['labels']).reshape(len(dataset['labels']),1) #Create the classifier clf = svm.SVC() hog_features = np.array(hog_features) data_frame = np.hstack((hog_features,labels)) #Shuffle the data set np.random.shuffle(data_frame) percentage = 80 partition = int(len(hog_features)*percentage/100) x_train = data_frame[:partition,:-1] x_test = data_frame[partition:,:-1] y_train = data_frame[:partition,-1:].ravel() y_test = data_frame[partition:,-1:].ravel() #Train the classifier with the training data clf.fit(x_train,y_train)
然后我们使用测试集来评估模型。为了更好地理解数据,最后会报告一些指标。
y_pred = clf.predict(x_test) print("Accuracy: "+str(accuracy_score(y_test, y_pred))) print(' ') print(classification_report(y_test, y_pred))
结论
本研究的目的是探讨传统计算机视觉技术在应用于普通图像识别任务时的性能。鉴于我们没有花太多时间调整参数,它还是相当不错的。使用HOG参数(例如每个单元的像素数和每个块的单元格)可能会产生不同的结果。这个结果表明我们并不总是需要求助于复杂的学习任务,有时解决方案可能很简单。在这篇文章中我们只研究了给定图像的分类,我们还没有涉及对象定位。有许多方法可以在图像中查找和定位对象,例如滑动窗口和选择性搜索以及诸如候选区域之类的新技术。