Windsurf (Wavelet-based INDexing of ImageS Using Region Fragmentation)



Software library

Windsurf system

Related papers


The Windsurf HowTo

Database creation

Both the Windsurf library and the Wrapper package contain classes referring to the MySQL DBMS for efficient storing/retrieval of image features. If you plan to use such classes, we provide here the SQL instructions needed to create your database (DB). In case you would like to use a different DBMS, you may need to modify such instructions accordingly.

-- Create DB db_name

USE db_name;

-- Definition of raw-data table rd_table_name

DROP TABLE IF EXISTS `rd_table_name`;
CREATE TABLE `rd_table_name` (
  `image_id` int(11) NOT NULL,
  `image_name` varchar(255) NOT NULL,
  PRIMARY KEY (`image_id`),
  KEY `Index_path` (`image_name`) USING BTREE

-- Definition of features table feat_table_name

DROP TABLE IF EXISTS `feat_table_name`;
CREATE TABLE `feat_table_name` (
  `id_img` int(11) NOT NULL,
  `numreg` int(11) NOT NULL,
  `size_img` int(20) NOT NULL,
  `id_reg` int(11) NOT NULL,
  `size_reg` int(15) NOT NULL,
  `centr_1` varchar(100) NOT NULL,
  `centr_2` varchar(100) NOT NULL,
  `centr_3` varchar(100) NOT NULL,
  `centr_4` varchar(100) NOT NULL,
  `cov_1` varchar(150) NOT NULL,
  `cov_2` varchar(150) NOT NULL,
  `cov_3` varchar(150) NOT NULL,
  `cov_4` varchar(150) NOT NULL,
  PRIMARY KEY (`id_img`,`id_reg`),
  KEY `id_img` (`id_img`),
  CONSTRAINT `features_fk` FOREIGN KEY (`id_img`) REFERENCES `rd_table_name` (`image_id`) ON DELETE CASCADE ON UPDATE CASCADE

Properties file

Parameters for connecting to the underlying MySQL DB can be conveniently stored in a properties file that will be used by some of the Wrapper classes (see below). Each properties file contains the following entries (in this particular order):

host_name       -- MySQL host name
port_number     -- MySQL port number
user_name       -- MySQL user login
passwd          -- MySQL user passwd
db_name         -- DB name
feat_table_name -- features table name
rd_table_name   -- raw-data table name

Feature extraction

In order to populate the image DB, each image should be processed so as to insert extracted features into the DB. This could be easily performed by way of the WrapperFeatureWindsurfMySQL Wrapper class. In order to create an object of the WrapperFeatureWindsurfMySQL class, three arguments should be provided: the path of the properties file (see above), the path of the directory that will contain temporary index files, and the base path for image files (this allows to use relative names in the image DB). Then, the extractImage method can be exploited to extract and store features for the image whose file name is given as parameter to the method.

        WrapperFeatureWindsurfMySQL wf=new WrapperFeatureWindsurfMySQL(propertiesFile, tempPath, relPath);
        ImageID id=wf.extractImage(imageFileName);
            System.out.println("Problems during features extraction for image: "+imageFileName);

Inserting into the index

For efficient access to image features, the Windsurf library also contains classes implementing M-tree-based indices. As detailed in our papers, Windsurf supports indices built on images and/or regions. The WrapperIndexWindsurf class provides a simplified access to the underlying M-tree indices. After having initialized the WrapperIndexWindsurf class object, using the names of the files containing the two indices, the insertNewImage and insertAllRegions methods allow the insertion of extracted features in the image and the region indices, respectively.

        WrapperIndexWindsurf.init(imageIndexName, regionIndexName, wf);
            System.out.println("Problems when inserting image "+imageFileName+" in the image index");
            System.out.println("Problems when inserting image "+imageFileName+" in the region index");

Index construction

Although it is possible to insert image features into an index following a one-by-one modality, this usually is not the most efficient way to create that index. Indeed, when you want to create an index over a set of images, the best way is to exploit the bulk-loading functionality of M-tree. In this way, a new (image/region) index can be efficiently built on all the features contained in an existing DB. This can be performed by way of the MySQL2Txt Wrapper class and of the createIndexBIN method of the WrapperIndexWindsurf class, as exemplified in the following.

        WrapperIndexWindsurf.init(imageIndexName, regionIndexName, wf);
        String regfile="regfeatures.txt", imgfile="imgfeatures.txt";
        File feature=new File(regfile);
        MySQL2Txt script=new MySQL2Txt(regfile);
        script.createRegionIndexFile((WindsurfFeatureManagerMySQL) wf.getFM());
        WrapperIndexWindsurf.createIndexBIN(false, regfile);
        feature=new File(imgfile);
        script=new MySQL2Txt(imgfile);
        script.createImageIndexFile((WindsurfFeatureManagerMySQL) wf.getFM());
        WrapperIndexWindsurf.createIndexBIN(true, imgfile);

Index-based k-NN query

Finally, we show how a simple k-NN query can be performed over an image DB. To this end, one should first decide which scoring function has to be used to compare images: the Windsurf library provides several alternatives, in the following we will use the EMD metric function, as implemented by the ScoringFunctionEMD class. The second step is to choose the algorithm for solving the query: in our example we will stick to the one exploiting the image M-tree-based index. To this end, one should use an instance of the WindsurfQuerySFMtree class, which can be defined by specifying the query image, the scoring function to be used, and the name of the file containing the image index. By way of the kNN method (whose sole parameter is the number of requested results, k) the user can obtain the result images as a vector of ScoredResultImage objects, containing ID and distance to the query for each of the k results.

        ScoringFunction sf=new ScoringFunctionEMD();
        WindsurfImage query=(WindsurfImage) wf.retrieveImage(new ImageIDnumerical(queryImageID));
        WindsurfQuerySFMtree alg=new WindsurfQuerySFMtree(query, sf, imageIndexName);
        Vector<ScoredResultImage> v=alg.kNN(k);
        for(int i=0; i<k; i++)
            System.out.println(v.get(i).toString(i, v.get(i).getID().toString()));