Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Porównaj obraz BLOB z obrazami przechowywanymi jako ORDImage przy użyciu SQL/MM Still Image

W końcu wróciłem do problemu i zacząłem działać.

Problem polegał po prostu na tym, że miałem trochę null wartości w ORDImage pole...

Znalazłem swój błąd, próbując zapisać StillImage obiekt bezpośrednio do moich ZDJĘĆ tabela :

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 następnie implementacja następującego minimalnego przykładu :

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

Działało dobrze podczas ograniczania phot_id do 10, nawet zastępując p.phot_source2 z si_mkstillimage1(p.phot_source.source.localdata) (co było przyczyną problemu). Nie udało się jednak usunąć phot_id ograniczenie. Więc w końcu zrozumiałem, że mam trochę null wartości w phot_source kolumna (ORDImage ), które mogą powodować problem.

I rzeczywiście wywołując SI_StillImage() konstruktor z null parametr prowadzi do następującego komunikatu o błędzie:

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

Usunąłem wszystkie null wartości z phot_source kolumna i wszystko działa teraz dobrze :)

Aby przejść dalej:

Wadą tego jest to, że porównanie ze wszystkimi obrazami przechowywanymi w tabeli zajmuje bardzo dużo czasu (1155 sekund (około 20 minut) za 5000 zdjęcia). Próbowałem więc przechowywać funkcje obrazów bezpośrednio w tabeli :

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 potem wykonaj porównanie w ten sposób:

-- 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 daje następujący błąd, ponieważ wydaje się, że nie można porównać funkcji obrazu bezpośrednio za pomocą = operator :

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

Myślałem, że rozwiązaniem będzie przechowywanie funkcji obrazu jako wartości liczbowych, ale przeczytałem cały dokumentacja i nie znalazłem żadnego sposobu, aby uzyskać odpowiednią wartość liczbową z funkcji obrazu.

Na szczęście SI_score funkcje są dostępne dla każdej funkcji obrazu, więc możemy użyć następujących funkcji do porównania obrazów:

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

Skróciłem czas z 1155 sekund (około 20 minut) do 226 sekund (mniej niż 3 minuty) za 5000 obrazy.

Wiem, że nadal jest bardzo powolny, ale nie mogę znaleźć innego sposobu na poprawę wydajności... jeśli ktoś ma pomysł, nie wahaj się podzielić.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Nie rozumiem, dlaczego moja grupa według upada

  2. Jak przechwycić zdarzenie „następne”, gdy przesunięcie jest zmienne dla elementów, które można wielokrotnie przetwarzać?

  3. Funkcja NVL2() w Oracle

  4. 12c Plany adaptacyjne

  5. ORA-00054:zasób zajęty i pozyskiwanie z określonym NOWAIT lub upłynął limit czasu