Поиск и чтение больших файлов в приложении C++ Linux

Ниже приведены три подхода к решению этой проблемы (и есть много других).

  • Первый - это стандартный подход в компьютерном зрении, сопоставление ключевых точек. Это может потребовать некоторых базовых знаний для реализации и может быть медленным.

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

  • Третий метод является быстрым и надежным, но потенциально труднее всего его реализовать.

Соответствие ключевых точек

Лучше, чем набирать 100 случайных точек, - набирать 100 важных баллов. Некоторые части изображения содержат больше информации, чем другие (особенно на краях и углах), и именно эти вы хотите использовать для интеллектуального сопоставления изображений. Google " извлечение ключевых точек " и " сопоставление ключевых точек ", и вы найдете немало научных работ по этому вопросу. В наши дни ключевые точки SIFT являются, пожалуй, самыми популярными, поскольку они могут сопоставлять изображения в различных масштабах, поворотах и ​​освещении. Некоторые реализации SIFT можно найти здесь здесь .

Одним из недостатков сопоставления ключевых точек является время выполнения наивной реализации: O (n ^ 2m), где n - количество ключевых точек в каждом изображении, а m - количество изображений в базе данных. Некоторые умные алгоритмы могут находить ближайшее совпадение быстрее, например, квадродерево или разбиение двоичного пространства.


Альтернативное решение: метод гистограммы

Другим менее надежным, но потенциально более быстрым решением является построение гистограмм признаков для каждого изображения и выбор изображения с гистограммой, ближайшей к входу. гистограмма изображения. Я реализовал это как старшекурсник, и мы использовали 3 цветовые гистограммы (красная, зеленая и синяя) и две текстурные гистограммы, направление и масштаб. Я приведу подробности ниже, но я должен отметить, что это хорошо работает только для сопоставления изображений, ОЧЕНЬ похожих на изображения базы данных. Повторно масштабированные, повернутые или обесцвеченные изображения могут потерпеть неудачу с этим методом, но небольшие изменения, такие как обрезка, не нарушат алгоритм

Вычислить цветовые гистограммы несложно - просто выберите диапазон для гистограммных сегментов и для каждого диапазона подсчитайте количество пикселей с цветом в этом диапазоне. Например, рассмотрим «зеленую» гистограмму и предположим, что мы выбрали 4 сегмента для нашей гистограммы: 0-63, 64-127, 128-191 и 192-255. Затем для каждого пикселя мы смотрим на значение зеленого и добавляем подсчет в соответствующий сегмент. Когда мы закончим подсчет, мы делим каждое общее количество сегментов на количество пикселей во всем изображении, чтобы получить нормализованную гистограмму для зеленого канала.

Для гистограммы направления текстуры мы начали с определения края изображения. Каждая точка ребра имеет нормальный вектор, указывающий в направлении, перпендикулярном ребру. Мы квантовали угол вектора нормали в одно из 6 сегментов между 0 и PI (поскольку ребра имеют 180-градусную симметрию, мы конвертировали углы между -PI и 0, чтобы они были между 0 и PI). После подсчета количества краевых точек в каждом направлении мы имеем ненормализованную гистограмму, представляющую направление текстуры, которую мы нормализовали путем деления каждого сегмента на общее количество краевых точек в изображении.

Чтобы вычислить гистограмму масштаба текстуры, для каждой точки ребра мы измерили расстояние до следующей ближайшей точки ребра в том же направлении. Например, если точка края A имеет направление 45 градусов, алгоритм идет в этом направлении, пока не найдет другую точку края с направлением 45 градусов (или в пределах разумного отклонения). После вычисления этого расстояния для каждой граничной точки мы сбрасываем эти значения в гистограмму и нормализуем ее путем деления на общее количество краевых точек.

Теперь у вас есть 5 гистограмм для каждого изображения. Чтобы сравнить два изображения, вы берете абсолютное значение разности между каждым сегментом гистограммы, а затем суммируете эти значения. Например, чтобы сравнить изображения A и B, мы вычислили бы

|A.green_histogram.bucket_1 - B.green_histogram.bucket_1| 

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


Третий выбор - ключевые точки + деревья решений

Третий подход, который, вероятно, намного быстрее, чем два других, использует семантические леса текста (PDF ). Это включает в себя извлечение простых ключевых точек и использование деревьев решений коллекции для классификации изображения. Это быстрее, чем простое сопоставление ключевых точек SIFT, поскольку позволяет избежать дорогостоящего процесса сопоставления, а ключевые точки намного проще, чем SIFT, поэтому извлечение ключевых точек происходит намного быстрее. Тем не менее, он сохраняет неизменность метода SIFT к вращению, масштабированию и освещению, что является важной особенностью, которой не хватало в методе гистограммы.

Обновление :

Моя ошибка - статья Semantic Texton Forests посвящена не только сопоставлению изображений, но и маркировке регионов. Вот оригинальная статья, которая выполняет сопоставление: Распознавание ключевых точек с использованием рандомизированных деревьев . Кроме того, нижеприведенные статьи продолжают развивать идеи и представляют современное состояние (c. 2010):

14
задан Jon Seigel 19 March 2010 в 19:11
поделиться

5 ответов

fseek64 - это функция C. Чтобы сделать его доступным, вам нужно определить _FILE_OFFSET_BITS = 64 перед включением системных заголовков, которые более или менее определят, что fseek фактически является fseek64. Или сделайте это в аргументах компилятора, например gcc -D_FILE_OFFSET_BITS = 64 ....

http://www.suse.de/~aj/linux_lfs.html содержит большое количество поддержки больших файлов в Linux:

  • Компилируйте свои программы с помощью " gcc -D_FILE_OFFSET_BITS = 64 ". Это заставляет все вызовы доступа к файлам использовать 64-битные варианты. Также меняются некоторые типы, например off_t становится off64_t. Поэтому важно всегда использовать правильные типы и не использовать, например, int вместо off_t. Для совместимости с другими платформами вы должны использовать getconf LFS_CFLAGS, который вернет -D_FILE_OFFSET_BITS = 64 на платформах Linux, но может вернуть что-то еще, например, на Solaris. Для линковки вы должны использовать флаги ссылок, которые сообщаются через getconf LFS_LDFLAGS. В системах Linux вам не нужны специальные флаги ссылок.
  • Определите _LARGEFILE_SOURCE и _LARGEFILE64_SOURCE. С этими определениями вы можете напрямую использовать функции LFS, такие как open64.
  • Используйте флаг O_LARGEFILE с open для работы с большими файлами.
27
ответ дан 1 December 2019 в 06:21
поделиться

Пробовали ли вы использовать fseeko () с символом препроцессора _FILE_OFFSET_BITS , установленным на 64 ?

Это даст вам интерфейс, подобный fseek () , но с параметром смещения типа off_t вместо long . Установка _FILE_OFFSET_BITS = 64 сделает off_t 64-битным типом.

То же самое для ftello () .

5
ответ дан 1 December 2019 в 06:21
поделиться

fseek64 () не является стандартным, в документации по компилятору должно быть указано, где его найти.

Вы пробовали fgetpos и fsetpos ? Они предназначены для больших файлов, и реализация обычно использует 64-битный тип в качестве основы для fpos_t.

5
ответ дан 1 December 2019 в 06:21
поделиться

Используйте fsetpos (3) и fgetpos (3) . Они используют тип данных fpos_t , который, как мне кажется, гарантированно может содержать как минимум 64 бита.

2
ответ дан 1 December 2019 в 06:21
поделиться

Если вы хотите придерживаться стандартных интерфейсов ISO C, используйте fgetpos () и fsetpos () . Однако эти функции полезны только для сохранения позиции файла и возврата к той же позиции позже. Они представляют позицию с использованием типа fpos_t , который не обязательно должен быть целочисленным типом данных. Например, в системе на основе записей это может быть структура, содержащая номер записи и смещение внутри записи. Это может быть слишком ограничивающим.

POSIX определяет функции ftello () и fseeko () , которые представляют позицию с использованием типа off_t . Это должен быть целочисленный тип, а значение представляет собой смещение в байтах от начала файла. Вы можете выполнять над ним арифметические операции и использовать fseeko () для выполнения относительных поисков. Это будет работать в Linux и других системах POSIX.

Кроме того, скомпилируйте с -D_FILE_OFFSET_BITS = 64 (Linux / Solaris). Это определит off_t как 64-битный тип (то есть off64_t ) вместо long , и переопределит функции, которые используют смещения файлов, чтобы они были версиями которые принимают 64-битные смещения. Это значение по умолчанию при компиляции для 64-разрядной версии, поэтому в этом случае не требуется.

10
ответ дан 1 December 2019 в 06:21
поделиться