๐Ÿ˜Bow Plane Bike Train

import cv2
import numpy as np
import os, glob, time

# ๊ฐ์ข… ๋ณ€์ˆ˜ ์„ ์–ธ---โ‘ 
startT = time.time()                        # ์†Œ์š”์‹œ๊ฐ„ ์ธก์ •์„ ์œ„ํ•œ ์‹œ๊ฐ„ ์ €์žฅ
categories =  ['airplanes', 'Motorbikes' ]  # ์นดํ…Œ๊ณ ๋ฆฌ ์ด๋ฆ„ 
dictionary_size = 50                        # ์‚ฌ์ „ ํฌ๊ธฐ, ํด๋Ÿฌ์Šคํ„ฐ ๊ฐฏ์ˆ˜ 
base_path = "../img/101_ObjectCategories/"  # ํ•™์Šต ์ด๋ฏธ์ง€ ๊ธฐ๋ณธ ๊ฒฝ๋กœ 
dict_file = './plane_bike_dict.npy'         # ์‚ฌ์ „ ๊ฐ์ฒด ์ €์žฅํ•  ํŒŒ์ผ ์ด๋ฆ„ 
svm_model_file = './plane_bike_svm.xml'     # SVM ๋ชจ๋ธ ๊ฐ์ฒด ์ €์žฅํ•  ํŒŒ์ผ ์ด๋ฆ„ 

# ์ถ”์ถœ๊ธฐ์™€ BOW ๊ฐ์ฒด ์ƒ --- โ‘ก
detector = cv2.xfeatures2d.SIFT_create()    # ์ถ”์ถœ๊ธฐ๋กœ SIFT ์ƒ์„ฑ 
matcher = cv2.BFMatcher(cv2.NORM_L2)        # ๋งค์นญ๊ธฐ๋กœ BF ์ƒ์„ฑ
bowTrainer = cv2.BOWKMeansTrainer(dictionary_size) # KMeans๋กœ ๊ตฌํ˜„๋œ BWOTrainer ์ƒ์„ฑ
bowExtractor = cv2.BOWImgDescriptorExtractor(detector, matcher) # ํžˆ์Šคํ† ๊ทธ๋žจ ๊ณ„์‚ฐํ•  BOW์ถ”์ถœ๊ธฐ ์ƒ์„ฑ

# ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ KMeansTrainer์— ์ถ”๊ฐ€---โ‘ข
train_paths = []                            # ํ›ˆ๋ จ์— ์‚ฌ์šฉํ•  ๋ชจ๋“  ์ด๋ฏธ์ง€ ๊ฒฝ๋กœ 
train_labels = []                           # ํ•™์Šต ๋ฐ์ดํƒ€ ๋ ˆ์ด๋ธ”
print('Adding descriptor to BOWTrainer...')
for idx, category in enumerate(categories): # ์นดํ…Œ๊ณ ๋ฆฌ ์ˆœํšŒ
    dir_path = base_path + category          
    img_paths = glob.glob(dir_path +'/*.jpg') 
    img_len = len(img_paths)
    for i, img_path in enumerate(img_paths): # ์นดํ…Œ๊ณ ๋ฆฌ ๋‚ด์˜ ๋ชจ๋“  ์ด๋ฏธ์ง€ ํŒŒ์ผ ์ˆœํšŒ
        train_paths.append(img_path)        
        train_labels.append(idx)            # ํ•™์Šต ๋ฐ์ดํƒ€ ๋ ˆ์ด๋ธ”, 0 ๋˜๋Š” 1 
        img = cv2.imread(img_path)          
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        # ํŠน์ง•์ ๊ณผ ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ ์ถ”์ถœ ๋ฐ bowTrainer์— ์ถ”๊ฐ€ ---โ‘ฃ
        kpt, desc= detector.detectAndCompute(gray, None) 
        bowTrainer.add(desc)                
        print('\t%s %d/%d(%.2f%%)' \
              %(category,i+1, img_len, (i+1)/img_len*100), end='\r')
    print()
print('Adding descriptor completed...')

# KMeans ํด๋Ÿฌ์Šคํ„ฐ๋กœ ๊ตฐ์ง‘ํ™”ํ•˜์—ฌ ์‹œ๊ฐ ์‚ฌ์ „ ์ƒ์„ฑ ๋ฐ ์ €์žฅ---โ‘ค
print('Starting Dictionary clustering(%d)... \
        It will take several time...'%dictionary_size)
dictionary = bowTrainer.cluster() # ๊ตฐ์ง‘ํ™”๋กœ ์‹œ๊ฐ ์‚ฌ์ „ ์ƒ์„ฑ  
np.save(dict_file, dictionary)    # ์‹œ๊ฐ ์‚ฌ์ „ ๋ฐ์ดํƒ€(๋„˜ํŒŒ์ผ)๋ฅผ ํŒŒ์ผ๋กœ ์ €์žฅ
print('Dictionary Clustering completed...dictionary shape:',dictionary.shape)

# ์‹œ๊ฐ ์‚ฌ์ „๊ณผ ๋ชจ๋“  ์ด๋ฏธ์ง€์˜ ๋งค์นญ์ ์œผ๋กœ ํžˆ์Šคํ† ๊ทธ๋žจ ๊ณ„์‚ฐ---โ‘ฅ
bowExtractor.setVocabulary(dictionary)      # bowExtractor์— ์‹œ๊ฐ ์‚ฌ์ „ ์…‹ํŒ… 
train_desc = []                             # ํ•™์Šต ๋ฐ์ดํƒ€ 
for i, path in enumerate(train_paths):      # ๋ชจ๋“  ํ•™์Šต ๋Œ€์ƒ ์ด๋ฏธ์ง€ ์ˆœํšŒ
    img = cv2.imread(path)                  # ์ด๋ฏธ์ง€ ์ฝ๊ธฐ 
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 
    # ๋งค์นญ์ ์— ๋Œ€ํ•œ ํžˆ์Šคํ† ๊ทธ๋žจ ๊ณ„์‚ฐ --- โ‘ฆ
    hist = bowExtractor.compute(gray, detector.detect(gray)) 
    train_desc.extend(hist)                 
    print('Compute histogram training set...(%.2f%%)'\
                    %((i+1)/len(train_paths)*100),end='\r')
print("\nsvm items", len(train_desc), len(train_desc[0]))

# ํžˆ์Šคํ† ๊ทธ๋žจ์„ ํ•™์Šต๋ฐ์ดํƒ€๋กœ SVM ํ›ˆ๋ จ ๋ฐ ๋ชจ๋ธ ์ €์žฅ---โ‘ง
print('svm training...')
svm = cv2.ml.SVM_create()
svm.trainAuto(np.array(train_desc), cv2.ml.ROW_SAMPLE, np.array(train_labels))
svm.save(svm_model_file)
print('svm training completed.')
print('Training Elapsed: %s'\
        %time.strftime('%H:%M:%S', time.gmtime(time.time()-startT)))

# ์›๋ž˜์˜ ์ด๋ฏธ์ง€๋กœ ํ…Œ์ŠคํŠธ --- โ‘จ
print("Accuracy(Self)")
for label, dir_name in enumerate(categories):
    labels = []
    results = []
    img_paths = glob.glob(base_path + '/'+dir_name +'/*.*')
    for img_path in img_paths:
        labels.append(label)
        img = cv2.imread(img_path)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        feature = bowExtractor.compute(gray, detector.detect(gray))
        ret, result = svm.predict(feature)
        resp = result[0][0]
        results.append(resp)

    labels = np.array(labels)
    results = np.array(results)
    err = (labels != results)
    err_mean = err.mean()
    print('\t%s: %.2f %%' % (dir_name, (1 - err_mean)*100))

์ถœ๋ ฅ๊ฒฐ๊ณผ

[ WARN:0@0.050] global shadow_sift.hpp:15 cv::xfeatures2d::SIFT_create DEPRECATED: cv.xfeatures2d.SIFT_create() is deprecated due SIFT tranfer to the main repository. https://github.com/opencv/opencv/issues/16736
Adding descriptor to BOWTrainer...
        airplanes 800/800(100.00%)
        Motorbikes 798/798(100.00%)
Adding descriptor completed...
Starting Dictionary clustering(50)...         It will take several time...
Dictionary Clustering completed...dictionary shape: (50, 128)
Compute histogram training set...(100.00%)
svm items 1598 50
svm training...
svm training completed.
Training Elapsed: 00:02:13
Accuracy(Self)
        airplanes: 94.50 %
        Motorbikes: 96.24 %