Libpuzzle Indexing millions of pictures?

后端 未结 4 1887
走了就别回头了
走了就别回头了 2020-12-12 14:03

its about the libpuzzle libray for php ( http://libpuzzle.pureftpd.org/project/libpuzzle ) from Mr. Frank Denis. I´am trying to understand how to index and store the data in

4条回答
  •  攒了一身酷
    2020-12-12 14:46

    So, let's take a look at the example they give and try to expand.

    Let's assume you have a table that stores information relating to each image (path, name, description, etc). In that table, you'll include a field for the compressed signature, calculated and stored when you initially populate the database. Let's define that table thus:

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

    When you initially compute the signature, you're also going to compute a number of words from the signature:

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

    Now you can put those words into a table, defined thus:

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

    Now you insert into that table, prepending the position index of where the word was found, so that you know when a word matches that it matched in the same place in the signature:

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

    Your data thus initialized, you can grab images with matching words relatively easily:

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

    You could improve the query by adding a HAVING clause that requires a minimum strength, thus further reducing your matching set.

    I make no guarantees that this is the most efficient setup, but it should be roughly functional to accomplish what you're looking for.

    Basically, splitting and storing the words in this manner allows you to do a rough distance check without having to run a specialized function on the signatures.

提交回复
热议问题