I am using Oracle 11g r2.
I have a table that stores images as ORDImage :
PHOTOS (phot_id integer
, phot_filename varchar2(256)
, phot_source ordsys.ordimage)
And another temporary table that stores an image uploaded by a user as BLOB.
INSERT_TEMP (itemp_id integer, itemp_source blob)
I want to move the BLOB image to the PHOTOS table only if does not already exists, by comparing the two images. I need to use SQL/MM Still Image methods as ORDImageSignature methods are deprecated in Oracle 11g.
Here is the code :
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;
The image is inserted as ORDImage successfully if I omit the comparison, else an exception is raised (sqlcode: 1, sqlerrm: User-defined Exception), using DBMS_UTILITY.FORMAT_ERROR_BACKTRACE it tells me the following :
ORA-06512: à “ORDSYS.SI_STILLIMAGE”, ligne 27
ORA-06512: à “ORDSYS.SI_MKSTILLIMAGE1”, ligne 6
ORA-06512: à “SURV.APP_CORE”, ligne 212
line 212 is the line that checks 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;
It seems the problem is that it does not accept p.phot_source.source.localdata as parameter. Do you have any idea on how I can solve this ?
I have also tried :
select count(*) into l_exist
from photos p
where l_featurelist.si_score(new si_stillimage1(p.phot_source.source.localdata)) = 0;
Thank you !
I finally came back to the problem, and get it to work.
The problem was simply that I had some null values in the ORDImage field…
I found my error by trying to store the StillImage object directly into my PHOTOS table :
and then implementing the following minimal example :
It was working fine when restricting the
phot_idto 10, even by replacingp.phot_source2withsi_mkstillimage1(p.phot_source.source.localdata)(wich was causing the problem). But it failed when removing thephot_idrestriction. So I finally understood that I had some null values in thephot_sourcecolumn (ORDImage) that can cause the problem.And indeed calling
SI_StillImage()constructor with a null parameter leads to the following error message :I removed all null values from the
phot_sourcecolumn and all is working fine now 🙂To go further:
The downside of this is that it takes a very long time to do the comparison with all the images stored in the table (1155 seconds (arround 20 min) for 5000 photos). So I have tried to store images features directly into the table :
And then do the comparison like this :
But it gives the following error as it seems not possible to compare image features directly using the
=operator :I thought a solution would be to store image features as numeric values, but I read the entire documentation and I have not found any way to get any corresponding numeric value from an image feature.
Luckily,
SI_scorefunctions are provided for each image feature, so we can use the following to compare the images :I reduced the time from 1155 seconds (arround 20 min) to 226 seconds (less than 3 min) for 5000 images.
I know, it is still very slow, but I can’t find another way to improve performances…, if anyone has an idea do not hesitate to share.