Barry Price

Just another Perl hacker, ensconced in Asia

How Flooded Is Bangkok?

| Comments

On a Saturday night, when I really should have been watching football, I noticed Vanalli and thai101 discussing the Bangkok floods on Twitter…

They are smart. They just aren’t Perl nerds. This is probably a good thing, as it means they don’t spend their Saturday nights writing Perl code… That would be sad. Ahem.

I hacked up a quick script that would scan through every pixel in a given image, count all of the pixels that were mostly blue, and report that back as a percentage. But I didn’t have a decent map to work from.

Soon enough though, @thai101 came up with this one (click to embiggen):

Share photos on twitter with Twitpic

This was created by cropping Bangkok itself out of this larger image.

The script I’d put together failed on two counts - I hadn’t considered that Bangkok is not rectangular (d’oh), and I’d assumed the flood pixels would be blue. They’re not - they’re turquoise. Which means that we’re not looking for “mostly blue” pixels - we’re looking for pixels which are very blue AND very green, but not very red.

That’s why the first run came up with a figure of 9%, which looked wrong - and was.

A few tweaks later though, it turns out that 21.19% of the pixels in that cropped image, discounting the white pixels, are approximately turquoise.

This is, of course, not the most scientific of investigations:

But it’s the best guess I’ve seen so far.

It’d be very interesting to run it daily and see how things are developing, if we can get hold of good enough source data in a timely manner.

For now though, here’s the Perl code for anyone who wants to check my work:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#!/usr/bin/perl

use Modern::Perl;
use Image::Magick;

my $fileName = $ARGV[0];

if (!defined($fileName))
{
    die("No filename given");
}

my $image = new Image::Magick;

my $t = 0;    # count turquoise pixels
my $w = 0;    # count white pixels

$image->Read($fileName);

my $height = $image->Get('height');
my $width  = $image->Get('width');

my $total_pixels = $width * $height;

# loop around every row
for my $x (1 .. $height)
{
    # loop around every pixel on this row
    for my $y (1 .. $width)
    {
        # get color values
        my $pixel = $image->Get("pixel[$x,$y]");
        my @p = split(/,/, $pixel);

        # p[0] is the red val, p[1] is the green val, p[2] is the blue val

        # if white (ish) - check for pixels where RGB are all >87.5% 'on':
        if (($p[0] > 57343) && ($p[1] > 57343) && ($p[2] > 57343))
        {
            $w++;
        }

        # if turquoise - check for green & blue both more than 75% 'on':
        elsif (($p[1] > 49152) && ($p[2] > 49152))
        {
            $t++;
        }
    }
}

say "Total pixel count, $total_pixels";
say "Found $t turquoise pixels, and $w white pixels";

my $pct_ignored = $w / $total_pixels * 100;

say sprintf "%.2f%% of total pixels are white - ignoring", $pct_ignored;

my $not_ignored    = $total_pixels - $w;
my $pct_turquoise = $t / $not_ignored * 100;

say sprintf "%.2f%% of non-white pixels are turquoise", $pct_turquoise;

And here’s the output:

1
2
3
4
Total pixel count, 195210
Found 11806 turquoise pixels, and 139482 white pixels
71.45% of total pixels are white - ignoring
21.19% of non-white pixels are turquoise

Thresholds are entirely arbitrary, all errors are my own.

Comments