Итак, давайте посмотрим на пример, который они дают, и попробуем развернуть.
Предположим, у вас есть таблица, в которой хранится информация, относящаяся к каждому изображению (путь, имя, описание и т. Д.).В этой таблице вы включите поле для сжатой подписи, рассчитанной и сохраненной при первоначальном заполнении базы данных.Давайте определим эту таблицу следующим образом:
CREATE TABLE images (
image_id INTEGER NOT NULL PRIMARY KEY,
name TEXT,
description TEXT,
file_path TEXT NOT NULL,
url_path TEXT NOT NULL,
signature TEXT NOT NULL
);
Когда вы изначально вычисляете подпись, вы также собираетесь вычислить количество слов из подписи:
// this will be run once for each image:
$cvec = puzzle_fill_cvec_from_file('img1.jpg');
$words = array();
$wordlen = 10; // this is $k from the example
$wordcnt = 100; // this is $n from the example
for ($i=0; $i<min($wordcnt, strlen($cvec)-$wordlen+1); $i++) {
$words[] = substr($cvec, $i, $wordlen);
}
Теперь вы можете поместитьэти слова в таблицу, определенную следующим образом:
CREATE TABLE img_sig_words (
image_id INTEGER NOT NULL,
sig_word TEXT NOT NULL,
FOREIGN KEY (image_id) REFERENCES images (image_id),
INDEX (image_id, sig_word)
);
Теперь вы вставляете в эту таблицу, добавляя индекс позиции, где слово было найдено, чтобы вы знали, когда слово соответствует, что оно соответствует в том же самомпоместите в подписи:
// the signature, along with all other data, has already been inserted into the images
// table, and $image_id has been populated with the resulting primary key
foreach ($words as $index => $word) {
$sig_word = $index.'__'.$word;
$dbobj->query("INSERT INTO img_sig_words (image_id, sig_word) VALUES ($image_id,
'$sig_word')"); // figure a suitably defined db abstraction layer...
}
Таким образом, ваши данные инициализированы, вы можете сравнительно легко получить изображения с подходящими словами:
// $image_id is set to the base image that you are trying to find matches to
$dbobj->query("SELECT i.*, COUNT(isw.sig_word) as strength FROM images i JOIN img_sig_words
isw ON i.image_id = isw.image_id JOIN img_sig_words isw_search ON isw.sig_word =
isw_search.sig_word AND isw.image_id != isw_search.image_id WHERE
isw_search.image_id = $image_id GROUP BY i.image_id, i.name, i.description,
i.file_path, i.url_path, i.signature ORDER BY strength DESC");
Вы можете улучшить запрос, добавив предложение HAVING
для этого требуется минимум strength
, что еще больше сокращает ваш набор соответствий.
Я не даю никаких гарантий, что это наиболее эффективная настройка, но она должна быть примерно функциональной, чтобы выполнить то, что вы ищете.
По сути, разделение и хранение слов таким образом позволяет вам выполнять грубую проверку расстояния без необходимости запускать специализированную функцию в сигнатуре.Рез.