sql >> Database teknologi >  >> RDS >> Mysql

Libpuzzle Indeksering af millioner af billeder?

Så lad os tage et kig på det eksempel, de giver, og prøve at udvide.

Lad os antage, at du har en tabel, der gemmer information vedrørende hvert billede (sti, navn, beskrivelse osv.). I denne tabel vil du inkludere et felt for den komprimerede signatur, beregnet og gemt, når du først udfylder databasen. Lad os definere den tabel således:

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

Når du først beregner signaturen, skal du også beregne et antal ord fra signaturen:

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

Nu kan du sætte disse ord ind i en tabel, defineret således:

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

Nu indsætter du i den tabel, foran positionsindekset for, hvor ordet blev fundet, så du ved, hvornår et ord matcher, at det matchede på samme sted i signaturen:

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

Dine data er således initialiseret, du kan relativt nemt fange billeder med matchende ord:

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

Du kan forbedre forespørgslen ved at tilføje en HAVING klausul, der kræver en minimum strength , hvilket yderligere reducerer dit matchende sæt.

Jeg garanterer ikke, at dette er den mest effektive opsætning, men den burde være nogenlunde funktionel for at opnå det, du leder efter.

Grundlæggende giver opdeling og lagring af ordene på denne måde dig mulighed for at foretage en grov afstandskontrol uden at skulle køre en specialiseret funktion på signaturerne.



  1. mysql-tjenesten starter ikke/lægger på - timeout (Ubuntu, MariaDB)

  2. Brug af SSHTunnelForwarder til at oprette forbindelse til en MySQL db via SSH

  3. Hvorfor bruge join i MySQL-forespørgsler i stedet for hvor?

  4. Hvad svarer til 'beskriv tabel' i SQL Server?