Mysql
 sql >> база данни >  >> RDS >> Mysql

Libpuzzle Индексиране на милиони снимки?

И така, нека да разгледаме примера, който дават, и да се опитаме да разширим.

Да предположим, че имате таблица, която съхранява информация, свързана с всяко изображение (път, име, описание и т.н.). В тази таблица ще включите поле за компресирания подпис, изчислен и съхранен, когато първоначално попълвате базата данни. Нека дефинираме тази таблица по следния начин:

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 , като по този начин допълнително намалявате вашия съвпадащ набор.

Не давам никакви гаранции, че това е най-ефективната настройка, но трябва да е приблизително функционална, за да постигнете това, което търсите.

По принцип разделянето и съхраняването на думите по този начин ви позволява да направите груба проверка на разстоянието, без да се налага да изпълнявате специализирана функция върху подписите.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. CakePHP 3 - Анализирайте датата с LocalStringFormat за коригиране на SQL формат и правилна валидация

  2. Ефективно съхраняване на 7 300 000 000 реда

  3. Минимизиране на SQL заявки чрез присъединяване с връзка един към много

  4. Как да конфигурирам Rails за достъп без парола до отдалечена база данни

  5. MySQL str_to_date произвежда NULL въпреки валидното форматиране