package eu.europeana.service.ir.image.api; import it.cnr.isti.exception.TechnicalRuntimeException; import it.cnr.isti.feature.extraction.FeatureExtractionException; import it.cnr.isti.feature.extraction.Image2Features; import it.cnr.isti.melampo.index.searching.MelampoSearcherHub; import it.cnr.isti.melampo.tools.thumbnail.locator.ImageLocator; import it.cnr.isti.melampo.vir.exceptions.BoFException; import it.cnr.isti.melampo.vir.exceptions.VIRException; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import eu.europeana.service.ir.image.IRConfiguration; import eu.europeana.service.ir.image.IRConfigurationImpl; import eu.europeana.service.ir.image.domain.QueryResults; import eu.europeana.service.ir.image.exceptions.ImageSearchingException; import eu.europeana.service.ir.image.web.model.json.ImageSearchResultItem; import eu.europeana.service.ir.image.web.model.json.SearchResultItem; /** * @author Paolo Bolettieri <paolo.bolettieri@isti.cnr.it> * @author Sergiu Gordea <sergiu.gordea_at_ait.ac.at> */ public class ImageSearchingServiceImpl implements ImageSearchingService { private Logger log = Logger.getLogger(getClass()); @Autowired private IRConfiguration configuration; private String dataset = null; private MelampoSearcherHub index; private QueryResults queryResults = new QueryResults(); private static final int NUM_RESULTS = 100; private Image2Features img2ftx; private ImageLocator imageLocator; public ImageSearchingServiceImpl(IRConfiguration configuration) { this(configuration.getDefaultDataset(), configuration); } public ImageSearchingServiceImpl(String dataset, IRConfiguration configuration) { this.configuration = configuration; this.dataset = dataset; } // public ImageSearchingServiceImpl() { // this(null); // } /* * (non-Javadoc) * * @see eu.europeana.service.ir.image.api.ImageSearchingService#init() */ @Override public void init() { // ensure initialization of configuration attribute getConfiguration(); // init index searcher bean try { if (index == null) { index = new MelampoSearcherHub(); // File test = new File("."); // System.out.println(">>>>>> " + test.getAbsolutePath()); File indexFolder = getConfiguration().getIndexFolder( getDataset()); File indexConfFolder = getConfiguration().getIndexConfFolder( getDataset()); if (indexFolder.exists()) { log.trace("loading image index from following location: " + indexFolder.getAbsolutePath()); // the indices.properties and LIRE_MP7ALL properties index.openIndices(indexConfFolder); // System.out.println("test"); } else { // prepare folder indexFolder.mkdirs(); } } } catch (BoFException e) { log.warn("No image index available!", e); // e.printStackTrace(); } catch (VIRException e) { log.warn("Cannot open image index!", e); } // init feature extraction bean try { if (img2ftx == null) img2ftx = new Image2Features(getConfiguration() .getIndexConfFolder(getDataset())); } catch (Exception e) { log.warn("Cannot instantiate feature extractor!", e); } } /* * (non-Javadoc) * * @see * eu.europeana.service.ir.image.api.ImageSearchingService#searchSimilar * (java.lang.String) */ public void searchSimilar(String resourceId) throws ImageSearchingException { this.searchSimilar(resourceId, null); } /* * (non-Javadoc) * * @see * eu.europeana.service.ir.image.api.ImageSearchingService#searchSimilar * (java.io.InputStream) */ public void searchSimilar(InputStream imageQueryObj) throws ImageSearchingException { this.searchSimilar(imageQueryObj, null); } /** * this method is the basis for index searching * * @param features * @throws ImageSearchingException */ private void searchByImageFeatures(String features, String queryType) throws ImageSearchingException { try { ArrayList<String> vals = new ArrayList<String>(); ArrayList<String> flds = new ArrayList<String>(); addFieldByQueryType(flds, queryType); vals.add(features); index.query(vals, flds, false); queryResults = new QueryResults(); List<SearchResultItem> results = getSearchResultsList(index .getResults(0, NUM_RESULTS)); queryResults.setResults(results); } catch (VIRException e) { throw new ImageSearchingException("Error performing search by obj", e); } catch (IOException e) { throw new ImageSearchingException("Error performing search by obj", e); } } protected ArrayList<SearchResultItem> getSearchResultsList(String[][] retval) { ArrayList<SearchResultItem> results = new ArrayList<SearchResultItem>( retval.length); for (int i = 0; i < retval.length; i++) { SearchResultItem resultItem = new ImageSearchResultItem(); resultItem.setScore(retval[i][0]); resultItem.setResourceId(retval[i][1]); resultItem.setThmbUrl(retval[i][2]); resultItem.setCachedThmbUrl(getCachedThumbnailUrl(resultItem)); if (resultItem.getResourceId() == null) break; // in the case that the search returns less than // retval.length results results.add(resultItem); log.info("add to results: " + resultItem.getResourceId()); log.info("score:" + resultItem.getScore()); } log.debug("results from index service: " + results.toString()); return results; } private String getCachedThumbnailUrl(SearchResultItem resultItem) { if(getThumbnailLocator() == null) return null; else{ return getThumbnailLocator().getImageUrl(getDataset(), resultItem.getResourceId()); } } /* * (non-Javadoc) * * @see * eu.europeana.service.ir.image.api.ImageSearchingService#searchSimilar * (java.net.URL) */ public void searchSimilar(URL imageQueryURL) throws ImageSearchingException { this.searchSimilar(imageQueryURL, null); } public List<SearchResultItem> getResults(int startFrom, int numResults) { return queryResults.getResults(startFrom, numResults); } @Override public int getTotalResults() throws ImageSearchingException { try { return queryResults.getResults(0, -1).size(); } catch (NullPointerException e) { throw new ImageSearchingException( ImageSearchingException.MESSAGE_NO_RESULTS, e); } } @Override public IRConfiguration getConfiguration() { if (configuration == null) configuration = new IRConfigurationImpl(); return configuration; } protected String getDataset() { return dataset; } public ImageLocator getThumbnailLocator() { if (imageLocator == null) { String imageLocatorClass = getConfiguration() .getImageLocatorClass(); if (imageLocatorClass != null) { try { imageLocator = (ImageLocator) Class.forName( imageLocatorClass).newInstance(); imageLocator.setConfigParams(getConfiguration().getLocatorConfigurations()); } catch (Exception e) { throw new TechnicalRuntimeException( "Cannot instantiate image controller! check project configurations!", e); } } } return imageLocator; } @Override public void searchSimilar(String resourceId, String queryType) throws ImageSearchingException { ArrayList<String> vals = new ArrayList<String>(); ArrayList<String> flds = new ArrayList<String>(); addFieldByQueryType(flds, queryType); vals.add(resourceId); try { index.query(vals, flds, true); queryResults = new QueryResults(); List<SearchResultItem> results = getSearchResultsList(index .getResults(0, NUM_RESULTS)); queryResults.setResults(results); } catch (VIRException e) { throw new ImageSearchingException("Error performing search by id " + resourceId, e); } catch (IOException e) { throw new ImageSearchingException("Error performing search by id " + resourceId, e); } } protected void addFieldByQueryType(ArrayList<String> flds, String queryType) { if(queryType == null || QUERY_TYPE_MP7.equals(queryType)) flds.add(it.cnr.isti.melampo.index.Parameters.LIRE_MP7ALL); else flds.add(it.cnr.isti.melampo.index.Parameters.CC_DCD); } @Override public void searchSimilar(InputStream imageQueryObj, String queryType) throws ImageSearchingException { log.info("searching by obj "); try { String features = img2ftx.extractFeatures(imageQueryObj); searchByImageFeatures(features, queryType); } catch (FeatureExtractionException e) { throw new ImageSearchingException( "Cannot extract features from (image) input stream! ", e); } } @Override public void searchSimilar(URL imageQueryURL, String queryType) throws ImageSearchingException { log.info("searching by URL " + imageQueryURL.toString()); try { String features = img2ftx.extractFeatures(imageQueryURL); searchByImageFeatures(features, queryType); } catch (FeatureExtractionException e) { throw new ImageSearchingException( "Cannot extract features from (image) input stream! ", e); } } }