SIFT 특징 및 SVM 기반 이미지 분류

5213 단어 pythonopencv
간단 한 이미지 분류 예, 사용 하 는 그림 집합 은 모두 13 가지 이 며, 모든 파일 은http://download.csdn.net/detail/u012874151/8655041다운로드
방법:
1. 그림 유형 에 따라 모든 그림 의 SIFT 특징 을 추출 하여 훈련 합 니 다.
2. 각 유형의 그림 의 SIFT 특징 을 K 류 로 분류 하여 이러한 visual vocabulary (size 는 K) 를 구성한다.
3. 훈련 에 집 중 된 모든 사진 에 대해 vocabulary 에서 K 개의 단어의 '주파수' 를 통계 하여 해당 하 는 직사 도 를 얻는다.
4. 직사 도 를 샘플 벡터 로 하면 SVM 의 훈련 데이터 와 테스트 데 이 터 를 구축 할 수 있다.
python (numpy & opencv) 으로 샘플 을 만 들 었 습 니 다. 정확 도 는 약 89% 이 고 개선 할 수 있 습 니 다.
해당 코드 는 다음 과 같 습 니 다.
'''
  @author: Tiejian Zhang
  @email: [email protected]
  @method: SIFT -> k-means -> SVM
'''
import cv2
import numpy as np

TrainSetInfo = {
	"car"		:	40,
	"city"		:	20,
	"dog"		:	30,
	"earth"		:	15,
	"fireworks"	:	20,
	"flowers"	:	20,
	"fruits"	:	20,
	"glass"		:	20,
	"gold"		:	15,
	"gun"		:	20,
	"plane"		:	40,
	"sky"		:	30,
	"worldcup"	:	40
}

TestSetInfo = {
	"car"		:	119,
	"city"		:	59,
	"dog"		:	49,
	"earth"		:	24,
	"fireworks"	:	54,
	"flowers"	:	63,
	"fruits"	:	78,
	"glass"		:	52,
	"gold"		:	44,
	"gun"		:	44,
	"plane"		:	102,
	"sky"		:	78,
	"worldcup"	:	131
}

def calcSiftFeature(img):
	gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
	sift = cv2.SIFT(200) # max number of SIFT points is 200
	kp, des = sift.detectAndCompute(gray, None)
	return des

def calcFeatVec(features, centers):
	featVec = np.zeros((1, 50))
	for i in range(0, features.shape[0]):
		fi = features[i]
		diffMat = np.tile(fi, (50, 1)) - centers
		sqSum = (diffMat**2).sum(axis=1)
		dist = sqSum**0.5
		sortedIndices = dist.argsort()
		idx = sortedIndices[0] # index of the nearest center
		featVec[0][idx] += 1	
	return featVec

def initFeatureSet():
	for name, count in TrainSetInfo.items():
		dir = "TrainSet/" + name + "/"
		featureSet = np.float32([]).reshape(0,128)

		print "Extract features from TrainSet " + name + ":"
		for i in range(1, count + 1):
			filename = dir + name + " (" + str(i) + ").jpg"
			img = cv2.imread(filename)
			des = calcSiftFeature(img)
			featureSet = np.append(featureSet, des, axis=0)
		
		featCnt = featureSet.shape[0]
		print str(featCnt) + " features in " + str(count) + " images
" # save featureSet to file filename = "Temp/features/" + name + ".npy" np.save(filename, featureSet) def learnVocabulary(): wordCnt = 50 for name, count in TrainSetInfo.items(): filename = "Temp/features/" + name + ".npy" features = np.load(filename) print "Learn vocabulary of " + name + "..." # use k-means to cluster a bag of features criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 0.1) flags = cv2.KMEANS_RANDOM_CENTERS compactness, labels, centers = cv2.kmeans(features, wordCnt, criteria, 20, flags) # save vocabulary(a tuple of (labels, centers)) to file filename = "Temp/vocabulary/" + name + ".npy" np.save(filename, (labels, centers)) print "Done
" def trainClassifier(): trainData = np.float32([]).reshape(0, 50) response = np.float32([]) dictIdx = 0 for name, count in TrainSetInfo.items(): dir = "TrainSet/" + name + "/" labels, centers = np.load("Temp/vocabulary/" + name + ".npy") print "Init training data of " + name + "..." for i in range(1, count + 1): filename = dir + name + " (" + str(i) + ").jpg" img = cv2.imread(filename) features = calcSiftFeature(img) featVec = calcFeatVec(features, centers) trainData = np.append(trainData, featVec, axis=0) res = np.repeat(np.float32([dictIdx]), count) response = np.append(response, res) dictIdx += 1 print "Done
" print "Now train svm classifier..." trainData = np.float32(trainData) response = response.reshape(-1, 1) svm = cv2.SVM() svm.train_auto(trainData, response, None, None, None) # select best params svm.save("svm.clf") print "Done
" def classify(): svm = cv2.SVM() svm.load("svm.clf") total = 0; correct = 0; dictIdx = 0 for name, count in TestSetInfo.items(): crt = 0 dir = "TestSet/" + name + "/" labels, centers = np.load("Temp/vocabulary/" + name + ".npy") print "Classify on TestSet " + name + ":" for i in range(1, count + 1): filename = dir + name + " (" + str(i) + ").jpg" img = cv2.imread(filename) features = calcSiftFeature(img) featVec = calcFeatVec(features, centers) case = np.float32(featVec) if (dictIdx == svm.predict(case)): crt += 1 print "Accuracy: " + str(crt) + " / " + str(count) + "
" total += count correct += crt dictIdx += 1 print "Total accuracy: " + str(correct) + " / " + str(total) if __name__ == "__main__": initFeatureSet() learnVocabulary() trainClassifier() classify()

좋은 웹페이지 즐겨찾기