Python構(gòu)建圖像分類識(shí)別器的方法
機(jī)器學(xué)習(xí)用在圖像識(shí)別是非常有趣的話題。
我們可以利用OpenCV強(qiáng)大的功能結(jié)合機(jī)器學(xué)習(xí)算法實(shí)現(xiàn)圖像識(shí)別系統(tǒng)。
首先,輸入若干圖像,加入分類標(biāo)記。利用向量量化方法將特征點(diǎn)進(jìn)行聚類,并得出中心點(diǎn),這些中心點(diǎn)就是視覺碼本的元素。
其次,利用圖像分類器將圖像分到已知的類別中,ERF(極端隨機(jī)森林)算法非常流行,因?yàn)镋RF具有較快的速度和比較精確的準(zhǔn)確度。我們利用決策樹進(jìn)行正確決策。
最后,利用訓(xùn)練好的ERF模型后,創(chuàng)建目標(biāo)識(shí)別器,可以識(shí)別未知圖像的內(nèi)容。
當(dāng)然,這只是雛形,存在很多問題:
界面不友好。
準(zhǔn)確率如何保證,如何調(diào)整超參數(shù),只有認(rèn)真研究算法機(jī)理,才能真正清除內(nèi)部實(shí)現(xiàn)機(jī)制后給予改進(jìn)。
下面,上代碼:
import os
import sys
import argparse
import json
import cv2
import numpy as np
from sklearn.cluster import KMeans
# from star_detector import StarFeatureDetector
from sklearn.ensemble import ExtraTreesClassifier
from sklearn import preprocessing
try:
import cPickle as pickle #python 2
except ImportError as e:
import pickle #python 3
def load_training_data(input_folder):
training_data = []
if not os.path.isdir(input_folder):
raise IOError("The folder " + input_folder + " doesn't exist")
for root, dirs, files in os.walk(input_folder):
for filename in (x for x in files if x.endswith('.jpg')):
filepath = os.path.join(root, filename)
print(filepath)
object_class = filepath.split('\\')[-2]
print("object_class",object_class)
training_data.append({'object_class': object_class, 'image_path': filepath})
return training_data
class StarFeatureDetector(object):
def __init__(self):
self.detector = cv2.xfeatures2d.StarDetector_create()
def detect(self, img):
return self.detector.detect(img)
class FeatureBuilder(object):
def extract_features(self, img):
keypoints = StarFeatureDetector().detect(img)
keypoints, feature_vectors = compute_sift_features(img, keypoints)
return feature_vectors
def get_codewords(self, input_map, scaling_size, max_samples=12):
keypoints_all = []
count = 0
cur_class = ''
for item in input_map:
if count >= max_samples:
if cur_class != item['object_class']:
count = 0
else:
continue
count += 1
if count == max_samples:
print ("Built centroids for", item['object_class'])
cur_class = item['object_class']
img = cv2.imread(item['image_path'])
img = resize_image(img, scaling_size)
num_dims = 128
feature_vectors = self.extract_features(img)
keypoints_all.extend(feature_vectors)
kmeans, centroids = BagOfWords().cluster(keypoints_all)
return kmeans, centroids
class BagOfWords(object):
def __init__(self, num_clusters=32):
self.num_dims = 128
self.num_clusters = num_clusters
self.num_retries = 10
def cluster(self, datapoints):
kmeans = KMeans(self.num_clusters,
n_init=max(self.num_retries, 1),
max_iter=10, tol=1.0)
res = kmeans.fit(datapoints)
centroids = res.cluster_centers_
return kmeans, centroids
def normalize(self, input_data):
sum_input = np.sum(input_data)
if sum_input > 0:
return input_data / sum_input
else:
return input_data
def construct_feature(self, img, kmeans, centroids):
keypoints = StarFeatureDetector().detect(img)
keypoints, feature_vectors = compute_sift_features(img, keypoints)
labels = kmeans.predict(feature_vectors)
feature_vector = np.zeros(self.num_clusters)
for i, item in enumerate(feature_vectors):
feature_vector[labels[i]] += 1
feature_vector_img = np.reshape(feature_vector, ((1, feature_vector.shape[0])))
return self.normalize(feature_vector_img)
# Extract features from the input images and
# map them to the corresponding object classes
def get_feature_map(input_map, kmeans, centroids, scaling_size):
feature_map = []
for item in input_map:
temp_dict = {}
temp_dict['object_class'] = item['object_class']
print("Extracting features for", item['image_path'])
img = cv2.imread(item['image_path'])
img = resize_image(img, scaling_size)
temp_dict['feature_vector'] = BagOfWords().construct_feature(img, kmeans, centroids)
if temp_dict['feature_vector'] is not None:
feature_map.append(temp_dict)
return feature_map
# Extract SIFT features
def compute_sift_features(img, keypoints):
if img is None:
raise TypeError('Invalid input image')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
keypoints, descriptors = cv2.xfeatures2d.SIFT_create().compute(img_gray, keypoints)
return keypoints, descriptors
# Resize the shorter dimension to 'new_size'
# while maintaining the aspect ratio
def resize_image(input_img, new_size):
h, w = input_img.shape[:2]
scaling_factor = new_size / float(h)
if w < h:
scaling_factor = new_size / float(w)
new_shape = (int(w * scaling_factor), int(h * scaling_factor))
return cv2.resize(input_img, new_shape)
def build_features_main():
data_folder = 'training_images\\'
scaling_size = 200
codebook_file='codebook.pkl'
feature_map_file='feature_map.pkl'
# Load the training data
training_data = load_training_data(data_folder)
# Build the visual codebook
print("====== Building visual codebook ======")
kmeans, centroids = FeatureBuilder().get_codewords(training_data, scaling_size)
if codebook_file:
with open(codebook_file, 'wb') as f:
pickle.dump((kmeans, centroids), f)
# Extract features from input images
print("\n====== Building the feature map ======")
feature_map = get_feature_map(training_data, kmeans, centroids, scaling_size)
if feature_map_file:
with open(feature_map_file, 'wb') as f:
pickle.dump(feature_map, f)
# --feature-map-file feature_map.pkl --model- file erf.pkl
#----------------------------------------------------------------------------------------------------------
class ERFTrainer(object):
def __init__(self, X, label_words):
self.le = preprocessing.LabelEncoder()
self.clf = ExtraTreesClassifier(n_estimators=100,
max_depth=16, random_state=0)
y = self.encode_labels(label_words)
self.clf.fit(np.asarray(X), y)
def encode_labels(self, label_words):
self.le.fit(label_words)
return np.array(self.le.transform(label_words), dtype=np.float32)
def classify(self, X):
label_nums = self.clf.predict(np.asarray(X))
label_words = self.le.inverse_transform([int(x) for x in label_nums])
return label_words
#------------------------------------------------------------------------------------------
class ImageTagExtractor(object):
def __init__(self, model_file, codebook_file):
with open(model_file, 'rb') as f:
self.erf = pickle.load(f)
with open(codebook_file, 'rb') as f:
self.kmeans, self.centroids = pickle.load(f)
def predict(self, img, scaling_size):
img = resize_image(img, scaling_size)
feature_vector = BagOfWords().construct_feature(
img, self.kmeans, self.centroids)
image_tag = self.erf.classify(feature_vector)[0]
return image_tag
def train_Recognizer_main():
feature_map_file = 'feature_map.pkl'
model_file = 'erf.pkl'
# Load the feature map
with open(feature_map_file, 'rb') as f:
feature_map = pickle.load(f)
# Extract feature vectors and the labels
label_words = [x['object_class'] for x in feature_map]
dim_size = feature_map[0]['feature_vector'].shape[1]
X = [np.reshape(x['feature_vector'], (dim_size,)) for x in feature_map]
# Train the Extremely Random Forests classifier
erf = ERFTrainer(X, label_words)
if model_file:
with open(model_file, 'wb') as f:
pickle.dump(erf, f)
#--------------------------------------------------------------------
# args = build_arg_parser().parse_args()
model_file = 'erf.pkl'
codebook_file ='codebook.pkl'
import os
rootdir=r"F:\airplanes"
list=os.listdir(rootdir)
for i in range(0,len(list)):
path=os.path.join(rootdir,list[i])
if os.path.isfile(path):
try:
print(path)
input_image = cv2.imread(path)
scaling_size = 200
print("\nOutput:", ImageTagExtractor(model_file,codebook_file)\
.predict(input_image, scaling_size))
except:
continue
#-----------------------------------------------------------------------
build_features_main()
train_Recognizer_main()
以上這篇Python構(gòu)建圖像分類識(shí)別器的方法就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
如何在PyCharm中配置使用Anaconda環(huán)境
這篇文章主要介紹了如何在PyCharm中配置使用Anaconda環(huán)境,圖文講解寫的非常詳細(xì)簡單易懂,還不會(huì)的小伙伴快來看看吧2023-03-03
DRF跨域后端解決之django-cors-headers的使用
這篇文章主要介紹了DRF跨域后端解決之django-cors-headers的使用,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-01-01
Python sqlite3事務(wù)處理方法實(shí)例分析
這篇文章主要介紹了Python sqlite3事務(wù)處理方法,結(jié)合具體實(shí)例形式分析了Python針對(duì)sqlite3事務(wù)處理的操作技巧,代碼中包含詳盡的注釋,需要的朋友可以參考下2017-06-06
Python?第三方庫?Pandas?數(shù)據(jù)分析教程
這篇文章主要介紹了Python?第三方庫?Pandas?數(shù)據(jù)分析教程的相關(guān)資料,需要的朋友可以參考下2022-09-09
python向量化與for循環(huán)耗時(shí)對(duì)比分析
這篇文章主要介紹了python向量化與for循環(huán)耗時(shí)對(duì)比分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05
Python中dictionary items()系列函數(shù)的用法實(shí)例
這篇文章主要介紹了Python中dictionary items()系列函數(shù)的用法,很實(shí)用的函數(shù),需要的朋友可以參考下2014-08-08

