图像分类
小贴士:
图像分类的算法过程如下:
- 准备样本图像。样本图像的要求是:能代表所属类别种尽可能多的图像。
- 提取每个样本的特征后,形成类别特征码。
- 应用机器学习算法对类别特征进行学习,提取特征码包含的图像知识。
- 判断位置图像所属类别。
余弦相似度:
余弦相似度是通过测量两个向量内积空间的夹角的余弦值类度量他们之间的相似性,尤其适用于任何维度的向量比较中,因此属于高维空间应用较多的机器学习算法。数字图像包含的特征码较多,而这些特征组就属于高危空间,这正是余弦相似度算法应用的范围,算法将每个图像的特征组转化为高维空间的向量,两个向量之间的角度之余弦值可用于确定两个向量是否大致指向相同的方向。
在图像分类中应用余弦相似度算法的关键在于:计算这些代表每个图像特征的向量的内积空间的夹角余弦值,从而度量图像之间的相似性。对于相似性的衡量标准有以下两种:
- 为相似性设置一个阀值。在这个阀值以内的都属于同一类别图像。这种标准可以将图像划分为多种类型,例如:高楼不但属于城市美景,而且属于写字楼景观。
- 选择与样本向量的余弦相似度最接近1的图像为该类别图像。这种标准只能将图像划分为一种类别。
算法原理:
将图像上的点分为不同的子集,这些子集往往属于孤立的点, 连续的曲线或者连续的区域。将这些点按区域组成子集,提取子集的特征后,将每个子集的特征作为图像的一个特征线来进行计算。
- 样本特征。设图像分为m个区域,每个区域有n个像素,每个像素在图像矩阵中以红,绿,蓝三色来表示,且区域特征计算方式为: 区域特征码 = (∑(i∈n[底部])像素i颜色的红色分量值/ n,∑(i∈n[底部])像素i颜色的绿色分量值/ n,∑(i∈n[底部])像素i颜色的蓝色分量值/ n) ,那么样本特征码矩阵为3 x m,即3行m列,这3行分别代表红,绿,蓝三个分量,每列个分量的区域特征码。
- 类别特征。这里为每个类别准备了3个样本,类别特征的计算方式为: 类别特征码 = (∑(i∈3[底部])像素i颜色的红色分量特征值/ 3,∑(i∈3[底部])像素i颜色的绿色分量特征值/ 3,∑(i∈3[底部])像素i颜色的蓝色分量特征值/ 3)。 其中,样本i是属于该类别的样本。在计算出类别特征后,算法对样本学习完毕。当有未知图像需要分类是,首先计算其图像的样本特征,然后将样本特征和类别特征映射为高维空间的向量,最后计算这两个向量的余弦相似度,选择余弦相似度最大的类别为未知图像对应的类别。
1>提取特征码
def readpic(fn): #返回图像特征码 fnimg = cv2.imread(fn) img = cv2.resize(fnimg,(20, 10)) w = img.shape[1] h = img.shape[0] w_interval = int(w/w_fg) h_interval = int(h/h_fg) alltz = [] alltz.append([]) alltz.append([]) alltz.append([]) for now_h in range(0,h,h_interval): for now_w in range(0,w,w_interval): b = img[now_h:now_h + h_interval, now_w:now_w + w_interval, 0] g = img[now_h:now_h + h_interval, now_w:now_w + w_interval, 1] r = img[now_h:now_h + h_interval, now_w:now_w + w_interval, 2] btz = np.mean(b) gtz = np.mean(g) rtz = np.mean(r) alltz[0].append(btz) alltz[1].append(gtz) alltz[2].append(rtz) return alltz
2>计算类别特征码。通过每个类别所有样本的区域特征的平均值,提取类别特征。
#读取图像,提取每类图像的特征 for ii in range(1,picflag + 1): smp_x = [] b_tz = np.array([0,0,0]) g_tz = np.array([0,0,0]) r_tz = np.array([0,0,0]) mytz = np.zeros((3,w_fg*h_fg)) for jj in range(1,3): fn = 'p' + str(ii) + '-' + str(jj) +'.png' tmptz = readpic(fn) mytz +=np.array(tmptz) mytz/=3 train_x.append(mytz[0].tolist() + mytz[1].tolist() + mytz[2].tolist())
3>计算待分类图像的特征码与每个类别特征码之间的余弦距离,距离最大者为图像所属分类。
fn = 'all.png' testtz = np.array(readpic(fn)) simtz = testtz[0].tolist() + testtz[1].tolist() + testtz[2].tolist() maxtz = 0 nowi = 0 for i in range(0,picflag): nowsim = get_cossimi(train_x[i],simtz) if nowsim>maxtz: maxtz = nowsim nowi = i print(u'%s 属于第%d类'% (fn,nowi+1))
完整代码:
import numpy as np
import cv2
print(u'正在处理中')
w_fg = 20
h_fg = 15
picflag = 3
def readpic(fn):
#返回图像特征码
fnimg = cv2.imread(fn)
img = cv2.resize(fnimg,(300, 210))
w = img.shape[1]
h = img.shape[0]
w_interval = int(w/w_fg)
h_interval = int(h/h_fg)
alltz = []
alltz.append([])
alltz.append([])
alltz.append([])
for now_h in range(0,h,h_interval):
for now_w in range(0,w,w_interval):
b = img[now_h:now_h + h_interval, now_w:now_w + w_interval, 0]
g = img[now_h:now_h + h_interval, now_w:now_w + w_interval, 1]
r = img[now_h:now_h + h_interval, now_w:now_w + w_interval, 2]
btz = np.mean(b)
gtz = np.mean(g)
rtz = np.mean(r)
alltz[0].append(btz)
alltz[1].append(gtz)
alltz[2].append(rtz)
return alltz
def get_cossimi(x,y):
myx = np.array(x)
myy = np.array(y)
cos1 = np.sum(myx*myy)
cos21 = np.sqrt(sum(myx*myx))
cos22 = np.sqrt(sum(myy*myy))
return cos1/float(cos21*cos22)
#x和d样本初始化
train_x = []
d = []
#读取图像,提取每类图像的特征
for ii in range(1,picflag + 1):
smp_x = []
b_tz = np.array([0,0,0])
g_tz = np.array([0,0,0])
r_tz = np.array([0,0,0])
mytz = np.zeros((3,w_fg*h_fg))
for jj in range(1,3):
fn = 'ptest' + str(jj) +'.jpg'
tmptz = readpic(fn)
mytz +=np.array(tmptz)
mytz/=3
train_x.append(mytz[0].tolist() + mytz[1].tolist() + mytz[2].tolist())
fn = 'ptest3.jpg'
testtz = np.array(readpic(fn))
simtz = testtz[0].tolist() + testtz[1].tolist() + testtz[2].tolist()
maxtz = 0
nowi = 0
for i in range(0,picflag):
nowsim = get_cossimi(train_x[i],simtz)
if nowsim>maxtz:
maxtz = nowsim
nowi = i
print(u'%s 属于第%d类'% (fn,nowi+1))
fn = 'ptest1.jpg'
testtz = np.array(readpic(fn))
simtz = testtz[0].tolist() + testtz[1].tolist() + testtz[2].tolist()
maxtz = 0
nowi = 0
for i in range(0,picflag):
nowsim = get_cossimi(train_x[i],simtz)
if nowsim > maxtz:
maxtz = nowsim
nowi = i
print(u'%s属于第%d类' % (fn,nowi+1))
fn = 'ptest2.jpg'
testtz = np.array(readpic(fn))
simtz = testtz[0].tolist() + testtz[1].tolist() + testtz[2].tolist()
maxtz = 0
nowi = 0
for i in range(0,picflag):
nowsim = get_cossimi(train_x[i],simtz)
if nowsim>maxtz:
maxtz = nowsim
nowi = i
print(u'%s 属于第%d类'% (fn,nowi+1))
King@_@