Advice on techniques for recognising land/sea mass in google maps - language-agnostic

I am looking to develop some code that will be able to by looking at images downloaded from google maps, categorize which part of the image depicts the land and which part depicts the sea.
I am a bit of a newbie to computer vision and machine learning so I am looking for a few pointers on specific techniques or API's that may be useful (I am not looking for the code to this solution).
What I have some up with so far:
Edge detection may not be much help (on its own). Although it gives quite a nice outline of the coast, artefacts on the surface/above the sea may give false positives for land mass (stuff like clouds, ships, etc).
Extracting the blue colour element of an image may give a very good indication of which is sea or not (as obviously, the sea has a much higher level of blue saturation than the land)
Any help is of course, greatly appreciated.
EDIT (for anyone who may want to do something similar):
Use the static google maps API to
fetch map images (not satellite
photos, these have too much
noise/artefacts to be precise).
Example url-
http://maps.google.com/maps/api/staticmap?sensor=false&size=1000x1000&center=dover&zoom=12&style=feature:all|element:labels|visibility:off&style=feature:road|element:all|visibility:off
To generate my threshold images I used the Image processing lab. I would apply the normalized RGB -> extract blue channel filter and then apply Binarization -> otsu threshold. This has produced extremley useful images without the need to fiddle with thresholds values (the algorithm is very clever so I won't muddy the waters and attempt to explain it)

I assume you are using the satellite view images from Google Maps otherwise you wouldn't have written about ships or other artefacts.
As you already said it might be a good idea to simply try to extract the blue image part.
Just having a look at the blue channel of an RGB image isn't going to work (I just tried), since the woods and so on will not give a good threshold value on the water.
So you can try converting the image to YCbCr color space and have a look at the chrominance channels there.
This an example I just made with a screenshot from google maps. I converted it to YCbCr in Matlab and just took the Cb channel.
You can then binarize this image by a well set threshold, which shouldnt be too hard to find.
You probably will still have small artefacts for which you could use morphological operators (Opening the image several times).
This should remove small artefacts and leave the parts that are land and the parts that are water.
Hope it helps... if not, please keep asking...
EDIT
I've just tried again with another screenshot in matlab:
Convert Image to YCbCr colorspace
Just have a look at Cb channel
find threshold on Cb image either fixed or by i.e. Otsu's method which finds an appropriate thresholdl in a bipartite histogram
perform opening or other filters to eliminate small noises
The original image I made:
After applying a threshold on the Cb image:
After applying an opening (5) on the image
I just picked a threshold manually... You might get better results by having a look which threshold would work better... But as you see this should also work on the different colors of water from rivers and ocean.

You are looking for a segmentation algorithm, that assigns each pixel to one of two classes (land, sea). One of the simplest approaches is to use thresholding.
define a threshold t
if pixel value > t -> assign pixel to land
else assign pixel to sea (usually you will have a bitmap, where you keep track of the pixel class)
Since this approach works best if you can distinguish land and sea masses easily, I would suggest that you compare the hue value of the pixels (i. e. find a threshold between blue and green).

Related

Polygonal Search

I have read several of the posts concerning Polygonal Search, but they are all about fixing or updating the programs. I am just wondering how it works. If there is a way I can get something like pseudo code of it or an explanation of how a shape captures the data points.
To further specify my goal, I am trying to make a constant square that will be held over a map (such as google maps), but the map can move around behind the square, however, the square will continue to report whatever cities lie within its bounds. [I will eventually proceed to building it, I just need some guidance]
Thank you.
There is an open-source library which has a function to check if two shapes overlap. You can check source code:
http://turfjs.org/static/docs/module-turf_inside.html
If you look for theory behind it check Hyperplane separation theorem

Determine type of terrain at location

I'm trying to determine the terrain type at an arbitrary location. If I make use of Google Maps for instance, I can visually see what terrain is forest, built up areas and water for instance by the colour displayed on the map.
I'm trying to see whether there's any sort of API call I can use to get this basic information. I don't need it to be highly precise and I don't really need to determine the exact terrain type (so stuff like the Corine Land Cover is pure overkill). I'm going to need to make a number of these requests every few minutes. I've found a previously asked question around 3 years ago which wasn't really resolved, I'm hoping that there's been a change now.
Is there anything I can use? I'm actually considering reading the displayed map tile myself and grabbing the pixel colour, but I'd appreciate if there was a simpler method.
It doesn't seem like they provided the API to do that..
A work around would be to use their static maps API.
basically after you turn off everything but the water and greens, you get something like this:
http://maps.googleapis.com/maps/api/staticmap?center=37.7833,-122.4167&zoom=10&format=png&sensor=false&size=640x480&maptype=roadmap&style=visibility:off&style=feature:water|element:geometry|visibility:simplified&style=feature:poi.park|element:geometry|visibility:on
you can, make the size to be 1px by 1px, zoom in, and check the color of this image to decide the type of area of this location.

open earth map with irregular station measurement overlays

I would like to draw a map of current temperatures (or air pressures, etc.) from many weather stations, with the underlying map still recognizable. the problem is easiest to think of as follows:
I have an array of spot measurements from irregularly spaced dots---think triples of GPS coordinates with one temperature value each. my stations can be very close to or very far apart from one another, and a user may want to zoom in or out. cold should be blue, warm should be red. Ideally, I would like to just pass the array, the color range, and have the rest be taken care of. I would prefer everything to be inside a web browser. The user needs to be able to zoom in, zoom out, move around, and get back to his current location.
I do not even know how to think about this problem. If a user has zoomed out enough, non-transparent dots could be so close as to obscure the terrain. However, zooming in, it would be nice to recognize the dot that is the station itself. This presumably requires some intelligence that realizes how many dots there are, e.g., relative to the density of the display? not sure.
I believe google maps charges for many API calls, so I would prefer using an open map and/or open API that can use different underlying maps. It does not have to be fancy. I don't care about directions, etc.---just a map that is recognizable at most zoom settings, with landmark and street names, and my nice temperature station overlay coloring, so that a user can visualize where it is cold and where it is warm.
(Stations come online and offline, but I don't need to update this more than once an hour. I can place the map measurements into a file that is URL web-accessible.)
is this an easy or a hard problem for the high-level web programmer?
/iaw
after looking around for a long time, I think the best way to do this is with html5 openlayers nexrad.
alas, the docs seem to be a mess. half the examples that I found did not seem to work. it's pretty hit-or-miss. similarly, the openlayers cookbook also seems to be outdated and has incorrect examples, but they did have a reasonably short example of such a nexrad map overlaid on the U.S., that one can further study.

html5 svg vs canvas for granite like background

i want to make to make a granite like background like http://www.tivli.com/ with a gradient at the center. i have found how to do gradient with both in the w3c tutorials, but are there any tutorials on how to make granite backgrounds in html5 canvas or svg? Thanks.
The site you referenced actually uses a simple 'noize.png' and then uses css3 radial gradients to buildup that background. I know you already knew that, I'm mentioning this for future readers.
Given this fact, I'll assume in the rest of my answer you want to learn, not a copy-pasta solution.
I've given up on svg looong time ago. But in canvas it's easy and fun... (especially now flash is FINALLY officially dead. Hurray).
So as others have already suggested in the comments to your question, why not use a seamless noise image? (you know where to find one :P).
You could still embed this image as 'DATA' in the html(, HINT: even or even feed image-data straight into canvas that will render it as your 'noise.php').
But then.. you are right: what if you wanted to change the noize-size?
And you want to know how to make granite/noise anyway..
And is mathematically/programmatically describing this noise lower in character-count (file-size) than supplying a ready-made image(-fragment)?
Start UPDATE 2 part 1:
Actually, after some good night sleep I realized/remembered that visual noise is one of the BEST way's to determine randomness. Humans are notoriously good at finding visual patterns, even professionals use this (and as such this is also heavily used in cryptography where one would need -for instance- a useful one time pad).
Also see 'commander' Crockford's YUI-lecture 'Principles of Security' from 19m07s to 22m37s.
Now why is this important? Well ECMA-script (aka javascript) defines a loose Math.random() function:
"returns a number value with positive sign, greater than or equal to 0 but less than 1, chosen randomly or pseudo randomly with
approximately uniform distribution over that range, using an
implementation-dependent algorithm or strategy"
Re-read the italic/bold part and welcome yourself to reality: each and every browser (brand/version) has it's own random-routine!!
"But what does it mean?" Well.. simply put.. Depending on browser(version)'s ES-Script implementation (cough cough IE): Noise based on Math.random() will/might render visible patterns in your noise (independently of possible tile-size)!!
So for the rest of this answer we are going to assume either an ideal world where browsers spit-out proper random numbers, or that you took control and use a stronger 'predictable' random-solution as is discussed on this wonderful article that google's bubble accidentally leaked :)
End Update 2 part 1
So let's start with the radial gradient-part. You already figured that one out.
Ok, then follows the noise-function in canvas (you could you could do this before the radial gradient, but this order gives a nicer grain and diffuses color banding the gradient produces -on a average lcd you would see them anyway since they're not true color-) : this is done by generating random pixels.
There would be a lot of different algorithms to use, I've used a straight-forward one that you can understand without math..
Note that generating noise for a modern day full-screen resolution is easily larger than 1 mega-pixel in resolution, so this would be slow! To overcome this we need to generate and RE-USE a small seamless tile. We use this as a pattern-fill in our full-size image that already has the radial gradient.
I also assume you want the radial gradient liquidly placed in the middle of the view-port, so if you want to go the fixed way (as opposed to the noize.png/css3 way you referenced), you'll also need an extra eventhandler 'onResize()' to have canvas render a new background.
Why? Well if you where to let the browser scale this background-image (created upon page-load) automatically, then the nice grain-size of your noise would change to, EVEN leading to visible PATTERNS that you would not want..
(Since I desperately want to go to sleep now..): The rest is thoroughly explained in the source-code of the function I wrote for you..
Here is the link to the fully documented code I wrote for you: jsfiddle.net/sU74C/ and here you can see it in full-screen preview.   UPDATE 1: function genNoise 80% FASTER!!
Use it if you like (retaining the link to this answer) or learn from it and do your own thing.
PLEASE DON'T FORGET to accept AN answer to this question (hopefully mine :))
Hope this helps!
UPDATE 2 part 2:
There are more way's to interact with canvas. One could also calculate/(re-)use/generate/save/import pixel-maps/array's (as png or base64 or jpg or ...) for instance, see this excellent article on faster 8bit and even faster 32bit (if the browser supports 'Uint8ClampedArray' as the type of the data property of the ImageData object) pixel-array's, including a proper solution to account for the endianness of the processor!!
So after giving this some considerable thought, it turns out that to do this 'right' is actually a challenge and should be divided in 2 parts:
Where do I get my noise-data (Math.random() or custom random or pre-defined external (image, json-string, random.com) or embedded (packed?) data)?
What is the fastest way to build/store/re-use this noise on full-screen size/canvas.
Given the statements in part 1 of this update and that we don't want patterns in our visible noise, I'm starting to lean to using some pre-rendered 'random' noise data (meant to tile seamlessly) that is embedded in the noise-generator: otherwise there is the overhead of running your own none-engine-optimized random function (times..a lot..).
Also I think one might get away with just black and white and transparency afterwards.. This might considerably speed-up things up AND reduce embedded pixel-data.
Think about it: black or white equals 0 or 1..
In base 64 one character can represent 6 bits. So a 30x30px image has 900 px divided by 6 bits = 150 characters (sweet-spot increments by 6px, so next is 36px*36px is 216 characters).

Subway lines in KML with different colors on one track?

My first KML project was an animated map of the Washington DC Metro system (see Animating Metro with KML and Google Earth). Unfortunately, where Metro lines share the same track, only one color prevails. The real map shows a wider line with both colors side by side.
Is there a way to draw a line in KML (Google Earth) with two side-by-side colors? I've seen a way to have a different color on the edges of the line, but that's different.
I could cheat by changing the coordinates of each station, but aside from computational difficulties, I'd have to continuously changes to positions every time the user zooms, to prevent a gap between colors (or an overlap).
Other subway systems show more than two colors running alongside each other, so an option to show multiple colors would be nice. And this is not really a gradient, as the colors don't fade together; they should be distinct, assuming the pixel width is wide enough.
This is probably a feature request, though surely someone else has run across this problem before Google Earth v6? Would love to be able to do this, or find a good workaround in the interim.
Michael
http://www.mvjantzen.com/blog/
The short answer is no, although you could probably create a custom MVC object that renders the line for you as desired (i.e. you would not need to alter the Kml)
http://code.google.com/apis/maps/articles/mvcfun.html
That said, your cheat method could work too - and I would disagree that
"...I'd have to continuously changes to positions every time the user
zooms, to prevent a gap between colors"
You can set the <gx:physicalWidth> property which allows you to set the width of a LineString to be in meters, rather than pixels.
https://developers.google.com/kml/documentation/kmlreference#gxphysicalwidth
In the case of your track example, this means you can set the width of the track to match the underlying imagery no matter what altitude the end user views it from.