The QBIC API has two levels of functionality, as described in the following sections:
At the higher level are command-line programs such as QbMkDbs, QbQBE, QbMkThmb, and QbDumpDb. These programs have been compiled on different platforms, and provide the following functionality:
You can run these programs in a command shell, or call them from your application using system or execl calls.
QBIC provides a high-level "wrapper" class, called QbicWrapClass, around the functions mentioned in QBIC Command-Line Programs, making the functions accessible directly from C++.
You simply create a QbicWrapClass object in your application, and then invoke the appropriate class method for the needed functionality. Details about the class and methods are described in "QbWrapClass" on page 31.
At lower level, QBIC provides a set of abstract C++ classes and a few fully implemented classes to provide QBIC functionality, such as database connection and management, feature data computation, and so on. The QBIC abstract C++ classes are classes that use pure virtual functions to define the interface, forcing the derived classes to specify the implementation. Programs cannot create instances of abstract classes-only pointers to abstract classes are allowed.
The QBIC API is designed to be extensible, which means that you can add new feature computation classes to QBIC in order to extend its functionality. Although the API was designed primarily for query by image content, it is general enough to process other media data types, such as video, audio, and text.
If you are familiar with the Object Management Group's Object Query Service (OQS) model, the low-level QBIC API maps classes and methods to the OQS model when possible, but it is not a full OQS implementation. For example, many of the QBIC classes implement the ToQueryString and FromQueryString methods to convert an instance of the class to an ASCII string. You can pass the ASCII string across process or machine boundaries in a client/server environment.
Abstract class definitions are briefly described in the following sections:
For details, please see later chapters in this manual. Header files that provide details of the C++ definitions for these classes are available in the qbic/QbicApi/include
subdirectory. Using this framework, you can define generic functions to populate and query a database.
The low-level class hierarchy is shown in Figure 1 on page 13.
Figure 1. Low-Level Class Hierarchy
The hierarchy uses only single inheritance. The naming convention for classes is QbDescriptivePhraseClass. Member functions are named in mixed case with the first character in uppercase. Variables are named in mixed case with the first letter in lowercase. For example, QbThisIsAClass, ThisIsAMemberFunction and thisIsAVariable are consistent with the naming convention.
QbDatumClass contains a pointer to a byte string, the length of the byte string, and a character description of the format. The member functions Get and Set allow getting and setting of the pointer and size variables. The functions GetFormatInfo and SetFormatInfo allow access to the format information. QbDatumClass supports marking of allocated memory so it can be deleted, freed, or left alone in the destructor or when reassigned using Set. It also has an assignment operator.
The class QbGenericDataClass is a class that defines generic data, such as image, video, character, and audio. This class encapsulates the data between the feature extraction process, the user interface, and external data, such as image files.
QbParameterClass is a class to encapsulate the parameters associated with a query. Both classes define the member functions ToQueryString and FromQueryString. These member functions are used to convert the class to an ASCII query string to allow the query to be passed from the client to the server query engine.
QbParameterClass is a full implementation of an array of name/value pairs for any of the feature classes.
QbGenericDataClass is a full implementation that gives a standardized way to pass query by example or query from a sampler between client and server. It also gives a standard way of passing domain-specific information between client and server. It does nothing to document the format of the domain-specific data. To do this, the class should be subclassed, and the domain-specific data can be specified. In the subclassed version, ToQueryString should take the domain-specific data and put it into QbGenericDataClass' QbDatumClass field named "data." Then it should call the base class ToQueryString function to encode both the generic information and the domain-specific information. FromQueryString reverses this process. An example of this process is in QbGenericImageDataClass.
To obtain a connection to a database or a filesystem, use QbConnectClass. The Connect/Disconnect call establishes a connection to a database or mounts a filesystem-processing that is expensive and typically only done once. The function QbGetConnection in the file QbCreate.cpp
implements the simple one-connection-per-address-space connection needed by the current engine.
QbGetConnection takes two arguments: the name of the data set, and the name of the connection class. It returns a const pointer instance of the connection class. Because it is const, you cannot Disconnect, Connect or delete the pointer. However, you can create instances of a database appropriate for this connection using the function CreateDatabaseClass and CreateKeyDatabaseClass.
Use the function QbDestroyConnection, also in QbCreate.cpp
, when you are finished with the connection. The current implementation for dbm files creates a directory using the passed name of the database.
To store features, the class QbDatabaseClass defines the abstract interface to a database. The virtual abstract member functions Open, Close, Insert, Update, Retrieve, Delete, Commit, and CreateIterator need to be defined by the specific implementation, such as DB2, Oracle, or dbm. Open and Close open and close a namespace for subsequent operations. If the namespace does not exist Open creates it. Open also takes an optional second argument that specifies the mode, either "w" for write, or "r" for read. The default is to open in the mode supported by the connection to the database. However, a call to Open in "w" mode with a "r" connection will fail.
To remove the namespace use the CloseAndRemove member function. The Insert member function inserts the key/value pair into the database and fails if the key already exists. To update an existing record, use the Update function. Update fails if the key does not exist. Given a key, Retrieve returns the value and Delete deletes the record. Because the database object often keeps state, copying of QbDatabaseClass is not allowed. If multiple objects are needed, the program is free to create them. CreateIterator is an abstract virtual function that creates an instance of a database iterator.
To define the interface to lists, use QbDbIteratorClass. This class has only three virtual functions: More, Next, and Reset (similar to the OQS iterator functions). More returns true if there is more data. Next returns the next record. Reset resets the iterator so that a future call to Next returns the first record.
To create an instance of QbDbIteratorClass, use the QbDatabaseClass member function CreateIterator. This assures the iterator is consistent with the database. The state of an iterator is undefined if an Insert, Delete, or Update is done to the database after the iterator was created. Once done using the iterator, do not forget to delete it (in order to avoid memory leaks).
To return the results of queries and to specify restrictions list of keys, use QbKeyDatabaseClass. A restriction list is a list of keys used to restrict a query. A common example is in a query such as "Find images by artist Picasso with this shade of red." A text query on "Picasso" returns a set of keys of images. These keys are then passed to the query function as a restriction list, together with the content-based query specification for "red," to obtain the final, ordered query results.
QbKeyDatabaseClass is a database of keys with distance values. Iterations on this database are required to return items in increasing distance order and to use key order in the event of a tie. QbKeyDatabaseClass is derived form QbDatabaseClass and includes several additional member functions.
IsRanked and SetRanked allow the user to query and set the ranked state of a database. Even though the database is always sorted using distance, this sort may not be valid. For an example, see the FilterResult function in the QbFeatureClass. GetDistance and SetDistance return and set the distance of a value datum.
GetNumberOfKeys returns the number of keys (records) in this database. The return results of a query are always ranked. When a QbKeyDatabaseClass is used to define a restriction list, use the same distance for all elements, or call SetDistance with no distance argument (because it defaults to use a distance of -1.0). The function RetrieveMax is a fast path to retrieve the element with the largest distance in the list. An efficient implementation of this function enhances query engine performance.
Finally, to pass restriction lists to a query, the member functions ToQueryString must be used. This process can be reversed using the function FromQueryString. ToQueryString creates a blank terminated list of key distance pairs, and FromQueryString reinserts these into a QbKeyDatabaseClass object.
QbFeatureClass is used to represent a feature. The member functions ComputeFeatures, Distance, ExecutionCostForDistance, FilterResult, and ExecutationCostForFilter are required virtual functions. ComputeFeature takes two arguments, a pointer to generic data and a query specification. Distance returns the distance between this instance of a feature class and another instance of the feature class. The FilterResult function arguments are a connected database, an optional key sublist of this database, the number of results requested by the query, the name of the catalog, and the query parameters. FilterResults can return a ranked or an unranked list. If the list is not ranked, the returned distances do not reflect final query ordering and the caller should use the Distance function to determine the final ordering. The functions GenericDataClassname and ParameterClassname return the name of the QbGenericDataClass and QbParameterClass class needed by this feature.
GetDefaultParameters returns a pointer to the default parameters for this feature class. This default parameter data is normally implemented as class static member data. The return type is const so that the caller cannot delete the result. Any implementation where the caller does not delete the results is allowed. To change the default parameters, make a copy of the default parameters using the assignment operator before changing the values.
The member function UpdateGlobalFeatureInfo allows the implementor of a feature to keep various statistics such as sum and sum of squares, which are needed at distance computation time. This allows the implementation Mahalanobis distance, if required. The base class implementation of this implements a simple counter to count the number of records in a database. You can use the parameter information to determine when to use global information. This is done using the class function ParameterUpdateFromGlobalInfo. Currently, only the Texture feature uses a variance weighted distance. In this case, the sum and sum of squares are stored as the global information for the feature. At query time, a parameter value of Vxx, where xx is an optional numerical weight, and V stands for variance, implements an inverse variance weighting. That is, a given feature is weighted by a coefficient given as 1/Vxx for all data in the collection. For example, V5 means (5/variance) weighting. At query time, the global information is read from the catalog and used to update the weights that will be used in the distance computation. Note that the query engine has no knowledge of the type of weighting or how the distance will be computed. This is left entirely up to the feature designer.
Features need to be stored in a database. This is accomplished using the member functions ToByteString and FromByteString. These functions convert the contents of the class into a byte string, and set the contents of the class from a byte string. The argument of ToByteString or FromByteString is a reference to the QbDatumClass.