Библиотека AVM SDK simple.NET

Материал из roboforum.ru Wiki
Перейти к: навигация, поиск

Содержание

Реализация алгоритма AVM (Associative Video Memory) под C#

Возможности алгоритма AVM

Алгоритм "Associative Video Memory" (AVM) использует принцип многоуровневой декомпозиции матриц распознавания, устойчив к шумам камеры, хорошо масштабируется, просто и быстро обучается, показывает приемлемое быстродействие на больших разрешениях входного видео (960x720 и больше). Алгоритм работает с полутоновыми (черно-белыми) изображениями.

Чем может быть полезен для вас алгоритм AVM?

Технология AVM – коммерческий проект, но Вы можете использовать AVM SDK абсолютно бесплатно в ваших некоммерческих проектах.

- Вы можете использовать AVM для отработки ваших собственных гипотез в области автономной навигации робота,
  основанной на визуальных ориентирах. И если эффективное решение в области навигации будет достигнуто,
  то далее будет возможным либо разработать ваш собственный алгоритм распознавания, и заменить AVM
  в вашем финальном (коммерческом) проекте, или использовать коммерческую версию алгоритма AVM.
- Вы можете использовать алгоритм AVM для сравнительных тестов по качеству распознавания при разработке
  собственного (вашего) алгоритма распознавания.

Структура библиотеки (реализация)

В состав реализации AVM SDK simple.NET входят две динамических библиотеки:

* avm061.dll – библиотека реализации алгоритма AVM;
* AVM_api.dll – библиотека wrapper, обеспечивающая C# интерфейс.

Исходные файлы проекта интерфейсной библиотеки AVM_api.dll расположены в папке: .\AVM_SDK_simple.net\AVM_api\AVM_api.csproj

Всё что нужно для подключения алгоритма AVM – это включение библиотек avm061.dll и AVM_api.dll в ваш проект. В качестве входных данных алгоритм AVM использует изображения в формате Bitmap.

Пакет AVM SDK simple.NET можно скачать здесь: [1]

Быстрый старт

Что нужно для обучения?

1. Создать экземпляр AVM: _am = new CvAssociativeMemory32S();
2. Выполнить инициализацию экземпляра (методы: Create, Load, или ReadPackedData): _am.Load(cRcgDataFileName);
3. Установить изображение для обработки: _am.SetImage(ref aSrcImage);
4. Записать новый образ в дерево поиска AVM: _am.Write(InterestArea, ObjIndex, true).

Что нужно для распознавания?

1. Выполнить пункты 1-3 описанные выше;
2. Прочитать массив описателей объектов (методы: ObjectTracking/ObjectRecognition): Array SeqObjDsr = _am.ObjectTracking(true, 0.54, 0.45);
3. Если массив не пуст (объекты найдены), то в цикле обработать массив описателей распознанных объектов.

Более подробно можно посмотреть в папке примеров использования AVM: .\AVM_SDK_simple.net\samples

Описание методов

void Create(Size aKeyImgSize, short aLevelMax, int aTreeTotal, bool aClustering);

Инициализация экземпляра AVM.

aKeyImgSize – ключевой размер изображения. В большинстве случаев оптимальное значение 80x80 пикселей.
aLevelMax   – максимальное количество уровней поискового дерева. Если параметр равен нулю,
              то будет установлено оптимальное значение по умолчанию.
aTreeTotal  – общее количество поисковых деревьев, при работе с коллекциями деревьев.
              По умолчанию равен 1 (одно поисковое дерево).
aClustering – признак использования дополнительных кластерных матриц в дереве поиска (для ускорения поиска).
              По умолчания включен (true).

void Write(Rectangle aInterestArea, int apData, bool aDeepLearning);

С помощью метода Write происходить "связывание" фрагмента изображения (первый параметр) с данными пользователя (второй параметры), в случае CvAssociativeMemory32S - это индекс объекта. Затем эти данные можно считать с помощью метода Read, если просканировать изображение окошком разного размера, и найти объект/объекты, что собственно и делает метод ObjectTracking/ObjectRecognition.

aInterestArea – область интереса, фрагмент изображения содержащий объект;
apData        – данные пользователя;
aDeepLearning – признак «углублённого» обучения (дополнительное сканирование в окрестности объекта).
                По умолчанию включен (true).

bool Read(Rectangle aInterestArea, ref Rectangle apSearchArea, ref IntPtr appData, ref UInt64 apIndex, ref UInt64 apHitCounter, ref double apSimilarity, bool aTotalSearch);

Чтение данных из памяти (третий параметр), которые проассоциированы с фрагментом изображения (первый параметр).

aInterestArea – область интереса;
apSearchArea  – область изображения, где был найден объект;
appData       – указатель на данные пользователя;
apIndex       – индекс ассоциативного ядра (откуда прочитаны данные);
apHitCounter  – счётчик попаданий в ассоциативное ядро;
apSimilarity  – коэффициент схожести с эталоном (если больше 0.5, то объект распознан);
aTotalSearch  – признак «тотального» поиска до последнего уровня дерева поиска
                (найдёт наиболее похожий образ в дереве поиска, даже если распознавание не произошло).

Метод возвращает значение true если в области интереса найден объект.

Array ObjectRecognition();

Выполняет сканирование изображения методом Read и возвращает массив описателей распознанных объектов.

Array ObjectTracking(bool aTrainingDuringTracking, double aSimilarityUpTrd, double aSimilarityDnTrd);

Выполняет поиск и прослеживание объектов. Возвращает массив описателей прослеживаемых объектов.

aTrainingDuringTracking – признак дополнительного обучения в процессе прослеживания объекта.
                          По умолчанию включен (true).
aSimilarityUpTrd        – верхний порог схожести ниже которого будет выполнено дополнительное
                          обучение на прослеживаемый объект (по умолчанию равен 0.54).
aSimilarityDnTrd        – нижний порог схожести выше которого ещё может быть выполнено дополнительное
                          обучение (по умолчанию равен 0.45).

Структура описателя объекта CvObjDsr32S:

State      – состояние функции распознавания;
ObjRect    – габариты найденного объекта;
Similarity – коэффициент сходства найденного объекта с эталоном (если больше 0.5 объект распознан);
Data       – ассоциированные с объектом данные пользователя;
Trj        – траектория движения объекта (в виде массива из 100 точек).

State:

cRecognizedObject  - распознан фрагмент изображения;
cGeneralizedObject - вычислены габариты обобщённой области объекта (метод ObjectRecognition);
cTrackedObject     - вычислены габариты прослеживаемого объекта (метод ObjectTracking);
cLearnThisObject   - индикация дополнительного обучения.

void Destroy();

Полностью освобождает все структуры памяти, которые были задействованы в AVM. После этого экземпляр AVM дальше работать не может, и необходимо инициализировать экземпляр с помощью одного из методов Create, Load, или ReadPackedData.

void SetActiveTree(int aTreeIdx);

Устанавливает (переключает) текущее дерево поиска из коллекции деревьев (см. Create третий параметр).

aTreeIdx – индекс дерева поиска (от нуля).

void ClearTreeData();

После вызова метода ClearTreeData дерево поиска обнуляется, но структуры данных, которые были созданы методом Create остаются, и можно продолжить обучение методом Write.

bool Save(string aFileName, bool aSaveWithoutOptimization);

Сохранение данных распознавания в файл.

aFileName – имя файла;
aSaveWithoutOptimization – признак выполнения предварительной оптимизации дерева поиска перед сохранением.
                           По умолчанию включён (true).

Если сохранение данных распознавания прошло успешно, возвращает true.

bool Load(string aFileName);

Загрузка данных распознавания из файла.

aFileName – имя файла;

Если загрузка данных распознавания прошло успешно, возвращает true.

CvRcgData WritePackedData();

Записывает данные распознавания в виде массива байтов, после чего данные могут быть помещены в пользовательские структуры (совместно с другими данными) и сохранены в файле.

void ReadPackedData(CvRcgData aRcgData);

Считывает данные распознавания из байтового массива, сформированного предварительно методом WritePackedData.

void OptimizeAssociativeTree();

Выполняет оптимизацию дерева поиска, в процессе которой ассоциативные ядра, у которых количество попаданий меньше порогового значения удаляются из дерева поиска.

void RestartTimeForOptimization();

Сбрасывает в исходное состояние таймер, который отсчитывает время до следующей оптимизации дерева поиска.

double EstimateOpportunityForTraining(Rectangle aInterestArea);

Возвращает коэффициент, который индицирует возможность обучения на область интереса (aInterestArea). Если метод возвращает значение меньше чем 0.015, то область интереса может не достаточно эффективно распознаваться.

void SetImage(ref Bitmap apSrcImg);

Устанавливает изображение apSrcImg для дальнейшей обработки (обучения/распознавания).

int GetTotalABases();

Возвращает общее количество ассоциативных ядер в дереве поиска.

short GetTotalLevels();

Возвращает общее количество уровней дерева поиска.

UInt64 GetCurIndex();

Возвращает текущий индекс последнего добавленного в дерево поиска ассоциативного ядра.

UInt64 GetWrRdCounter();

Возвращает счётчик циклов чтения/записи.

Size GetKeyImageSize();

Возвращает ключевой размер, установленный при инициализации методом Create.

Size GetBaseKeySize();

Возвращает базовый ключевой размер (40, 80, 160, … 2^n*10).

void SetParam(CvAM_ParamType aParam, double aValue);

Устанавливает значение (aValue) параметра (aParam) для экземпляра AVM.

Сразу хочу сказать, что по умолчанию параметры установлены оптимально для большинства случаев, но если есть желание поэкспериментировать (поиграть настройками), то тогда, пожалуйста:

Параметр ptRcgMxCellBase устанавливает базовое значение, которое используется в расчётах порога распознавания (по умолчанию равен 20000). Если это значение увеличивать, то количество прямых срабатываний (должно распознать и распознало) будет увеличиваться но будет увеличиваться и количество ложных срабатываний (не должно распознать, но распознало).

С заданной периодичностью происходит оптимизация поискового дерева AVM, и ядра которые появились в процессе обучения, но не набравшие определённого количества попаданий будут удалены из поискового дерева в процессе оптимизации. Оптимизацию можно инициировать непосредственно вызвав метод OptimizeAssociativeTree, а можно установить период с которым будет выполняться оптимизация с помощью параметра ptOptimizeLoop. Возраст (количество попаданий) сформировавшегося ядра можно назначить с помощью параметра ptMaxClusterAge. Увеличивая периодичность срабатываний оптимизации и при этом манипулируя возрастом сформировавшегося ядра, в процессе обучения можно избавляться (прореживать, отсеивать) от лишних «шумовых» образов.

Параметр «глубины» прослеживания ptTrackingDepth определяет пороговое значения количества кадров на которых объект не был обнаружен, после чего прослеживание будет прекращено. По умолчанию установлено 40 кадров (около 1.5 секунды), полезно уменьшить это значение, если происходит управление роботов в реальном масштабе времени, так как объекта к примеру нету в кадре уже полтары секунды а робот продолжает на него выравниваться и соответственно управление происходит не корректно. Я в своих экспериментах по управлению роботом, устанавливал SetParam(ptTrackingDepth, 2).

Implementation of the algorithm AVM for C#: Library AVM SDK simple.NET