sql >> Databáze >  >> RDS >> Oracle

Porovnejte obrázek BLOB s obrázky uloženými jako ORDImage pomocí SQL/MM Still Image

Konečně jsem se vrátil k problému a uvedl jej do provozu.

Problém byl prostě v tom, že jsem měl nějaké null hodnoty v ORDImage pole...

Při pokusu o uložení StillImage jsem našel svou chybu objekt přímo do mých FOTOGRAFIÍ tabulka :

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;

a poté implementaci následujícího minimálního příkladu :

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

Při omezení phot_id to fungovalo dobře na 10, a to i nahrazením p.phot_source2 s si_mkstillimage1(p.phot_source.source.localdata) (což způsobilo problém). Ale při odstraňování phot_id se to nezdařilo omezení. Tak jsem konečně pochopil, že mám nějakou nulu hodnoty v phot_source sloupec (ORDImage ), které mohou způsobit problém.

A skutečně volání SI_StillImage() konstruktor s null parametr vede k následující chybové zprávě:

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

Odebral jsem všechny null hodnoty z phot_source sloupec a vše nyní funguje dobře :)

Postup dále:

Nevýhodou je, že porovnání se všemi obrázky uloženými v tabulce trvá velmi dlouho (1155 sekund (asi 20 minut) za 5 000 fotky). Zkusil jsem tedy ukládat funkce obrázků přímo do tabulky:

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

A pak proveďte srovnání takto:

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

Ale zobrazuje následující chybu, protože se zdá, že není možné porovnat vlastnosti obrázku přímo pomocí = operátor :

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

Myslel jsem, že řešením by bylo uložit prvky obrázku jako číselné hodnoty, ale přečetl jsem celý dokumentaci a nenašel jsem žádný způsob, jak získat jakoukoli odpovídající číselnou hodnotu z obrazového prvku.

Naštěstí SI_score funkce jsou poskytovány pro každou vlastnost obrázku, takže k porovnání obrázků můžeme použít následující:

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

Zkrátil jsem čas z 1155 sekund (asi 20 minut)226 sekund (méně než 3 minuty) za 5 000 obrázky.

Vím, je to stále velmi pomalé, ale nemohu najít jiný způsob, jak zlepšit výkon..., pokud má někdo nápad, neváhejte se podělit.



  1. Výukový program pro samostatné připojení č. 10 na sqlzoo

  2. Příkaz SQL pro zápis tabulky?

  3. Databázová služba PostgreSQL

  4. Vytvořte funkci s hodnotou tabulky na serveru SQL Server