Python - Сравнивайте сходство / классифицируйте изображения с помощью SIFT-дескрипторов - PullRequest
0 голосов
/ 16 апреля 2020

Я понимаю, что это популярный вопрос о переполнении стека, однако мне пока не удалось найти лучшее решение.

Фон

Я пытаюсь классифицировать изображение. В настоящее время у меня есть 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 на изображениях в этом кластере, чтобы найти точное совпадение? Я изо всех сил пытаюсь найти много примеров кода для этого.

...