3

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)

2 つの画像を比較して、まだ存在しない場合にのみ、BLOB 画像を PHOTOS テーブルに移動したいと考えています。ORDImageSignature メソッドは Oracle 11g では非推奨になっているため、 SQL/MM Still Imageメソッドを使用する必要があります。

コードは次のとおりです。

 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: User-defined Exception )。

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;

ありがとうございました !

4

2 に答える 2

3

私はついに問題に戻り、それを機能させました。

問題は単純に、 ORDImageフィールドにいくつかのnull値があったことでした...


StillImageオブジェクトをPHOTOSテーブルに直接保存しようとして、エラーを見つけました。

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

を 10に制限するphot_idと、に置き換えp.phot_source2ても問題なく動作していましたsi_mkstillimage1(p.phot_source.source.localdata)(これが問題の原因でした)。phot_idしかし、制限を解除するときに失敗しました。そのため、問題を引き起こす可能性のある列 ( ORDImage ) にいくつかのnull値があることが最終的にわかりました。phot_source

実際、 nullパラメーターを指定SI_StillImage()してコンストラクターを呼び出すと、次のエラー メッセージが表示されます。

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が、すべてが正常に機能しています:)


さらに進むには:

これの欠点は、テーブルに格納されているすべての画像と比較するのに非常に長い時間がかかることです ( 5000枚の写真で1155 秒 (約 20 分) )。だから私はテーブルに画像機能を直接保存しようとしました:

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

5000枚の画像で、時間を1155 秒 (約 20 分)から226 秒 (3 分未満) に短縮しました。

まだ非常に遅いことはわかっていますが、パフォーマンスを改善する別の方法を見つけることができません....誰かアイデアがあれば、遠慮なく共有してください.

于 2012-07-27T14:20:02.707 に答える