/* * This file is part of Caliph & Emir. * * * Caliph & Emir is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Caliph & Emir is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Caliph & Emir; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Copyright statement: * -------------------- * (c) 2002-2005 by Mathias Lux (mathias@juggle.at) * http://www.juggle.at, http://caliph-emir.sourceforge.net * * changes by Margit Lang November 2005 */ package at.lux.fotoretrieval.retrievalengines; import at.lux.fotoretrieval.FileOperations; import at.lux.fotoretrieval.ResultListEntry; import at.lux.fotoretrieval.RetrievalFrame; import at.lux.fotoretrieval.RetrievalToolkit; import at.lux.imageanalysis.ColorLayout; import at.lux.imageanalysis.EdgeHistogram; import at.lux.imageanalysis.ScalableColor; import at.lux.imageanalysis.EdgeHistogramImplementation; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.Namespace; import org.jdom.input.SAXBuilder; import javax.swing.*; import java.io.File; import java.io.FileInputStream; import java.util.*; /** * FileSystemRetrieval * * @author Mathias Lux, mathias@juggle.at */ public class FileSystemRetrieval extends AbstractRetrievalEngine { private int maxResults = 50; private Vector matches1; public FileSystemRetrieval(int maxResults) { matches1 = new Vector(); this.maxResults = maxResults; } /** * @author margit * @param VisualDescriptorSet * @param whereToSearch * @param recursive * @param progress * */ public List<ResultListEntry> getSimilarImages_fromSet(Set<Element> VisualDescriptorSet, String whereToSearch, boolean recursive, JProgressBar progress) { Element VisualDescriptor; List<ResultListEntry> results = new LinkedList<ResultListEntry>(); Namespace mpeg7 = Namespace.getNamespace("", "urn:mpeg:mpeg7:schema:2001"); Namespace xsi = Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); int counter = -1; try { String[] descriptions = FileOperations.getAllDescriptions(new File(whereToSearch), recursive); double[][] diffs = new double[VisualDescriptorSet.size()][descriptions.length]; double[] difference = new double [diffs[0].length]; for (int j = 0; j<diffs.length; j++) { for (int i = 0; i < diffs[j].length; i++) { diffs[j][i] = -1.0; difference[i]=-1.0; } } double[] maxdiff = new double[maxResults]; for (int i = 0; i < maxdiff.length; i++) { maxdiff[i] = -1.0; } SAXBuilder builder = new SAXBuilder(); for (Iterator iterator = VisualDescriptorSet.iterator();iterator.hasNext();) { counter++; VisualDescriptor = (Element) iterator.next(); String descType = VisualDescriptor.getAttributeValue("type", xsi); if (progress != null) { progress.setString(VisualDescriptorSet.size()+" Margit: Finding MPEG-7 files ..."); } if (progress != null) { progress.setMinimum(0); progress.setMaximum(descriptions.length); progress.setValue(0); progress.setString("Comparing images " + descType); } ScalableColor scc = null; for (int i = 0; i < descriptions.length; i++) { Element e = null; try { e = builder.build(new FileInputStream(descriptions[i])).getRootElement(); java.util.List l = RetrievalToolkit.xpathQuery(e, "//VisualDescriptor", null); if (l.size() > 0) { // debug("Comparing elements ..."); if (descType.equals("ColorLayoutType")) { // debug("Comparing ColorLayout ..."); Element toCompare = null; for (Iterator iter = l.iterator(); iter.hasNext();) { Element elem = (Element) iter.next(); if (elem.getAttributeValue("type", xsi).equals("ColorLayoutType")) { //diffs[counter][i] = ColorLayout.getSimilarity(VisualDescriptor, (Element) l.get(0)); difference[i]= difference[i] + ColorLayout.getSimilarity(VisualDescriptor, (Element) l.get(0)); } } } else if (descType.equals("EdgeHistogramType")) { EdgeHistogram a = null; try { a = new EdgeHistogram(VisualDescriptor); } catch (Exception e1) { System.err.println("EdgeHistogram a is not an valid EdgeHistogram: " + e1.getMessage()); } for (Iterator iter = l.iterator(); iter.hasNext();) { Element elem = (Element) iter.next(); if (elem.getAttributeValue("type", xsi).equals("EdgeHistogramType")) { EdgeHistogram b = null; try { b = new EdgeHistogram(elem); } catch (Exception e1) { System.err.println("EdgeHistogram b is not an valid EdgeHistogram: " + e1.getMessage()); } difference[i]= difference[i]+ (double) EdgeHistogramImplementation.calculateDistance(a.getHistogram(), b.getHistogram()); //diffs[counter][i] = (double) EdgeHistogram.getSimilarity(a.getHistogram(), b.getHistogram()); } } } else if (descType.equals("ScalableColorType")) { // debug("Comparing ScalableColor ..."); String numC, numB; numC = VisualDescriptor.getAttributeValue("numOfCoeff"); numB = VisualDescriptor.getAttributeValue("numOfBitplanesDiscarded"); for (Iterator iter = l.iterator(); iter.hasNext();) { Element elem = (Element) iter.next(); if (elem.getAttributeValue("type", xsi).equals("ScalableColorType")) { // Ists der richtige D? if (numC.equals(elem.getAttributeValue("numOfCoeff")) && numB.equals(elem.getAttributeValue("numOfBitplanesDiscarded"))) { // Stimmen die Zahlen? if (!(scc != null)) { scc = new ScalableColor(VisualDescriptor); } difference[i]= difference[i]+scc.getSimilarity(new ScalableColor(elem)); //diffs[counter][i] = scc.getSimilarity(new ScalableColor(elem)); //debug(diffs[counter][i] + " - " + descriptions[i]); } else { debug("Not matched (numC,numB): " + "(" + numC + "," + numB + ") to (" + elem.getAttributeValue("numOfCoeff") + "," + elem.getAttributeValue("numOfBitplanesDiscarded") + ")"); } } } //difference[i]= difference[i]+diffs[counter][i]; } } if (progress != null) { progress.setValue(i); } } catch (JDOMException e1) { debug("Error building document " + descriptions[i]); } catch (Exception e2) { e2.printStackTrace(); } } } for (int i=0; i< difference.length;i++){ Element e = builder.build(new FileInputStream(descriptions[i])).getRootElement(); difference[i]= difference[i]/VisualDescriptorSet.size(); if (difference[i] > -1) { if (i == maxResults) { Arrays.sort(maxdiff); } if (i < maxResults) { maxdiff[i] = difference[i]; results.add(new ResultListEntry(difference[i], e, descriptions[i])); } else { if (difference[i] <= maxdiff[maxResults - 1] || maxdiff[maxResults - 1] < 0) { results.add(new ResultListEntry(difference[i], e, descriptions[i])); maxdiff[maxResults - 1] = difference[i]; for (int jj = maxResults - 1; jj > 0; jj--) { // bubble up :) if (maxdiff[jj - 1] > maxdiff[jj]) { double tmp = maxdiff[jj - 1]; maxdiff[jj - 1] = maxdiff[jj]; maxdiff[jj] = tmp; } } } } } //results.add(new ResultListEntry(difference[i], e, descriptions[i])); } // setting up results: if (progress != null) { progress.setMinimum(0); progress.setMaximum(descriptions.length); progress.setValue(0); progress.setString("Sorting images"); } // Sorting Vector ... Collections.sort(results, new Comparator() { public int compare(Object o1, Object o2) { int retVal = 0; double rel = ((ResultListEntry) o1).getRelevance() - ((ResultListEntry) o2).getRelevance(); if (rel < 0) retVal = -1; if (rel > 0) retVal = 1; return retVal; } }); } catch (Exception e) { debug("Couldn't find descriptions ... " + e.getMessage()); } return results; } public List<ResultListEntry> getImagesByXPathSearch(String xPath, String whereToSearch, boolean recursive, JProgressBar progress) { Vector results = new Vector(); try { if (progress != null) progress.setString("Finding MPEG-7 files ..."); String[] descriptions = FileOperations.getAllDescriptions(new File(whereToSearch), recursive); double[] diffs = new double[descriptions.length]; for (int i = 0; i < diffs.length; i++) { diffs[i] = -1.0; } SAXBuilder builder = new SAXBuilder(); if (progress != null) { progress.setMinimum(0); progress.setMaximum(descriptions.length); progress.setValue(0); progress.setString("Searching for XPath ..."); } double[] maxdiff = new double[maxResults]; for (int i = 0; i < maxdiff.length; i++) { maxdiff[i] = -1.0; } for (int i = 0; i < descriptions.length; i++) { Element e = null; try { e = builder.build(new FileInputStream(descriptions[i])).getRootElement(); java.util.List l = RetrievalToolkit.xpathQuery(e, xPath, null); if (l.size() > 0) { diffs[i] = 1.0 / (double) l.size(); if (i == maxResults) { Arrays.sort(maxdiff); } if (i < maxResults) { maxdiff[i] = diffs[i]; results.add(new ResultListEntry(diffs[i], e, descriptions[i])); } else { if (diffs[i] <= maxdiff[maxResults - 1] || maxdiff[maxResults - 1] < 0) { results.add(new ResultListEntry(diffs[i], e, descriptions[i])); maxdiff[maxResults - 1] = diffs[i]; for (int jj = maxResults - 1; jj > 0; jj--) { // bubble up :) if (maxdiff[jj - 1] > maxdiff[jj]) { double tmp = maxdiff[jj - 1]; maxdiff[jj - 1] = maxdiff[jj]; maxdiff[jj] = tmp; } } } else { debug("Result omitted!"); } } } l = null; if (progress != null) progress.setValue(i); } catch (JDOMException e1) { debug("Error building document " + descriptions[i]); } catch (Exception e1) { e1.printStackTrace(); } } // setting up results: if (progress != null) { progress.setMinimum(0); progress.setMaximum(descriptions.length); progress.setValue(0); progress.setString("Sorting images"); } // Sorting Vector ... Collections.sort(results, new Comparator() { public int compare(Object o1, Object o2) { int retVal = 0; double rel = ((ResultListEntry) o1).getRelevance() - ((ResultListEntry) o2).getRelevance(); if (rel < 0) retVal = -1; if (rel > 0) retVal = 1; return retVal; } }); } catch (Exception e) { debug("Couldn't find descriptions ... " + e.getMessage()); e.printStackTrace(System.out); } return results; } public List<ResultListEntry> getSimilarImages(Element VisualDescriptor, String whereToSearch, boolean recursive, JProgressBar progress) { List<ResultListEntry> results = new LinkedList<ResultListEntry>(); Namespace mpeg7 = Namespace.getNamespace("", "urn:mpeg:mpeg7:schema:2001"); Namespace xsi = Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); String descType = VisualDescriptor.getAttributeValue("type", xsi); try { if (progress != null) progress.setString("Finding MPEG-7 files ..."); String[] descriptions = FileOperations.getAllDescriptions(new File(whereToSearch), recursive); double[] diffs = new double[descriptions.length]; for (int i = 0; i < diffs.length; i++) { diffs[i] = -1.0; } SAXBuilder builder = new SAXBuilder(); if (progress != null) { progress.setMinimum(0); progress.setMaximum(descriptions.length); progress.setValue(0); progress.setString("Comparing images"); } double[] maxdiff = new double[maxResults]; for (int i = 0; i < maxdiff.length; i++) { maxdiff[i] = -1.0; } ScalableColor scc = null; for (int i = 0; i < descriptions.length; i++) { Element e = null; try { e = builder.build(new FileInputStream(descriptions[i])).getRootElement(); java.util.List l = RetrievalToolkit.xpathQuery(e, "//VisualDescriptor", null); if (l.size() > 0) { // debug("Comparing elements ..."); if (descType.equals("ColorLayoutType")) { // debug("Comparing ColorLayout ..."); Element toCompare = null; for (Iterator iter = l.iterator(); iter.hasNext();) { Element elem = (Element) iter.next(); if (elem.getAttributeValue("type", xsi).equals("ColorLayoutType")) { diffs[i] = ColorLayout.getSimilarity(VisualDescriptor, (Element) l.get(0)); } } } else if (descType.equals("EdgeHistogramType")) { EdgeHistogram a = null; try { a = new EdgeHistogram(VisualDescriptor); } catch (Exception e1) { System.err.println("EdgeHistogram a is not an valid EdgeHistogram: " + e1.getMessage()); } for (Iterator iter = l.iterator(); iter.hasNext();) { Element elem = (Element) iter.next(); if (elem.getAttributeValue("type", xsi).equals("EdgeHistogramType")) { EdgeHistogram b = null; try { b = new EdgeHistogram(elem); } catch (Exception e1) { System.err.println("EdgeHistogram b is not an valid EdgeHistogram: " + e1.getMessage()); } diffs[i] = (double) EdgeHistogramImplementation.calculateDistance(a.getHistogram(), b.getHistogram()); } } } else if (descType.equals("ScalableColorType")) { // debug("Comparing ScalableColor ..."); String numC, numB; numC = VisualDescriptor.getAttributeValue("numOfCoeff"); numB = VisualDescriptor.getAttributeValue("numOfBitplanesDiscarded"); for (Iterator iter = l.iterator(); iter.hasNext();) { Element elem = (Element) iter.next(); if (elem.getAttributeValue("type", xsi).equals("ScalableColorType")) { // Ists der richtige D? if (numC.equals(elem.getAttributeValue("numOfCoeff")) && numB.equals(elem.getAttributeValue("numOfBitplanesDiscarded"))) { // Stimmen die Zahlen? if (!(scc != null)) { scc = new ScalableColor(VisualDescriptor); } diffs[i] = scc.getSimilarity(new ScalableColor(elem)); debug(diffs[i] + " - " + descriptions[i]); } else { debug("Not matched (numC,numB): " + "(" + numC + "," + numB + ") to (" + elem.getAttributeValue("numOfCoeff") + "," + elem.getAttributeValue("numOfBitplanesDiscarded") + ")"); } } } } if (diffs[i] > -1) { if (i == maxResults) { Arrays.sort(maxdiff); } if (i < maxResults) { maxdiff[i] = diffs[i]; results.add(new ResultListEntry(diffs[i], e, descriptions[i])); } else { if (diffs[i] <= maxdiff[maxResults - 1] || maxdiff[maxResults - 1] < 0) { results.add(new ResultListEntry(diffs[i], e, descriptions[i])); maxdiff[maxResults - 1] = diffs[i]; for (int jj = maxResults - 1; jj > 0; jj--) { // bubble up :) if (maxdiff[jj - 1] > maxdiff[jj]) { double tmp = maxdiff[jj - 1]; maxdiff[jj - 1] = maxdiff[jj]; maxdiff[jj] = tmp; } } } } } } if (progress != null) progress.setValue(i); } catch (JDOMException e1) { debug("Error building document " + descriptions[i]); } catch (Exception e2) { e2.printStackTrace(); } } // setting up results: if (progress != null) { progress.setMinimum(0); progress.setMaximum(descriptions.length); progress.setValue(0); progress.setString("Sorting images"); } // Sorting Vector ... Collections.sort(results, new Comparator() { public int compare(Object o1, Object o2) { int retVal = 0; double rel = ((ResultListEntry) o1).getRelevance() - ((ResultListEntry) o2).getRelevance(); if (rel < 0) retVal = -1; if (rel > 0) retVal = 1; return retVal; } }); } catch (Exception e) { debug("Couldn't find descriptions ... " + e.getMessage()); } return results; } public List<ResultListEntry> getImagesBySemantics(String xPath, Vector objects, String whereToSearch, boolean recursive, JProgressBar progress) { LinkedList<ResultListEntry> results = new LinkedList<ResultListEntry>(); boolean isResult = false; try { if (progress != null) progress.setString("Finding MPEG-7 files ..."); String[] descriptions = FileOperations.getAllDescriptions(new File(whereToSearch), recursive); double[] diffs = new double[descriptions.length]; for (int i = 0; i < diffs.length; i++) { diffs[i] = -1.0; } SAXBuilder builder = new SAXBuilder(); if (progress != null) { progress.setMinimum(0); progress.setMaximum(descriptions.length); progress.setValue(0); progress.setString("Searching for XPath ..."); } double[] maxdiff = new double[maxResults]; for (int i = 0; i < maxdiff.length; i++) { maxdiff[i] = -1.0; } for (int i = 0; i < descriptions.length; i++) { Element e = null; try { e = builder.build(new FileInputStream(descriptions[i])).getRootElement(); java.util.List l = RetrievalToolkit.xpathQuery(e, xPath, null); isResult = false; if (l.size() > 0) { isResult = true; Element semantics = (Element) l.get(0); Namespace mpeg7 = semantics.getNamespace(); java.util.List rels = semantics.getChild("Graph", mpeg7).getChildren("Relation", mpeg7); java.util.List obje = semantics.getChildren("SemanticBase", mpeg7); String rel1 = (String) objects.get(3); String rel2 = (String) objects.get(4); boolean rel1OK = false; boolean rel2OK = false; debug("found Element matching XPath Statement ...."); // checking relation 1 if (rel1.length() > 0) { if (rel1.equals("*")) { for (Iterator it1 = rels.iterator(); it1.hasNext();) { Element relation = (Element) it1.next(); // test if objects are referenced: boolean inverse = false; if (((String) objects.get(5)).length() > 0) inverse = true; if (isValidRelation(relation, (String) objects.get(0), (String) objects.get(1), obje, inverse, 1)) { rel1OK = true; } } } else { for (Iterator it1 = rels.iterator(); it1.hasNext();) { Element relation = (Element) it1.next(); if (relation.getAttributeValue("type").endsWith(":" + rel1)) { // test if objects are referenced: boolean inverse = false; if (((String) objects.get(5)).length() > 0) inverse = true; if (isValidRelation(relation, (String) objects.get(0), (String) objects.get(1), obje, inverse, 1)) { rel1OK = true; } } } } } else { rel1OK = true; } // Checking relation 2 if (rel2.length() > 0) { if (rel2.equals("*")) { for (Iterator it1 = rels.iterator(); it1.hasNext();) { Element relation = (Element) it1.next(); // test if objects are referenced: boolean inverse = false; if (((String) objects.get(6)).length() > 0) inverse = true; if (isValidRelation(relation, (String) objects.get(1), (String) objects.get(2), obje, inverse, 2)) { rel2OK = true; } } } else { for (Iterator it1 = rels.iterator(); it1.hasNext();) { Element relation = (Element) it1.next(); if (relation.getAttributeValue("type").endsWith(":" + rel2)) { // test if objects are referenced: boolean inverse = false; if (((String) objects.get(6)).length() > 0) inverse = true; if (isValidRelation(relation, (String) objects.get(1), (String) objects.get(2), obje, inverse, 2)) { rel2OK = true; } } } } } else { rel2OK = true; } if (rel2.length() > 0) { } isResult = rel1OK && rel2OK; } if (isResult) { diffs[i] = 1.0 / (double) l.size(); if (i == maxResults) { Arrays.sort(maxdiff); } if (i < maxResults) { maxdiff[i] = diffs[i]; results.add(new ResultListEntry(diffs[i], e, descriptions[i])); } else { if (diffs[i] <= maxdiff[maxResults - 1] || maxdiff[maxResults - 1] < 0) { results.add(new ResultListEntry(diffs[i], e, descriptions[i])); maxdiff[maxResults - 1] = diffs[i]; for (int jj = maxResults - 1; jj > 0; jj--) { // bubble up :) if (maxdiff[jj - 1] > maxdiff[jj]) { double tmp = maxdiff[jj - 1]; maxdiff[jj - 1] = maxdiff[jj]; maxdiff[jj] = tmp; } } } else { debug("Result omitted!"); } } } l = null; if (progress != null) progress.setValue(i); } catch (JDOMException e1) { debug("Error building document " + descriptions[i]); } catch (Exception e1) { e1.printStackTrace(); } } // setting up results: if (progress != null) { progress.setMinimum(0); progress.setMaximum(descriptions.length); progress.setValue(0); progress.setString("Sorting images"); } // Sorting Vector ... Collections.sort(results, new Comparator() { public int compare(Object o1, Object o2) { int retVal = 0; double rel = ((ResultListEntry) o1).getRelevance() - ((ResultListEntry) o2).getRelevance(); if (rel < 0) retVal = -1; if (rel > 0) retVal = 1; return retVal; } }); } catch (Exception e) { debug("Couldn't find descriptions ... " + e.getMessage()); e.printStackTrace(System.out); } return results; } private void debug(String message) { if (RetrievalFrame.DEBUG) System.out.println("[at.lux.fotoretrieval.retrievalengines.FileSystemRetrieval] " + message); } private boolean isValidRelation(Element relation, String obj1, String obj2, java.util.List objects, boolean inverse, int numRelation) { boolean isValid = false; if (inverse) debug("Searching for inverse relation"); Namespace mpeg7 = relation.getNamespace(); String src = relation.getAttributeValue("source"); String tgt = relation.getAttributeValue("target"); Element target = null; Element source = null; for (Iterator iterator = objects.iterator(); iterator.hasNext();) { Element obj = (Element) iterator.next(); String id = obj.getAttributeValue("id"); if (id != null) { if (tgt.substring(1).equals(id)) { target = obj; // debug("Target: " + obj.getChild("Label", mpeg7).getChildTextTrim("Name", mpeg7)); } if (src.substring(1).equals(id)) { source = obj; // debug("Source: " + obj.getChild("Label", mpeg7).getChildTextTrim("Name", mpeg7)); } } } debug("Checking relation: " + relation.getAttributeValue("type") + " src: " + source.getChild("Label", mpeg7).getChildTextTrim("Name", mpeg7) + ", tgt: " + target.getChild("Label", mpeg7).getChildTextTrim("Name", mpeg7)); if (!inverse) { debug("for source contains '" + obj1 + "' and target contains '" + obj2 + "'"); } else { debug("for source contains '" + obj2 + "' and target contains '" + obj1 + "'"); } if (target != null && source != null) { int hits1 = 1; if (!obj1.equals("*")) { if (!inverse) { hits1 = RetrievalToolkit.xpathQuery(source, "*[contains(descendant-or-self::node(),'" + obj1 + "')]", null).size(); } else { hits1 += RetrievalToolkit.xpathQuery(target, "*[contains(descendant-or-self::node(),'" + obj1 + "')]", null).size(); } } int hits2 = 1; if (!obj2.equals("*")) { if (!inverse) { hits2 = RetrievalToolkit.xpathQuery(target, "*[contains(descendant-or-self::node(),'" + obj2 + "')]", null).size(); } else { hits2 += RetrievalToolkit.xpathQuery(source, "*[contains(descendant-or-self::node(),'" + obj2 + "')]", null).size(); } } if (hits1 > 0 && hits2 > 0) { isValid = true; if (numRelation == 1) { if (inverse) { matches1.add(source); } else { matches1.add(target); } } else { if (inverse) { isValid = matches1.contains(target); } else { isValid = matches1.contains(source); } // isValid = (matches1.contains(target) || matches1.contains(source)); } debug("Match detected!"); } } return isValid; } }