Tag Archives: CCTV

Consolidating real time traffic CCTV data from data.gov.hk with Goolge Map API

Real time CCTV snapshot images from major route and highways in Hong Kong are provided online at data.gov.hk. Considering availability of data and related technology in the last decade, we have made a huge progress from obtaining traffic jam information from the radio to real time traffic CCTV images on the web.

Advancement in web technology not only enabled access of information, but also provided information in a manner flexible enough to easily build new view of content from multiple sources. The term “mashups” generally refer to this type of web application, and one such example presented here being visualizing road traffic data in near real time images on the web. A demo page is available on this site.

As explained in a previous article demonstrating a practical neural network application, CCTV images from the Hong Kong road network are already made available online. Together with Google Map API, an integration of the two will no doubt a very interesting fusion of technology.

Firstly, visit data.gov.hk for a glimpse of the traffic data available. Each CCTV provides image data on the web via a fixed URL.

The next thing to do is to integrate these data in Google Map API. In an attempt for a quick demonstration, a simple out-of-the-box application is adapted to retrieve data from data.gov.hk. These include the camera image, and the best of all, the geographical information from each of these images, i.e. the longitude and latitude. data.gov.hk provided a complete list of geographical data of its cameras, but since they are encoded in a format not directly understood by Google Map (HK80), a translation is required.

After confirming the position of each camera, a simple CSV file is created and the resulting Javascript is generated using an AWK script. There can’t be a method possibly be simpler than this when a prototype page with the Google API has been worked out. The below is captured from the resulting web page showing a selection of location of interest from all available CCTV images from data.gov.hk.

hkdatagovcctv2

The map below in HTML created using Google Map API showing a complete list of CCTV location available at data.gov.hk. Clicking on each marker will open the real time image from the corresponding CCTV camera.hkdatagovcctv1

Excel is used to output a CSV data file for generating the Javascript file for use in the above example. The original file is in PDF but it is fairly easy to convert into Excel and then export from local coordinates in data.gov.hk (HK80) to something Google Map API can understand and render.hkdatagovcctv3

The layout of the CSV file is largely duplicated from the PDF file, and the line below is a sample. Most fields are self-explanatory, only the last three fields are additional to the data from the PDF file. Two of these are the converted coordinates for Google Map, and the last one is the default position of the CCTV image with respect to the marker. This can be either one of C,Q,W,A,S. For Q,W,A,S the image will be displayed on the corresponding quadrant as these characters are laid out on the keyboard, while C represent the display centered below the marker.


H106F,H106F.JPG,Connaught Road Central near Exchange Square,http://tdcctv.data.one.gov.hk/H106F.JPG,816365,834060,22.2861747,114.1554513,C

The AWK script below is used to loop through the CSV file to generate the part of the HTML content for each CCTV data.

BEGIN{
	FS=",";
	idx=1
}

{
	print "y0=" $7 ";x0=" $8;
	print "y1=y0+0.04;x1=x0+0.05;"
	print "var bounds" idx " = new google.maps.LatLngBounds(new google.maps.LatLng(y0,x0),new google.maps.LatLng(y1,x1));"
    print "var srcImage" idx " = '" $4 "';"
	print "var marker" idx " = new google.maps.Marker({position:new google.maps.LatLng(y0,x0),map:map,title: '" $1 "\\n" $3 "'});"
	print "var quadrant" idx " = \"C\";"
    print "overlay" idx " = new TrafficImageOverlay(bounds" idx ", srcImage" idx ", quadrant" idx ", map);"
	print "arr.push(overlay" idx ");"
	print "marker" idx ".addListener('click', function() {overlay" idx ".toggle();});"
	if ($9=="C") {
		print "overlay" idx ".toggle();"
	}
	idx++;
}

Finally, the HTML file.

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <title>Hong Kong Real Time Road Traffic Camera Image</title>
<style>
      /* Always set the map height explicitly to define the size of the div
       * element that contains the map. */
      #map {
        height: 100%;
      }
      /* Optional: Makes the sample page fill the window. */
      html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
    </style>

    <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_SECRET_GOOGLEMAP_KEY"></script>
    <script>

    var overlay;
	var arr = [];
    TrafficImageOverlay.prototype = new google.maps.OverlayView();
    TrafficImageOverlay.prototype.toggle = function() {
      if (this.getMap()) {
		if (this.quadrant_=="A") {this.quadrant_="Q"; this.setMap(null); this.setMap(this.map_);}
		else if (this.quadrant_=="Q") {this.quadrant_="W"; this.setMap(null); this.setMap(this.map_);}
		else if (this.quadrant_=="W") {this.quadrant_="S"; this.setMap(null); this.setMap(this.map_);}
		else if (this.quadrant_=="S") {this.quadrant_="C"; this.setMap(null); this.setMap(this.map_);}
		else if (this.quadrant_=="C") {this.quadrant_="A"; this.setMap(null);}
		else
		this.setMap(null);
      } else {
        this.setMap(this.map_);
      }
    };

	TrafficImageOverlay.prototype.refreshImg = function() {
		try {
			this.img_.src=this.image_+'?rand=' + Math.random();
		}
		catch (err) {
			Console.log(err);
		}
	}

	function initMap() {
        var map = new google.maps.Map(document.getElementById('map'), {
			zoom: 12,
			center: {lat: 22.308, lng: 114.1368}
        });

		var x0,x1,y0,y1;

		<!-- code block below is generated from awk script, showing only one block. One block for each CCTV data. -->

		y0=22.35110061;x0=114.0740287;
		y1=y0+0.04;x1=x0+0.05;
		var bounds1 = new google.maps.LatLngBounds(new google.maps.LatLng(y0,x0),new google.maps.LatLng(y1,x1));
        var srcImage1 = 'http://tdcctv.data.one.gov.hk/TC560F.JPG';
		var marker1 = new google.maps.Marker({position:new google.maps.LatLng(y0,x0),map:map,title: 'Tsing Ma Bridge'});
		var quadrant1 = "Q";
        overlay1 = new TrafficImageOverlay(bounds1, srcImage1, quadrant1, map);
		arr.push(overlay1);
		marker1.addListener('click', function() {overlay1.toggle();});

		<!-- end code block generated from awk script -->
	}

    function TrafficImageOverlay(bounds, image, quadrant, map) {this.bounds_ = bounds;this.image_ = image;this.quadrant_ = quadrant;this.map_ = map;this.div_ = null;this.setMap(map);}
		TrafficImageOverlay.prototype.onAdd = function() {
        var div = document.createElement('div');div.style.borderStyle = 'none';div.style.borderWidth = '0px';div.style.position = 'absolute';
        var img = document.createElement('img');img.src = this.image_;img.style.width = '100%';img.style.height = '100%';
		img.style.position = 'absolute';div.appendChild(img);this.div_ = div;
		var panes = this.getPanes();panes.overlayLayer.appendChild(div);
		this.img_=img;
    };

	TrafficImageOverlay.prototype.draw = function() {
        var overlayProjection = this.getProjection();
        var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
        var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());
        var div = this.div_;div.style.left = sw.x+'px';div.style.top=ne.y+'px';div.style.width=(ne.x-sw.x)+'px';div.style.height=(sw.y-ne.y)+'px';
		if (this.quadrant_=="Q") {
			div = this.div_;div.style.left = sw.x-(ne.x-sw.x)+'px';div.style.top=ne.y+'px';div.style.width=(ne.x-sw.x)+'px';div.style.height=(sw.y-ne.y)+'px';
		}else if (this.quadrant_=="W") {
			div = this.div_;div.style.left = sw.x+'px';div.style.top=ne.y+'px';div.style.width=(ne.x-sw.x)+'px';div.style.height=(sw.y-ne.y)+'px';
		}else if (this.quadrant_=="A") {
			div = this.div_;div.style.left = sw.x-(ne.x-sw.x)+'px';div.style.top=ne.y+(sw.y-ne.y)+'px';div.style.width=(ne.x-sw.x)+'px';div.style.height=(sw.y-ne.y)+'px';
		}else if (this.quadrant_=="S") {
			div = this.div_;div.style.left = sw.x+'px';div.style.top=ne.y+(sw.y-ne.y)+'px';div.style.width=(ne.x-sw.x)+'px';div.style.height=(sw.y-ne.y)+'px';
		}else if (this.quadrant_=="C") {
			div = this.div_;div.style.left = sw.x-(ne.x-sw.x)/2+'px';div.style.top=ne.y+(sw.y-ne.y)+'px';div.style.width=(ne.x-sw.x)+'px';div.style.height=(sw.y-ne.y)+'px';
		}
    };

	TrafficImageOverlay.prototype.onRemove = function() {
        this.div_.parentNode.removeChild(this.div_);this.div_ = null;
    };

    google.maps.event.addDomListener(window, 'load', initMap);

	var refreshIdx = 0;
	setInterval(
		function() {
			refreshIdx++;
			if (refreshIdx >= arr.length) {
				refreshIdx = 0;
			}
			try {
				arr[refreshIdx].refreshImg();
			} catch (err) {
				Console.log(err);
			}
		},10000
	);
    </script>
  </head>
  <body>
<div id="map"></div>
</body>
</html>
Advertisements

Analysis of traffic CCTV camera image from data.gov.hk with GPU deep learning on Amazon cloud

In this installment, modern computing technology including Internet, artificial intelligence, deep learning, GPU, and cloud technology are utilized to solve practical problem.

Traffic jam is very common in metropolitan cities. Authorities responsible for road traffic management often install CCTV for monitoring. Data available at data.gov.hk site published on the Internet for big data analysis is one such example. The followings are two sample images from the same camera with one showing heavy traffic and the other one with very light traffic.

Modern pattern recognition technology is a piece of cake to determine these two distinct conditions from reading images above. The frontier in this field is no doubt utilizing deep learning network in GPU processor. Amazon AWS provided GPU equipped computing resources for such task.

The first step is to fire up an GPU instance on Amazon AWS. The following AMI is selected. Note that HVM is required for GPU VM.
awsgpu1

The next step is to choose a GPU instance. As the problem is simple enough only g2.2xlarge is used.
awsgpu2

After logging in to the terminal, set up CUDA 7, cuDNN, caffe, and DIGITS. The steps can be referred from their respective official documentations. A device query test below confirmed successful installation of CUDA. The whole process may took an hour to complete if installed from scratch. There may be pre-built images out there.
awsgpu4

Note that an account from NVIDIA Accelerated Computing Developer Program may be required to download some of these packages. A make test below confirmed complete setup of caffe.awsgpu5

Finally, after installing DIGITS, the login page is default to port 5000. At AWS console network connection rule can easily be setup to open this port. Alternatively, for more secure connections, tunneling can be used instead, as shown below running at 8500.awsgpu6

Now it is time to start training. A new image classification dataset is to be created. As stated above the source image set is obtained from data.gov.hk. At this site, traffic cameras installed over strategic road network point feed JPG image on the web for public access. The images are refreshed every 2 minutes. A simple shell script is prepared to fetch the image to build the data set. Below is the screen where DIGITS configures the classification training.
awsgpu8

Since our sample data set size is small, the training completed in no time.
awsgpu9

awsgpu10

Next, a model is defined. GoogLeNet is selected in this example.
awsgpu12awsgpu13

Model training in progress. The charts update in real time.
awsgpu17

awsgpu15awsgpuB

When the model is completed, some tests can be carried out. In this example, the model is trained to determine whether the camera image taken indicates traffic jam or not.

A traffic jam sample. Prediction: free=-64.23%, jam=89.32%
awsgpuC

The opposite. Prediction: free=116.62%, jam=-133.61%
awsgpuE

With Amazon cloud, the ability to deploy cutting edge AI technology in GPU is no longer limited to researchers or those rich in resources. General public can now benefit from these easy to access computing resources to explore limitless possibilities in the era of big data.