利用SIFT或ORB和KMeans方法实现图像的聚类
一、使用SIFT或ORB提取特征
尺度不变特征转换(Scale-invariant feature transform)是一种用来侦测与描述影像中的局部性特征的视觉算法,即通过求一幅图中的特征点及其有关尺度和方向的描述子得到特征,并进行图像特征点匹配。SIFT所查找到的特征点是一些十分突出,不会因光照,仿射变换和噪音等因素而变化的点,如角点、边缘点、暗区的亮点及亮区的暗点等,噪声也保持一定程度的稳定性,除此之外SIFT还具有独特性,多量性,高速性,可扩展性等特点。 ORB(Oriented FAST and Rotated BRIEF)是一种快速特征点提取和描述的算法。ORB 特征是将 FAST 特征点的检测方法与 BRIEF 特征描述子结合起来,并在它们原来的基础上做了改进与优化。 ORB算法之前的周报已经总结过,本次选用ORB算法提取特征是因为这是最近所学习的算法,有一定的基础,并且没使用SIFT或SURF算法提取特征是因为经过实验对比后发现ORB效果相对好一点,其他两种提取特征的方法得到的结果不理想。
二、使用KMeans进行聚类
k-means 算法将一组 N 样本 X 划分成 K 不相交的簇 C, 每个都用该簇中的样本的均值 μ j \mu_j μ j 描述。这个均值(means)通常被称为簇的“质心(centroids)”。K-means(K-均值)算法旨在选择一个质心, 能够最小化惯性或簇内平方和的标准: ∑ i = 0 n m i n u j ∈ C ( ∣ ∣ x j − u i ∣ ∣ 2 ) \sum_{i=0}^{n}{min_{u_j \in C}(\mid\mid x_j - u_i\mid\mid^{2})} i = 0 ∑ n m i n u j ∈ C ( ∣ ∣ x j − u i ∣ ∣ 2 ) 该算法可分为三个步骤。第一步是选择初始质心,最基本的方法是从 X 数据集中选择 k 个样本。初始化完成后,K-means 由接下来两个步骤之间的循环组成。 第一步将每个样本分配到其最近的质心。第二步通过取分配给每个先前质心的所有样本的平均值来创建新的质心。计算旧的和新的质心之间的差异,并且算法重复这些最后的两个步骤,直到该值小于阈值。
三、自己构建的图像数据集
我选取了100张图片作为数据集,分别有10个类,每个类各有10张图片,分别为猫,狗,鸭舌帽,书包,飞机,人,热水壶,汽车,球鞋,椅子。 数据集放在了百度网盘 ,百度网盘链接:https://pan.baidu.com/s/1ldUB3fAIk2ameYvM1W3AsQ 提取码:jbpb
(1)狗示例
(2)猫示例
(3)飞机示例
(4)椅子示例
(5)汽车示例
(6)人示例
(7)水壶示例
(8)球鞋示例
(9)帽子示例
(10)书包示例
四、代码文件
import os
import cv2
import numpy as np
from sklearn. cluster import KMeans
import skimage. io as io
from PIL import Image
import os. path
import glob
import matplotlib. pyplot as plt
def convertjpg ( jpgfile, outdir, width = 400 , height = 400 ) :
img = Image. open ( jpgfile)
try :
new_img= img. resize( ( width, height) , Image. BILINEAR)
new_img. save( os. path. join( outdir, os. path. basename( jpgfile) ) )
except Exception as e:
print ( e)
for jpgfile in glob. glob( "test\\*.jpg" ) :
convertjpg( jpgfile, "image_dataset" )
def get_filenames ( path) :
path_filenames = [ ]
filenames = os. listdir( path)
for file in filenames:
if not file . startswith( '.' ) :
path_filenames. append( os. path. join( path, file ) )
return path_filenames
def image_clusterByKMeans ( cluster_nums, path_filenames, randomState = None ) :
features = [ ]
'''
特征提取的方法分为三种 这里实验了2种。
一种是SIFT算法,一种是ORB算法
'''
sift = cv2. xfeatures2d. SIFT_create( )
files = path_filenames
for file in files:
img = cv2. imread( file )
gray = cv2. cvtColor( img, cv2. COLOR_BGR2GRAY)
kp, des = sift. detectAndCompute( gray, None )
print ( des. shape)
if des is None :
path_filenames. remove( file )
continue
reshape_feature = des. reshape( - 1 , 1 )
print ( reshape_feature. shape)
'''
这里也有2种方法进行实验,第一种是我查阅资料看到大部分人取的是reshape_feature[0]即只取第一个元素的值;
第二种是我在实验过程中觉得可以取平均值mean来算,使用np.mean(reshape_feature)
但是我觉得2者的结果没有太大的差别,可能平均值的大部分比较好,但是有个别类只有1-2个图片。
'''
reshape_feature_Mean = np. array( [ np. mean( reshape_feature) ] )
features. append( reshape_feature_Mean. tolist( ) )
print ( reshape_feature[ 0 ] )
print ( reshape_feature_Mean)
input_x = np. array( features)
print ( input_x)
print ( input_x. shape)
kmeans = KMeans( n_clusters = cluster_nums, max_iter = 10000 ) . fit( input_x)
return kmeans. labels_, kmeans. cluster_centers_
def main ( ) :
path_filenames = get_filenames( "image_dataset" )
imgs = os. listdir( 'image_dataset' )
imgnum = len ( imgs)
cluster_nums = 10
labels, cluster_centers = image_clusterByKMeans( cluster_nums, path_filenames)
res = labels. tolist( )
result = [ [ ] for i in range ( 10 ) ]
i = 0
for i in range ( imgnum) :
result[ res[ i] ] . append( i + 1 )
for i in range ( cluster_nums) :
print ( '%02d个' % ( res. count( i) ) , end= ': ' )
print ( result[ i] )
for i in range ( cluster_nums) :
size = len ( result[ i] )
plt. figure( figsize= ( 20 , 20 ) )
for j in range ( size) :
ax = plt. subplot( 1 , size, 1 + j)
plt. xticks( [ ] )
plt. yticks( [ ] )
file = path_filenames[ result[ i] [ j] - 1 ]
img = io. imread( file )
ax. imshow( img)
plt. show( )
if __name__ == "__main__" :
main( )
五、实验结果
(1)SIFT+KMEANS
图1 实验结果1
(2)ORB+KMEANS
图2 实验结果2
参考资料:
https://docs.opencv.org/master/db/d95/classcv_1_1ORB.html https://github.com/Byronnar/image_classfication https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html#sklearn.cluster.KMeans https://blog.csdn.net/qq_18150255/article/details/88040858 https://blog.csdn.net/weixin_43823854/article/details/102017382 https://blog.csdn.net/dss_dssssd/article/details/82692894