/** * */ package nl.tno.stormcv.example; import java.util.ArrayList; import java.util.List; import backtype.storm.Config; import backtype.storm.LocalCluster; import backtype.storm.topology.TopologyBuilder; import backtype.storm.tuple.Fields; import backtype.storm.utils.Utils; import nl.tno.stormcv.StormCVConfig; import nl.tno.stormcv.batcher.SlidingWindowBatcher; import nl.tno.stormcv.bolt.BatchInputBolt; import nl.tno.stormcv.bolt.SingleInputBolt; import nl.tno.stormcv.example.util.GlobalContrastEnhancementOp; import nl.tno.stormcv.example.util.GlobalContrastEnhancementOp.CEAlgorithm; import nl.tno.stormcv.fetcher.StreamFrameFetcher; import nl.tno.stormcv.model.Frame; import nl.tno.stormcv.model.serializer.FrameSerializer; import nl.tno.stormcv.operation.MjpegStreamingOp; import nl.tno.stormcv.spout.CVParticleSpout; /** * @author John Schavemaker * */ public class E9_ContrastEnhancementTopology { /** * @param args */ public static void main(String[] args) { // first some global (topology configuration) StormCVConfig conf = new StormCVConfig(); /** * Sets the OpenCV library to be used which depends on the system the topology is being executed on */ //conf.put( StormCVConfig.STORMCV_OPENCV_LIB, "mac64_opencv_java248.dylib" ); conf.setNumWorkers( 4 ); // number of workers in the topology conf.setMaxSpoutPending( 32 ); // maximum un-acked/un-failed frames per spout (spout blocks if this number is reached) conf.put( StormCVConfig.STORMCV_FRAME_ENCODING, Frame.JPG_IMAGE ); // indicates frames will be encoded as JPG throughout the topology (JPG is the default when not explicitly set) conf.put( Config.TOPOLOGY_ENABLE_MESSAGE_TIMEOUTS, true ); // True if Storm should timeout messages or not. conf.put( Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS , 10 ); // The maximum amount of time given to the topology to fully process a message emitted by a spout (default = 30) conf.put( StormCVConfig.STORMCV_SPOUT_FAULTTOLERANT, false ); // indicates if the spout must be fault tolerant; i.e. spouts do NOT! replay tuples on fail conf.put( StormCVConfig.STORMCV_CACHES_TIMEOUT_SEC, 30 ); // TTL (seconds) for all elements in all caches throughout the topology (avoids memory overload) // some live camera feeds from http://webcam.prvgld.nl/ List<String> urls = new ArrayList<String>(); urls.add( "rtsp://streaming3.webcam.nl:1935/n224/n224.stream" ); urls.add( "rtsp://streaming3.webcam.nl:1935/n233/n233.stream" ); int frameSkip = 13; // now create the topology itself (spout -> contrast enhancement --> streamer) TopologyBuilder builder = new TopologyBuilder(); // just one spout reading streams; i.e. this spout reads two streams in parallel builder.setSpout( "spout", new CVParticleSpout( new StreamFrameFetcher( urls ).frameSkip( frameSkip ) ), 1 ); // add bolt that does contrast enhancement (choose HSV_EQUALIZE_HIST or GRAY_EQUALIZE_HIST as algorithm) builder.setBolt( "contrastenhancement", new SingleInputBolt( new GlobalContrastEnhancementOp().setAlgorithm( CEAlgorithm.HSV_EQUALIZE_HIST ) ), 1 ) .shuffleGrouping( "spout" ); // add bolt that creates a web service on port 8558 enabling users to view the result builder.setBolt( "streamer", new BatchInputBolt( new SlidingWindowBatcher( 2, frameSkip).maxSize( 6 ), // note the required batcher used as a buffer and maintains the order of the frames new MjpegStreamingOp().port( 8558 ).framerate( 5 ) ).groupBy( new Fields( FrameSerializer.STREAMID ) ) , 1) .shuffleGrouping( "contrastenhancement" ); // NOTE: if the topology is started (locally) go to http://localhost:8558/streaming/tiles and click the image to see the stream! try { // run in local mode LocalCluster cluster = new LocalCluster(); cluster.submitTopology( "BackgroundSubtraction", conf, builder.createTopology() ); Utils.sleep( 120 * 1000 ); // run for one minute and then kill the topology cluster.shutdown(); System.exit( 1 ); // run on a storm cluster // StormSubmitter.submitTopology("some_topology_name", conf, builder.createTopology()); } catch (Exception e) { e.printStackTrace(); } } }