sql >> Databáze >  >> RDS >> Mysql

Libpuzzle Indexování milionů obrázků?

Podívejme se tedy na příklad, který uvádějí, a pokusme se jej rozšířit.

Předpokládejme, že máte tabulku, která ukládá informace týkající se každého obrázku (cesta, název, popis atd.). V této tabulce zahrnete pole pro komprimovaný podpis, vypočítaný a uložený při počátečním naplnění databáze. Definujme tuto tabulku takto:

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
);

Když zpočátku vypočítáte podpis, budete také počítat několik slov z podpisu:

// 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);
}

Nyní můžete tato slova vložit do tabulky definované takto:

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)
);

Nyní vložíte do této tabulky a přidáte před poziční index místa, kde bylo slovo nalezeno, abyste věděli, kdy se slovo shoduje s tím, že se shoduje na stejném místě v podpisu:

// 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...
}

Vaše data takto inicializovaná můžete poměrně snadno uchopit obrázky se shodnými slovy:

// $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");

Dotaz můžete vylepšit přidáním HAVING klauzule, která vyžaduje minimální strength , čímž se dále sníží vaše odpovídající sada.

Nezaručuji, že se jedná o nejúčinnější nastavení, ale mělo by být zhruba funkční, aby splnilo to, co hledáte.

V zásadě vám rozdělení a uložení slov tímto způsobem umožňuje provést hrubou kontrolu vzdálenosti, aniž byste museli spouštět speciální funkci na podpisy.



  1. SQL Pivot – Vědět, jak převést řádky na sloupce

  2. Parametry připojovacího řetězce pro zdroje textových souborů

  3. PHP a mySQL - ë napsáno jako «

  4. Jak vrátit tabulku z funkce MySQL