001package org.openimaj.picslurper.output; 002 003import java.io.IOException; 004import java.io.PrintWriter; 005import java.net.URL; 006import java.util.ArrayList; 007import java.util.List; 008import java.util.Set; 009 010import org.apache.log4j.Logger; 011import org.kohsuke.args4j.Option; 012import org.kohsuke.args4j.ProxyOptionHandler; 013import org.openimaj.picslurper.client.TrendDetector; 014import org.openimaj.picslurper.client.TrendDetectorFeatureExtractor; 015import org.openimaj.util.pair.IndependentPair; 016 017import com.google.gson.Gson; 018import com.google.gson.GsonBuilder; 019 020/** 021 * Find trends using graphs for duplicate detection and graph cardinality for trend detection 022 * 023 * @author Sina Samangooei (ss@ecs.soton.ac.uk) 024 * 025 */ 026public class TrendDetectionOutputListener implements OutputListener { 027 028 private static final Logger logger = Logger.getLogger(TrendDetectionOutputListener.class); 029 030 private transient Gson gson = new GsonBuilder().setPrettyPrinting().create(); 031 032 @Option( 033 name = "--time-between-output", 034 aliases = "-tbo", 035 required = false, 036 usage = "The time between trend outputs") 037 long timeToWait = 10000; 038 039 @Option( 040 name = "--trend-output", 041 aliases = "-to", 042 required = false, 043 usage = "Where to output trending images") 044 String trendOutput = "trends.json"; 045 046 @Option( 047 name = "--top-trends", 048 aliases = "-ntrends", 049 required = false, 050 usage = "The number of trending sets to output") 051 int ntrends = 10; 052 053 @Option( 054 name = "--feature-extractor-mode", 055 aliases = "-feo", 056 required = false, 057 usage = "The feature extractor used by the trend detector", 058 handler = ProxyOptionHandler.class, 059 multiValued = true) 060 List<TrendDetectorFeatureMode> feMode = new ArrayList<TrendDetectorFeatureMode>(); 061 List<TrendDetectorFeatureExtractor> feModeOp = new ArrayList<TrendDetectorFeatureExtractor>(); 062 063 private long lastTrendOutput; 064 private List<IndependentPair<TrendDetectorFeatureMode, TrendDetector>> detectors; 065 066 /** 067 * Construct the publishing connector 068 */ 069 public TrendDetectionOutputListener() { 070 071 } 072 073 @Override 074 public void newImageDownloaded(WriteableImageOutput written) { 075 try { 076 for (IndependentPair<TrendDetectorFeatureMode, TrendDetector> detector : this.detectors) { 077 detector.getSecondObject().indexImage(written); 078 } 079 } catch (IOException e) { 080 logger.error("Failed to index image!",e); 081 } 082 if(lastTrendOutput == -1 || lastTrendOutput + timeToWait < System.currentTimeMillis()){ 083 outputTrends(); 084 lastTrendOutput = System.currentTimeMillis(); 085 } 086 } 087 088 @Override 089 public void failedURL(URL url, String reason) { 090 091 } 092 093 @Override 094 public void finished() { 095 outputTrends(); 096 } 097 static class CountTrend{ 098 long count; 099 Set<WriteableImageOutput> set; 100 } 101 private void outputTrends() { 102 for (IndependentPair<TrendDetectorFeatureMode, TrendDetector> detector : this.detectors) { 103 List<Set<WriteableImageOutput>> trending = detector.getSecondObject().trending(ntrends); 104 List<CountTrend> out = new ArrayList<CountTrend>(); 105 for (Set<WriteableImageOutput> set : trending) { 106 logger.debug(String.format("[%d] %s", set.size(),set.toString())); 107 CountTrend ct = new CountTrend(); 108 ct.count = set.size(); 109 ct.set = set; 110 out.add(ct); 111 } 112 String output = gson.toJson(out); 113 try { 114 PrintWriter writer = new PrintWriter(trendOutput + "-" + detector.firstObject() + ".json","UTF-8"); 115 writer.println(output); 116 writer.flush(); 117 writer.close(); 118 } catch (IOException e) { 119 logger.error("Failed to write trends", e); 120 } 121 } 122 } 123 124 @Override 125 public void prepare() { 126 127 detectors = new ArrayList<IndependentPair<TrendDetectorFeatureMode,TrendDetector>>(); 128 TrendDetector detector; 129 for (int i = 0; i < this.feMode.size(); i++) 130 { 131 TrendDetectorFeatureExtractor extractor = this.feModeOp.get(i); 132 TrendDetectorFeatureMode mode = this.feMode.get(i); 133 detector = new TrendDetector(); 134 detector.setFeatureExtractor(extractor); 135 detectors.add(IndependentPair.pair(mode, detector)); 136 } 137 lastTrendOutput = -1; 138 } 139 140}