Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Vergleichen Sie ein BLOB-Bild mit Bildern, die als ORDImage gespeichert sind, indem Sie SQL/MM Standbild verwenden

Endlich bin ich auf das Problem zurückgekommen und habe es zum Laufen gebracht.

Das Problem war einfach, dass ich einige null hatte Werte im ORDImage Feld...

Ich habe meinen Fehler gefunden, als ich versucht habe, das Standbild zu speichern Objekt direkt in meine FOTOS Tabelle :

alter table PHOTOS add phot_source2 SI_Stillimage;
update photos p set p.phot_source2 = si_stillimage(p.phot_source.source.localData) where p.phot_id < 10;

und dann das folgende Minimalbeispiel implementieren :

DECLARE
    l_img_obj   si_stillimage;
    l_avgcolor  si_averagecolor;
    l_colorhist si_colorhistogram;
    l_poscolor  si_positionalcolor;
    l_texture   si_texture;
    l_featurelist   si_featurelist;
    l_blob      BLOB;
    l_exist     INTEGER;
BEGIN
    -- get the blob from the ordimage
    SELECT p.phot_source.source.localdata
    INTO l_blob FROM photos p
    WHERE phot_id = 2;
    -- build the stillimage object from the blob
    l_img_obj := NEW si_stillimage(l_blob);
    -- get image features and build the featureList object
    l_avgcolor    := NEW si_averagecolor(l_img_obj);
    l_colorhist   := NEW si_colorhistogram(l_img_obj);
    l_poscolor    := NEW si_positionalcolor(l_img_obj);
    l_texture     := NEW si_texture(l_img_obj);
    l_featurelist := NEW si_featurelist(l_avgcolor, 1, l_colorhist, 1, l_poscolor, 1, l_texture, 1);
    -- check if a similar image is found in the table
    SELECT 1
    INTO l_exist
    FROM photos p
    WHERE si_scorebyftrlist(l_featurelist, p.phot_source2) = 0
    AND phot_id < 10
    AND rownum = 1;
    -- show message if at least one similar photo has been found
    IF (l_exist = 1) THEN       
        dbms_output.put_line('A similar photo has been found');
    END IF;
END;
/ 

Es funktionierte gut, wenn die phot_id eingeschränkt wurde bis 10, sogar durch Ersetzen von p.phot_source2 mit si_mkstillimage1(p.phot_source.source.localdata) (was das Problem verursacht hat). Aber es schlug fehl, als die phot_id entfernt wurde Beschränkung. Also verstand ich endlich, dass ich etwas Null hatte Werte in phot_source Spalte (ORDImage ), die das Problem verursachen können.

Und tatsächlich Aufruf von SI_StillImage() Konstruktor mit einem null Parameter führt zu folgender Fehlermeldung :

ORA-06510: PL/SQL: unhandled user-defined exception
ORA-06512: at "ORDSYS.SI_STILLIMAGE", line 27
ORA-06512: at "ORDSYS.SI_MKSTILLIMAGE1", line 6
ORA-06512: at line 24

Ich habe alle null entfernt Werte aus phot_source Spalte und alles funktioniert jetzt gut :)

Um weiter zu gehen:

Der Nachteil dabei ist, dass der Vergleich mit allen in der Tabelle gespeicherten Bildern sehr lange dauert (1155 Sekunden (ca. 20 Minuten)). für 5000 Fotos). Also habe ich versucht, Bildmerkmale direkt in der Tabelle zu speichern :

alter table photos add (
    phot_averagecolor si_averagecolor,
    phot_colorhistogram si_colorhistogram,
    phot_positionalcolor si_positionalcolor,
    phot_texture si_texture
)

update photos p set
    p.phot_averagecolor = si_averagecolor(si_stillimage(p.phot_source.source.localData)),
    p.phot_colorhistogram = si_colorhistogram(si_stillimage(p.phot_source.source.localData)),
    p.phot_positionalcolor = si_positionalcolor(si_stillimage(p.phot_source.source.localData)),
    p.phot_texture = si_texture(si_stillimage(p.phot_source.source.localData))
where p.phot_id < 10

Und dann machen Sie den Vergleich so:

-- get the blob from the ordimage
SELECT p.phot_source.source.localdata
INTO l_blob FROM photos p
WHERE phot_id = 2;
-- build the stillimage object from the blob
l_img_obj := NEW si_stillimage(l_blob);
-- get image features and build the featureList object
l_avgcolor    := si_averagecolor(l_img_obj);
l_colorhist   := si_colorhistogram(l_img_obj);
l_poscolor    := si_positionalcolor(l_img_obj);
l_texture     := si_texture(l_img_obj);
l_featurelist := NEW si_featurelist(l_avgcolor, 1, l_colorhist, 1, l_poscolor, 1, l_texture, 1);
-- check if a similar image is found in the table
SELECT 1
INTO l_exist
FROM photos p
WHERE p.phot_averagecolor = l_avgcolor
AND p.phot_colorhistogram = l_colorhist
AND p.phot_positionalcolor = l_poscolor
AND p.phot_texture = l_texture
AND p.phot_id < 10
AND rownum = 1;

Aber es gibt den folgenden Fehler, da es anscheinend nicht möglich ist, Bildmerkmale direkt mit = zu vergleichen Betreiber :

ORA-22901: cannot compare VARRAY or LOB attributes of an object type
ORA-06512: at line 24

Ich dachte, eine Lösung wäre, Bildmerkmale als numerische Werte zu speichern, aber ich habe den gesamten Dokumentation und ich habe keine Möglichkeit gefunden, einen entsprechenden numerischen Wert von einer Bildfunktion zu erhalten.

Zum Glück SI_score Funktionen werden für jedes Bildmerkmal bereitgestellt, sodass wir die folgenden Bilder verwenden können, um sie zu vergleichen:

DECLARE
    l_img_obj   si_stillimage;
    l_blob      BLOB;
    l_exist     INTEGER;
BEGIN
    -- get the blob from the ordimage
    SELECT p.phot_source.source.localdata
    INTO l_blob FROM photos p
    WHERE phot_id = 2;
    -- build the stillimage object from the blob
    l_img_obj := NEW si_stillimage(l_blob);
    -- check if a similar image is found in the table
    SELECT 1
    INTO l_exist
    FROM photos p
    WHERE p.phot_averagecolor.SI_Score(l_img_obj) = 0
    AND p.phot_colorhistogram.SI_Score(l_img_obj) = 0
    AND p.phot_positionalcolor.SI_Score(l_img_obj) = 0
    AND p.phot_texture.SI_Score(l_img_obj) = 0
    AND rownum = 1;
    -- show message
    dbms_output.put_line(l_count || ' similar photo(s) found');
END;
/

Ich habe die Zeit von 1155 Sekunden (ca. 20 Minuten) reduziert auf 226 Sekunden (weniger als 3 Minuten) für 5000 Bilder.

Ich weiß, es ist immer noch sehr langsam, aber ich kann keine andere Möglichkeit finden, die Leistung zu verbessern ..., wenn jemand eine Idee hat, zögern Sie nicht, sie zu teilen.