Как определить паттерн на изображении с использованием OpenCV?

Мне нужно найти этикетки с помощью OpenCV. В приложении 1 представлена сама этикетка, в приложении 2 - изображение, на котором необходимо её обнаружить, а в приложении 3 - результаты работы программы. Она отображает результаты на объекте, который не имеет отношения к искомой этикетке, при этом это наиболее удачный результат по сравнению с методами cv2.TM_CCORR и cv2.TM_CCOEFF. Какую стратегию можно использовать для улучшения поиск этикеток на изображении?
  • 20 ноября 2024 г. 19:03
Ответы на вопрос 2
Поиск паттернов на изображении, особенно этикеток, может быть сложной задачей. Ваша проблема может возникать из-за множества факторов, но давайте рассмотрим стратегии, которые могут помочь улучшить точность обнаружения этикеток с использованием OpenCV.

### 1. Предобработка изображений
   - **Улучшение контрастности**: Используйте методы изменения контрастности, такие как CLAHE (Contrast Limited Adaptive Histogram Equalization), чтобы улучшить видимость этикеток.
   - **Фильтрация шума**: Применяйте фильтры (например, Gaussian или Median) для уменьшения шума на изображении.

### 2. Использование методов детекции объектов
   - **Методы компьютерного зрения**: Вместо простого шаблонного сопоставления (cv2.matchTemplate) можно использовать более сложные методы, такие как:
     - **HOG (Histogram of Oriented Gradients)**: Метод детекции объектов, хорошо справляющийся с изменениями в освещении и масштабе.
     - **```SIFT``` или ```ORB```**: Извлечение ключевых точек из шаблона и изображения с использованием алгоритмов SIFT или ORB, затем сопоставление ключевых точек с помощью FLANN или BFMatcher.
   
### 3. Применение машинного обучения
   - **Обучение классификатора**: Можно использовать алгоритмы машинного обучения (например, SVM, Random Forest) для обучения классификаторов на основе извлеченных характеристик (фичей) из изображений этикеток.
   - **Нейронные сети**: Использование более продвинутых подходов, таких как использование сверточных нейронных сетей (CNN), для детекции объектов на изображении.

### 4. Постобработка
   - **Фильтрация ложных срабатываний**: После первичного обнаружения можно использовать правила (например, размер и форма обнаруженной области), чтобы удалить ложные срабатывания.
   - **Смотреть на локализацию**: Если у вас есть информация о том, где этикетка может находиться на изображении, это может помочь уменьшить пространство поиска.

### 5. Группировка и объединение результатов
   - **Non-maximum Suppression (NMS)**: Если обнаруживается несколько областей, соответствующих одной метке, объедините их с помощью NMS для улучшения локализации.

### Пример кода
Вот пример, как использовать ORB для обнаружения ключевых точек и сопоставления их между изображением этикетки и целевым изображением.

```python
import cv2

# Загружаем изображения
template = cv2.imread('template.jpg', cv2.IMREAD_GRAYSCALE)
target = cv2.imread('target.jpg', cv2.IMREAD_GRAYSCALE)

# Создаем ORB детектор
orb = cv2.ORB_create()

# Находим ключевые точки и дескрипторы
kp1, des1 = orb.detectAndCompute(template, None)
kp2, des2 = orb.detectAndCompute(target, None)

# Сопоставляем дескрипторы
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(des1, des2)

# Сортируем и визуализируем результаты
matches = sorted(matches, key=lambda x: x.distance)

# Рисуем найденные соответствия
result_img = cv2.drawMatches(template, kp1, target, kp2, matches[:10], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)

cv2.imshow('Matches', result_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
```

### Заключение
Подход к обнаружению этикеток можно адаптировать с учетом особенностей ваших данных. Возможно, потребуется попробовать несколько методов в комбинации или в последовательности, чтобы добиться наилучших результатов.
Во-первых, оформи код, нечитаемо. Кнопка  в помощь. 
Во-вторых, matchTemplate(), насколько я знаю, не-инвариантна к поворотам и масштабу. Иными словами, поворот или изменение размера целевого объекта сломают сопоставление.
В-третьих, на показанном кадре более одного экземпляра целевого объекта. Так предполагается или нет? Если предполагается, сколько экземпляров ожидается? Потому что разница очень большая с точки зрения методики.

Варианта тут три.
1. пытаться обучать под задачу нейронку. А лучше дообучить существующую, скажем, YOLOv5 . Но тебе потребуется минимум несколько сотен размеченных изображений объекта в разных комбинациях, плюс в 2-3 раза больше похожих изображений без целевого объекта. Готовить такую базу будет утомительно, да и само обучение требует понимания что ты делаешь.
2. попробовать зафиксировать угол поворота или масштаб (т.е. допустить, что он всегда одинаков). Тогда другой параметр можно будет подбирать. Например, мы фиксируем масштаб и делаем 16 изображений объекта в разных поворотах, а потом поочерёдно ищем каждый вариант на кадре. Потом анализируем силу откликов - сколько их, насколько они сильные и т.д. Скорее всего, будет медленно
3. взять за основу поиск по локальным особенностям. Он справляется с масштабом и поворотом, но не справляется с несколькими экземплярами объекта. Это можно забороть, если использовать скользящее окно. Иными словами, находим на кадре узнаваемые точки - локальные особенности (желательно достаточно много и достаточно плотно), используя алгоритмы вроде ORB или SIFT. Затем выбираем те из них, которые попадают в прямоугольную рамку-окно. Затем сверяем эти особенности с особенностями объекта, используя RANSAC или подобный метод. Если получилось хороше совпадение - значит, в этой рамке есть объект или значительная его часть, и мы можем оценить его позицию в кадре в целом. Повторяем процесс, сдвигая рамку, пока оно не "обойдёт" всё изображение. Тоже может быть небыстро, так как нам требуется неоднократный поиск по картинке.
Похожие вопросы