Verwaltung und Programmierung


Abfragen anhand des Abbildinhalts ausführen

Nach dem Katalogisieren von Abbildern können Sie ein oder mehrere Abbilder nach Inhalt abfragen. Wenn Sie ein Abbild nach Inhalt abfragen, identifizieren Sie die Eingabe für die Abfrage und eine Zielgruppe von katalogisierten Abbildern. Sie können die Eingabe in einer Abfragezeichenfolge (siehe Abfragezeichenfolge angeben) oder in einem Abfrageobjekt (siehe Abfrageobjekt verwenden) angeben.

Wenn Sie eine Abfragezeichenfolge verwenden, können Sie die Abfrage von der DB2-Befehlszeile aus oder innerhalb eines Programms übergeben. Wenn Sie ein Abfrageobjekt verwenden, hängt es vom Verweis auf das Abfrageobjekt ab, ob Sie die Abfrage von der DB2-Befehlszeile aus oder innerhalb eines Programms übergeben können. Wenn Sie ein Abfrageobjekt benennen und sichern, können Sie anschließend in einer UDF, die eine benannte Abfrage akzeptiert (die UDF QbScoreFromName oder QbScoreTBFromName), mit Hilfe des Namens auf das Abfrageobjekt verweisen. Sie können die UDF von der DB2-Befehlszeile aus oder innerhalb eines Programms aufrufen. Wenn Sie mit Hilfe der Kennung auf das Abfrageobjekt verweisen, können Sie die Abfrage nur innerhalb eines Programms übergeben.

Der Image Extender vergleicht die Merkmalwerte, die in der Abfrage angegeben sind, mit denen der Zielabbilder und berechnet ein Ähnlichkeitsergebnis für jedes Abbild. Dieses Ergebnis zeigt, wie sehr der Merkmalwerte des Zielabbilds den Merkmalwerten ähneln, die in der Abfrage angegeben sind.

Sie können Abbilder abrufen, deren Merkmalwerte denen der Abfrage am ähnlichsten sind. Sie können außerdem ein einzelnes katalogisiertes Abbild abfragen und dessen Ähnlichkeitsergebnis abrufen, oder die Ähnlichkeitsergebnisse für alle katalogisierten Abbilder in einer Tabellenspalte abrufen.

Abbilder abfragen

Der Image Extender stellt drei APIs zur Verfügung, um die katalogisierten Abbilder in einer Tabellenspalte abzurufen. Die APIs unterscheiden sich nur insofern, daß sie eine Abfragezeichenfolge oder ein Abfrageobjekt als Eingabe benötigen:


API Eingabe
QbQueryStringSearch Abfragezeichenfolge
QbQuerySearch Kennung für Abfrageobjekt
QbQueryNameSearch Name des Abfrageobjekts

In jeder der drei APIs können Sie außerdem

Sie können außerdem auf einen Bereich von Ausgabestrukturen zeigen, der die Ergebnisse der Suche enthalten soll. Daraufhin gibt der Image Extender in diesen Strukturen die Kennungen der Zielabbilder zurück, deren Merkmalwerte denen der Abfrage am ähnlichsten sind. Er gibt außerdem ein Ähnlichkeitsergebnis für jedes Abbild zurück, das angibt, wie sehr der Merkmalwert des Abbilds dem der Abfrage ähnelt. Die Struktur ist in der Kopfdatei für QBIC, dmbqbapi.h, wie folgt definiert:

typedef struct{
          char       imageHandle[MMDB_BASE_HANDLE_LEN+1];
          SQLDOUBLE  SCORE
} QbResult;

Sie müssen einen Bereich zuordnen, der groß genug ist, um die maximale angegebene Anzahl von Ergebnissen zu speichern, und Sie müssen in der API auf den Bereich zeigen. Sie müssen außerdem auf einen Zähler zeigen. Der Image Extender setzt den Wert des Zählers auf die Anzahl der Ergebnisse, die er zurückgibt.

Im folgenden Beispiel wird die API QbQueryStringSearch verwendet, um die katalogisierten Abbilder in einer Tabellenspalte anhand des Inhalts abzufragen. Beachten Sie, daß der Zeiger auf den Abfragebereich auf den Wert Null gesetzt ist.

QbResult       returns[MaxQueryReturns];
SQLINTEGER     maxResults=qbiMaxQueryReturns;
SQLINTEGER     count;
QbQueryHandle  qHandle;
QbResult       results[qbiMaxQueryReturns];

rc=QbQueryStringSearch(
          "QbColorFeatureClass color=<255, 0, 0>" /*query string */
          "employee",                       /* user table */
          "picture",                        /* image column */
          maxResults,                       /* maximum number of results */
          0,                                /* query scope pointer * /
          qbiArray,                         /* store results in an array */
          &count,                           /* count of returned images */
          results);                         /* array of returned results */

Es folgt eine Anforderung unter Verwendung der API QbQuerySearch. Beachten Sie, daß die Kennung für das Abfrageobjekt als Eingabe angegeben ist.

QbResult       returns[MaxQueryReturns];
SQLINTEGER     maxResults=qbiMaxQueryReturns;
SQLINTEGER     count;
QbQueryHandle  qHandle;
QbResult       results[qbiMaxQueryReturns];

rc=QbQuerySearch(
                 qHandle,                       / query object handle */
                "employee",                     /* user table */
                "picture",                      /* image column */
                maxResults,                     /* maximum number of results */
                0,                              /* query scope pointer * /
                qbiArray,                       /* store results in an array */
                &count,                         /* count of returned images */
                results);                       /* array of returned results */

Es folgt eine Anforderung unter Verwendung der API QbQueryNameSearch. Beachten Sie, daß der Name (und nicht die Kennung) für das Abfrageobjekt als Eingabe angegeben ist.

QbQueryHandle  qHandle;
char           qName[18];
char           qDesc[250];
char           results[qbiMaxQueryReturns];
SQLINTEGER     maxResults=qbiMaxQueryReturns;

/* Name the query object*/

strcpy(qName,"fshavgcol");
strcpy(qDesc,"average color query, created 10/15/96");

rc=QbQueryNameCreate(
                qHandle,                        /* query object handle */
                qName,                          /* query object name */
                qDesc);                         /* query object description */

/* Issue the query */

rc=QbQueryNameSearch(
                qName,                          /* query object name */
                "employee",                     /* user table */
                "picture",                      /* image column */
                maxResults,                     /* maximum number of results */
                0,                              /* query scope pointer * /
                qbiArray,                       /* store results in an array */
                &count,                         /* count of returned images */
                results);                       /* array of returned results */

Ähnlichkeitsergebnisse für Abbilder abrufen

Der Image Extender stellt vier UDFs zur Verfügung, die Sie in einer SQL-Anweisung verwenden können, um

das Ähnlichkeitsergebnis eines katalogisierten Abbilds in einer Tabellenspalte abzurufen. Das Ähnlichkeitsergebnis ist ein Gleitkommawert mit doppelter Genauigkeit im Bereich von 0,0 bis gegen Unendlichkeit. Je niedriger das Ähnlichkeitsergebnis, desto mehr stimmen die Merkmalwerte des Abbilds mit den Merkmalwerten überein, die in der Abfrage angegeben sind. Ein Ähnlichkeitsergebnis von 0,0 bedeutet, daß das Abbild exakt übereinstimmt.

Zu den UDFs gehören:

Verwenden Sie die UDF QbScoreFromStr oder QbScoreFromName, um das Ähnlichkeitsergebnis eines einzelnen katalogisierten Abbilds abzurufen. Verwenden Sie die UDF QbScoreTBFromStr oder QbScoreTBFromName, um das Ähnlichkeitsergebnis von mehreren katalogisierten Abbildern in einer Tabellenspalte abzurufen.

Ähnlichkeitsergebnis für ein einzelnes Abbild abrufen

Verwenden Sie die UDF QbScoreFromStr oder QbScoreFromName, um das Ähnlichkeitsergebnis eines einzelnen katalogisierten Abbilds in einer Tabellenspalte abzurufen. Geben Sie eine Abfragezeichenfolge als Eingabe für die UDF QbScoreFromStr an. Geben Sie den Namen eines Abfrageobjekts als Eingabe für die UDF QbScoreFromName an. Geben Sie bei beiden UDFs auch den Namen der Tabellenspalte an, die das Zielabbild enthält.

In der folgenden Abfrage wird die UDF QbScoreFromStr verwendet, um die katalogisierten Abbilder in einer Tabellenspalte zu suchen, deren Ähnlichkeitsergebnis für die Durchschnittsfarbe sehr nah an Rot liegt.

SELECT name, description
FROM fabric
WHERE (QbScoreFromStr(
            'QbColorFeatureClass color=<255, 0, 0>',    /* query string *
                  swatch_img))>0.9                      /* table column */

Im folgenden C-Programmierungsbeispiel wird die UDF QbScoreFromName, verwendet, um eine ähnliche Anforderung zu stellen. Beachten Sie, daß als Eingabeparameter der Name eines Abfrageobjekts (statt einer Abfragezeichenfolge) angegeben wird:

EXEC SQL SELECT name, description
 INTO :hvName, :hvDesc
 FROM fabric
 WHERE (QbScoreFromName(
            'fshavgcol',                                /* query object name *
             swatch_img))<0.1;                         /* table column */

Sie können auch QbScore verwenden, sie ist aber veraltet: DB2 Extender Version 1 bot eine UDF mit dem Namen QbScore, mit der das Ähnlichkeitsergebnis eines Abbilds abgerufen wurde. Die Eingabeparameter für die UDF QbScore und deren Ergebnisse stimmen mit denen der UDF QbScoreFromName überein. Die UDF QbScore wird von DB2 Extender Version 5 akzeptiert, allerdings wird QbScoreFromName bevorzugt.

Ähnlichkeitsergebnis für mehrere Abbilder abrufen

Verwenden Sie die UDF QbScoreTBFromStr oder QbScoreTBFromName, um das Ähnlichkeitsergebnis von mehreren katalogisierten Abbildern in einer Tabellenspalte abzurufen. Beide UDFs geben eine zweispaltige Tabelle mit Abbildkennungen und Ähnlichkeitsergebnissen zurück; die Zeilen in der Tabelle sind absteigend nach Ähnlichkeitsergebnis sortiert. Der Name der Kennungsspalte in der Ergebnistabelle ist IMAGE_ID, der Name der Ähnlichkeitsergebnisspalte ist SCORE.

Geben Sie eine Abfragezeichenfolge als Eingabe für die UDF an. Geben Sie den Namen eines Abfrageobjekts als Eingabe für die UDF QbScoreTBFromName an. Geben Sie bei beiden UDFs auch den Namen der Tabelle und der Spalte an, die die Zielabbilder enthält. Sie können außerdem die maximale Anzahl an Zeilen angeben, die in der Ergebnistabelle zurückgegeben werden sollen. Wenn Sie keine maximale Anzahl an Ergebniszeilen angeben, gibt die UDF für jedes katalogisierte Abbild in der Zieltabellenspalte eine Zeile zurück.

In der folgenden Abfrage wird die UDF QbScoreTBFromStr verwendet, um die zehn katalogisierten Abbilder in einer Tabellenspalte zu suchen, deren Textur der eines Abbilds in einer Server-Datei am ähnlichsten ist.

SELECT name, description
FROM fabric
WHERE CAST (swatch_img as varchar(250))IN 
 SELECT CAST (image_id as varchar(25)) FROM TABLE
 (QbScoreTBFromStr
 (QbTextureFeatureClass file=<server,"patterns/ptrn07.gif">'   /*query string */
                     
      'fabric',                                               /* table */
      'swatch_img',                                           /* table column */
      10))                                       /* maximum number of results */
AS T1));

Im folgenden C-Programmierungsbeispiel wird die UDF QbScoreTBFromName verwendet. Beachten Sie, daß als Eingabeparameter der Name eines Abfrageobjekts (statt einer Abfragezeichenfolge) angegeben wird. Beachten Sie außerdem, daß keine Eingabe für die maximale Ergebnisanzahl angegeben ist, so daß die UDF für jedes katalogisierte Abbild in der Zieltabellenspalte ein Ergebnis zurückgibt:

 SELECT name, description
 INTO :hvName, :hvDesc
 FROM fabric
 WHERE CAST (swatch_img as varchar(250)) IN 
(SELECT CAST (image_id as varchar(250)) FROM TABLE
(QbScoreTBFromName
            'fstxtr',                                   /* query object name */
            'fabric',                                   /* table */
            'swatch_img'))                              /* table column */ 
AS T1));           

Programm für QBIC-Abfragebeispiel

Die folgende Abbildung zeigt Teile eines in C geschriebenen Programms, mit eine QBIC-Abfrage erstellt und ausgeführt wird. Der Code in der Abbildung fragt Abbilder nach Durchschnittsfarbe ab. Er fordert den Benutzer zur Eingabe des Namens einer Farbe oder Abbilddatei auf. Der Benutzer kann auch ein Abbild, das von einer Abfrage zurückgegeben wird, als ein Beispielabbild für eine nachfolgende Abfrage verwenden. Das Programm verwendet danach die benannte Farbe oder die Farbe des Abbilds als Durchschnittsfarbe, um eine Spalte mit Abbildern abzufragen.

Das vollständige Programm befindet sich in der Datei QBICDEMO.C im Unterverzeichnis SAMPLES. Das vollständige Programm kann verwendet werden, um Abbilder nach Histogrammfarbe oder positionsgebundener Farbe sowie nach Durchschnittsfarbe abzufragen. Um das vollständige Programm ausführen zu können, müssen Sie die Beispielprogramme ENABLE, POPULATE und QBCATDMO ausführen (die sich auch im Unterverzeichnis SAMPLES befinden). Weitere Informationen zu Beispielprogrammen befinden sich im Anhang B. Beispielprogramme und Multimediadateien.

Beachten Sie folgende Punkte in dem Beispielprogramm:

(1)Die Kopfdatei dmbqbapi wird eingeschlossen.

(2)Der Benutzer wird zur Eingabe von Datenbankinformationen aufgefordert.

(3)Eine Verbindung zur Datenbank wird hergestellt.

(4)Ein Abfrageobjekt wird erstellt.

(5)Ein Merkmal wird zu einem Abfrageobjekt hinzugefügt.

(6)Der Benutzer wird zur Eingabe des Eingabetyps aufgefordert (Farbname, Abbilddatei oder zuvor abgerufenes Abbild).

(7)Die Datenquelle für das Merkmal wird angegeben. Die Datenquelle ist eine explizite Angabe für die Durchschnittsfarbe.

(8)Die Abfrage wird ausgeführt. Der Image Extender durchsucht die gesamte Spalte mit Abbildern. Außerdem wird 10 als maximale Anzahl von Abbildern angegeben, die zurückgegeben werden sollen.

(9)Das nächste Abbild aus der Gruppe der zurückgegebenen Abbilder wird angezeigt. Weitere Informationen zur Anzeige von Abbildern befinden sich im Abschnitt Abbild oder Videovollbild in normaler Größe anzeigen.

(10)Das Abfrageobjekt wird gelöscht.

Das Unterverzeichnis SAMPLES enthält ein weiteres Programm, das die Erstellung und Verwendung einer QBIC-Abfrage demonstriert. Das Programm in der Datei QBICPICK.C bietet dem Benutzer die Möglichkeit, die Suchkriterien für eine QBIC-Abfrage grafisch anzugeben. Beispielsweise bietet das Programm ein Farbauswahlmenü, mit dem die Durchschnittsfarbe ausgewählt werden kann. Das Programm setzt die Auswahl in eine Abfragezeichenfolge um.

Abbildung 21. Programm für QBIC-Abfragebeispiel

#include <sql.h>
#include <sqlcli.h>
#include <sqlcli1.h>
#include <dmbqbqpi.h> (1)
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <color.h>
#include <ctype.h>

#define   MaxQueryReturns        10

#define   MaxDatabaseNameLength  SQL_SH_IDENT
#define   MaxUserIdLength        SQL_SH_IDENT
#define   MaxPasswordLength      SQL_SH_IDENT
#define   MaxTableNameLength     SQL_LG_IDENT
#define   MaxColumnNameLength    SQL_LG_IDENT

static  char       databaseName[MaxDatabaseNameLength+1];
static  char       userid[MaxUserIdLength+1];
static  char       password[MaxPasswordLength+1];

static  char       tableName[MaxTableNameLength+1];
static  char       columnName[MaxColumnNameLength+1];

static  char       line[4000];

static  QbResult   results[MaxQueryReturns];
static  long       currentImage   = -1;
static  long       imageCount  = 0;

static  char*      tableAndColumn;

static  QbQueryHandle	averageHandle = 0;
static  QbQueryHandle	histogramHandle = 0;
static  QbQueryHandle	drawHandle = 0;
static  QbQueryHandle	lastHandle = 0;

static  SQLHENV    henv;
static  SQLHDBC    hdbc;
static  SQLHSTMT   hstmt;
static  SQLRETURN  rc;

static  char*    listQueries =
	"SELECT NAME,DESCRIPTION FROM MMDBSYS.QBICQUERIES ORDER BY NAME";

static  char*    menu[] = {

/*
 12345678901234567890123456789012345678901234567890123456789012345678901234567890 */
"",
"+-----------------------------------------------------------------------------+",
"| AVERAGE COLOR colorname                                                     |",
"| AVERAGE FILE filename format                                                |",
"| AVERAGE LAST                                                                |",
"| Press Enter to display the next image in the series                         |",
"+-----------------------------------------------------------------------------+",
"",
         0
};

static  char*       help[] = {
"",
"AVERAGE     Execute an average color query",
"  COLOR       Specifies the color to query for",
"  FILE        Specifies the file to compute the average color from",
"  LAST        Specifies the last displayed image be used to compute the color",
"  NEXT        Displays the next image from the current query or nothing if",
"                all of the image have been displayed."
"",
">>pause<<",
         0
};
/******************************************************************************/
/* doNext()                                                                   */
/******************************************************************************/
static void doNext(void)
{
	int ret;
   if (currentImage < imageCount)
      currentImage++;
   if (currentImage < imageCount)
      ret = DBiBrowse("/usr/local/bin/xv %s", MMDB_PLAY_HANDLE,
            results[currentImage].imageHandle, MMDB_PLAY_NO_WAIT); (9)
}


/******************************************************************************/
/* doAverage()                                                                */
/******************************************************************************/
static void doAverage(void)
{
   QbQueryHandle qohandle = 0; QbImageSource is; char* type;
   char* arg1; char* arg2;

   type = nextWord(0);
   if (abbrev(type, "color", 1)) {
      is.type = qbiSource_AverageColor;
      arg1 = nextWord(0);
      if (arg1 == 0) {
         printf("AVERAGE COLOR command requires a colorname argument.\n");
      return;
      }
      if (getColor(arg1, &is.averageColor) == 0) {
         printf("The colorname entered was not recognized.\n");
      return;
      }
   }
   else if (abbrev(type, "file", 1)) {
      is.type = qbiSource_ClientFile;
      arg1 = nextWord(0);
      if (arg1 == 0) {
         printf("AVERAGE FILE command requires a filename argument.\n");
      return;
      }
      arg2 = nextWord(0);
      if (arg2 == 0) {
         printf("AVERAGE FILE command requires a file format argument.\n");
      return;
      }
      strcpy(is.clientFile.fileName, arg1);
      strcpy(is.clientFile.format, arg2);
   }
   else if (abbrev(type, "last", 1)) {
      is.type = qbiSource_ImageHandle;
      if (0 <= currentImage &&; currentImage < imageCount)
         strcpy(is.imageHandle, results[currentImage]imageHandle);
      else {
         printf("No last image for AVERAGE LAST command\n");
      return;
      }
   }

   else {
      printf("AVERAGE command only supports COLOR, FILE, and LAST types.\n");
      return;
   }
		
   _QbQuerySetFeatureData(averageHandle, "QbColorFeatureClass", &is); (7)
   _QbQuerySearch(averageHandle, tableAndColumn, "IMAGE",
         MaxQueryReturns, 0, 0, &imageCount, results); (8)
   lastHandle = averageHandle;
   	
   currentImage = -1;
}
/******************************************************************************/
/* commandLoop()                                                              */
/******************************************************************************/
void commandLoop(void)
{
   int	done = 0;

   while (!done) { (6)
      displayText(menu);
      printf("%d", currentImage + 1);
      if (0 <= currentImage &&; currentImage < imageCount)
            printf("  %8.6f", results[currentImage].score);
      printf("> ");
   gets(line);
      done = processCommand(line);
   }
}


/******************************************************************************/
/* main()                                                                     */
/******************************************************************************/
void main(void)
{
   char*		inst;
   int		i;

   printf("\n\n");
   printf("Please enter: database_name [user_id] [password] "\n"); (2)
   gets(line);
   if (copyWord(line, databaseName, sizeof(databaseName)) == 0)
      exit(0);
   copyWord(0, userid, sizeof(userid));
   copyWord(0, password, sizeof(password));
   printf("\n");
		
   if (SQLAllocEnv(&henv) != SQL_SUCCESS)
      sqlError(SQL_NULL_HSTMT);
   if (SQLAllocConnect(henv, &hdbc) != SQL_SUCCESS)
      sqlError(SQL_NULL_HSTMT);
   if (SQLConnect(hdbc, (3)
                  (SQLCHAR*)databaseName,
                  SQL_NTS,
                  (SQLCHAR*)userid,
                  SQL_NTS,
                  (SQLCHAR*)password,
                  SQL_NTS) != SQL_SUCCESS)
      sqlError(SQL_NULL_HSTMT);

   printf("Initializing . . .\n");


      inst = getenv("DB2INSTANCE");
   if (inst != 0 &&; strcmp(inst, "keeseyt") == 0)
      tableAndColumn = "KEESEY.TEST";
   else
      tableAndColumn = "QBICDEMO.TEST";

   _QbQueryCreate(&averageHandle); (4)
   _QbQueryAddFeature(averageHandle, "QbColorFeatureClass");
   _QbQueryCreate(&histogramHandle);
   _QbQueryAddFeature(histogramHandle, "QbColorHistogramFeatureClass");
   _QbQueryCreate(&drawHandle);
   _QbQueryAddFeature(drawHandle, "QbDrawFeatureClass"); (5)

   commandLoop();
	
   _QbQueryDelete(drawHandle);
   _QbQueryDelete(histogramHandle); (10)
   _QbQueryDelete(averageHandle);

   if (SQLDisconnect(hdbc) != SQL_SUCCESS)
      sqlError(SQL_NULL_HSTMT);
   if (SQLFreeConnect(hdbc) != SQL_SUCCESS)
      sqlError(SQL_NULL_HSTMT);
   if (SQLFreeEnv(henv) != SQL_SUCCESS)
      sqlError(SQL_NULL_HSTMT);
}


[ Seitenanfang | Vorherige Seite | Nächste Seite | Inhaltsverzeichnis | Index ]

Search the DB2 Extender Books