sql >> Database teknologi >  >> RDS >> Oracle

Sammenlign et BLOB-billede med billeder gemt som ORDImage ved hjælp af SQL/MM-stillbillede

Jeg kom endelig tilbage til problemet og fik det til at virke.

Problemet var simpelthen, at jeg havde noget null værdier i ORDImage felt...

Jeg fandt min fejl ved at prøve at gemme StillImage objekt direkte ind i mine BILLEDER tabel :

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;

og derefter implementere følgende minimale eksempel :

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

Det fungerede fint, når du begrænsede phot_id til 10, selv ved at erstatte p.phot_source2 med si_mkstillimage1(p.phot_source.source.localdata) (som var årsag til problemet). Men det mislykkedes, da du fjernede phot_id begrænsning. Så jeg forstod endelig, at jeg havde noget null værdier i phot_source kolonne (ORDImage ), der kan forårsage problemet.

Og faktisk kalder SI_StillImage() konstruktør med en null parameter fører til følgende fejlmeddelelse:

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

Jeg fjernede alle null værdier fra phot_source kolonne og alt fungerer fint nu :)

For at gå videre:

Ulempen ved dette er, at det tager meget lang tid at foretage sammenligningen med alle de billeder, der er gemt i tabellen (1155 sekunder (ca. 20 min) for 5000 fotos). Så jeg har forsøgt at gemme billedfunktioner direkte i tabellen :

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

Og lav så sammenligningen sådan her :

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

Men det giver følgende fejl, da det ikke lader til at være muligt at sammenligne billedfunktioner direkte ved hjælp af = operatør:

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

Jeg troede, at en løsning ville være at gemme billedfunktioner som numeriske værdier, men jeg læste hele dokumentation og jeg har ikke fundet nogen måde at få nogen tilsvarende numerisk værdi fra en billedfunktion.

Heldigvis SI_score funktioner er tilvejebragt for hver billedfunktion, så vi kan bruge følgende til at sammenligne billederne:

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

Jeg reducerede tiden fra 1155 sekunder (ca. 20 min) til 226 sekunder (mindre end 3 min) for 5000 billeder.

Jeg ved godt, det er stadig meget langsomt, men jeg kan ikke finde en anden måde at forbedre præstationerne på..., hvis nogen har en idé, så tøv ikke med at dele.



  1. Forespørgselstidszone - db server &klientmaskine har forskellige tidszoner

  2. SUM med et pivot for at beregne den samlede score

  3. Hvordan bestemmer MySQL Cluster, hvilke dataknuder der skal søges efter en SELECT-forespørgsel?

  4. Jeg vil vise flere billeder fra databasen i jsp (jeg kortlægger servlet), så i jsp vil m vises i src af img tag