Я понимаю, что это популярный вопрос о переполнении стека, однако мне пока не удалось найти лучшее решение.
Фон
Я пытаюсь классифицировать изображение. В настоящее время у меня есть 10 000 уникальных изображений, которым может соответствовать данное изображение. Для каждого изображения в моей базе данных у меня есть только одно изображение для обучения. Итак, у меня есть БД 10000, и возможные выходные классы также 10000. Например, предположим, что есть 10000 уникальных объектов, и у меня есть одно изображение для каждого.
Цель состоит в том, чтобы сопоставить входное изображение с «лучшим» совпадающим изображением в БД.
В настоящее время я использую Python с OpenCV и библиотекой Sift для идентификации ключевых точек / дескрипторов. применяя стандартные методы сопоставления, чтобы увидеть, какое изображение в БД лучше всего подходит для входного изображения.
Код
Я использую следующий код для перебора своей базы данных изображений, чтобы затем найти все ключевые точки / дескрипторы и сохранить эти дескрипторы в файл. Это сэкономит время позже.
for i in tqdm(range(labels.shape[0])): #Use the length of the DB
# Read img from DB
img_path = 'data/'+labels['Image_Name'][i]
img = cv2.imread(img_path)
# Resize to ensure all images are equal for ROI
dim = (734,1024)
img = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
#Grayscale
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#Roi
img = img[150:630, 20:700]
# Sift
sift = cv2.xfeatures2d.SIFT_create()
keypoints_1, descriptors_1 = sift.detectAndCompute(img,None)
# Save descriptors
path = 'data/'+labels['Image_Name'][i].replace(".jpeg", "_descriptors.csv")
savetxt(path, descriptors_1, delimiter=',')
Затем, когда я буду готов классифицировать изображение, я смогу прочитать все дескрипторы. Это оказалось на 30% быстрее.
# Array to store all of the descriptors from SIFT
descriptors = []
for i in tqdm(range(labels.shape[0])): #Use the length of the DB
# Read in teh descriptor file
path = 'data/'+labels['Image_Name'][i].replace(".jpeg", "_descriptors.csv")
descriptor = loadtxt(path, delimiter=',')
# Add to array
descriptors.append(descriptor)
Наконец, мне просто нужно прочитать изображение, применить метод просеивания, а затем найти наилучшее совпадение.
# Calculate simaularity
img = cv2.imread(PATH)
# Resize
dim = (734,1024)
img = cv2.resize(img, dim, interpolation = cv2.INTER_AREA)
#Grayscale
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#Roi
img = img[150:630, 20:700]
# Sift
sift = cv2.xfeatures2d.SIFT_create()
keypoints_1, descriptors_1 = sift.detectAndCompute(img,None)
# Use Flann (Faster)
index_params = dict(algorithm=0, trees=5)
search_params = dict()
flann = cv2.FlannBasedMatcher(index_params, search_params)
# Store results
scoresdf = pd.DataFrame(columns=["index","score"])
#Find best matches in DB
for i in tqdm(range(labels.shape[0])):
# load in data
path = 'data/'+labels['Image_Name'][i].replace(".jpeg", "_descriptors.csv")
# Get descriptors for both images to compare
descriptors_2 = descriptors[i]
descriptors_2 = np.float32(descriptors_2)
# Find matches
matches = flann.knnMatch(descriptors_1, descriptors_2, k=2)
# select the lowest amount of keypoints
number_keypoints = 0
if len(descriptors_1) <= len(descriptors_2):
number_keypoints = len(descriptors_1)
else:
number_keypoints = len(descriptors_2)
# Find 'good' matches LOWE
good_points = []
ratio = 0.6
for m, n in matches:
if m.distance < ratio*n.distance:
good_points.append(m)
# Get simularity score
score = len(good_points) / number_keypoints * 100
scoresdf.loc[len(scoresdf)] = [i, score]
Все это работает, но это занимает некоторое время и Я хотел бы найти совпадение намного быстрее.
Решения?
Я читал о методе «мешок слова» (BOW). Тем не менее, я не знаю, будет ли это работать, учитывая, что есть 10000 классов. Нужно ли устанавливать K = 10000?
Учитывая, что каждый дескриптор является массивом, есть ли способ уменьшить мое пространство поиска? Могу ли я найти X ближайших массивов (дескрипторов) к дескриптору моего входного изображения?
Любая помощь будет принята с благодарностью:)
Редактировать
Можно ли использовать метод Bag of Words (BOW) для создания X кластеров. Затем, когда я читаю новое изображение, выясняю, к какому кластеру оно относится. Затем используйте сопоставление SIFT на изображениях в этом кластере, чтобы найти точное совпадение? Я изо всех сил пытаюсь найти много примеров кода для этого.