Сравните BLOB-изображение с изображениями, хранящимися в ORDImage с использованием SQL / MM Still Image - PullRequest
2 голосов
/ 27 марта 2012

Я использую Oracle 11g r2 .

У меня есть таблица, в которой изображения хранятся как ORDImage :

PHOTOS (phot_id integer
        , phot_filename varchar2(256)
        , phot_source ordsys.ordimage)

И еще один временныйтаблица, в которой хранится изображение, загруженное пользователем как BLOB .

INSERT_TEMP (itemp_id integer, itemp_source blob)

Я хочу переместить изображение BLOB в таблицу PHOTOS, только если оно еще не существует, путем сравнения двух изображений,Мне нужно использовать SQL / MM Still Image , поскольку методы ORDImageSignature устарели в Oracle 11g.

Вот код:

 declare
    [...]
 begin
    [...]
    -- get the blob from the temporary table (in_id passed as parameter)
    select itemp_source into l_img_blob from insert_temp where itemp_id = in_id;
    -- build the stillimage object from the blob
    l_img_obj := new si_stillimage(l_img_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 already exists
    select count(*) into l_exist from photos p where SI_ScoreByFtrList(l_featurelist, SI_MkStillImage1(p.phot_source.source.localdata)) = 0;
    if (l_exist > 0) then
       out_message := app_util.get_translated_message('ERR_SIMILAR_PHOTO_ALREADY_EXISTS');
    else
       /* here the blob is inserted into the PHOTOS table as ORDImage successfully */
       out_message := app_util.get_translated_message('SUC_PHOTO_INSERTED');
    end if;
 end;

Изображение вставляется какORDImage успешно, если я опускаю сравнение, иначе возникает исключение ( sqlcode: 1, sqlerrm: пользовательское исключение ), используя DBMS_UTILITY.FORMAT_ERROR_BACKTRACE, оно сообщает мне следующее:

ORA-06512: à «ORDSYS.SI_STILLIMAGE», строчка 27
ORA-06512: à «ORDSYS.SI_MKSTILLIMAGE1», строчка 6
ORA-06512: à «SURV.APP_CORE», строка 212

строка 212 - это строка, которая проверяет, существует ли подобное изображение:

 select count(*) into l_exist
 from photos p 
 where SI_ScoreByFtrList(l_featurelist, SI_MkStillImage1(p.phot_source.source.localdata)) = 0;

Кажется, проблема в том, что он не принимает p.phot_source.source.localdata в качестве параметра.У вас есть идеи о том, как я могу решить эту проблему?

Я также пытался:

 select count(*) into l_exist 
 from photos p
 where l_featurelist.si_score(new si_stillimage1(p.phot_source.source.localdata)) = 0;

Спасибо!

Ответы [ 2 ]

2 голосов
/ 24 октября 2013

Даже это более чем годичный вопрос, я просто нашел его, когда искал собственные ответы на другую проблему.Но просто интересно, почему вам нужно сравнивать изображения по атрибутам, это медленно.

Лучшее решение - добавить поле хеш-varchar для изображений, а затем сравнить эти хэши.Если такой же хэш найден, то изображение уже существует.Это может быть пример хеша md5.Конечно, вам нужно выполнить эту процедуру один раз, чтобы уже создать базу данных для существующих изображений.

Используйте все виды атрибутов изображения для его хеширования, но не имя файла: размер, ширина, высота, раскраска всехkind.

И когда пользователь пытается добавить новое изображение, он берет эти атрибуты изображения, соединяет их вместе, а затем сравнивает этот хэш с другими хэшами в базе данных, и если это совпадение, изображение уже существует и игнорирует вставку..

Супербыстрая версия для сравнения изображений вместо метода "unpacking image".

2 голосов
/ 27 июля 2012

Я наконец вернулся к проблеме и заставил ее работать.

Проблема заключалась просто в том, что у меня было несколько значений null в поле ORDImage ...


Я обнаружил свою ошибку, пытаясь сохранить объект 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.Поэтому я наконец понял, что у меня есть некоторые значения null в столбце 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 изображений.

Я знаю, это все еще очень медленно, но я не могу найти другой способ улучшить выступления ..., если у кого-то есть идея, не стесняйтесь поделиться.

...