Oracle
 sql >> база данни >  >> RDS >> Oracle

Сравнете BLOB изображение с изображения, съхранени като ORDImage, като използвате SQL/MM неподвижно изображение

Най-накрая се върнах към проблема и го накарах да работи.

Проблемът беше просто, че имах някои null стойности в ORDIimage поле...

Открих грешката си, опитвайки се да запазя StillImage обект директно в моите СНИМКИ таблица :

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;

и след това прилагане на следния минимален пример :

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

Работеше добре при ограничаване на phot_id до 10, дори чрез замяна на p.phot_source2 с si_mkstillimage1(p.phot_source.source.localdata) (което причиняваше проблема). Но не успя при премахването на phot_id ограничение. Така най-накрая разбрах, че имам някаква нула стойности в phot_source колона (ORDImage ), което може да причини проблема.

И наистина извикване на SI_StillImage() конструктор с null параметър води до следното съобщение за грешка:

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

Премахнах всички null стойности от phot_source колона и сега всичко работи добре :)

За да отидете по-далеч:

Недостатъкът на това е, че отнема много време за сравнение с всички изображения, съхранени в таблицата (1155 секунди (около 20 минути) за 5000 снимки). Така че се опитах да съхранявам характеристики на изображения директно в таблицата:

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

И след това направете сравнението по следния начин:

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

Но дава следната грешка, тъй като изглежда не е възможно да се сравняват характеристиките на изображението директно чрез = оператор :

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

Мислех, че решение ще бъде да съхранявам характеристиките на изображението като числови стойности, но прочетох целия документация и не намерих никакъв начин да получа съответстваща числова стойност от функция на изображение.

За щастие, SI_score функции са предоставени за всяка функция на изображението, така че можем да използваме следното, за да сравним изображенията:

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

Намалих времето от 1155 секунди (около 20 минути) до 226 секунди (по-малко от 3 минути) за 5000 изображения.

Знам, че все още е много бавен, но не мога да намеря друг начин за подобряване на представянето..., ако някой има идея, не се колебайте да сподели.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle SQL:Избиране на един ред с най-новата дата между множество колони

  2. Премахване на водещи нули от varchar sql developer

  3. Как да върна ResultSet от съхранена процедура в Oracle?

  4. Как да изберете колони от таблица, които имат стойности, различни от null?

  5. Как да разархивирате файл в PL/SQL?