Adobe Photoshop CS5’s Content aware fill, and why the hype is just hype.

April 20, 2010 at 7:58 pm

As a photographer, I often get angry at the level of photo-manipulation that is performed on photographs to make them look better.  I also get angry when it comes to cliques of people who all take bad photographs, but who en masse, believe that the fact so many others do it, makes it good photography, or even, god forbid, art.

Lomographers, I’m looking at you.

I’m not a professional photographer, and I don’t claim to be.  My grandfather was a professional photographer, however, and as such I treat the profession with a great deal of respect; that being the people who are accredited within the profession - i.e. BIPP Licentiates, Associates and Fellows.
I don’t have much respect for rank amateurs with 2 or 3 digital cameras, several 8GB CF cards, and the view that happy-snapping 3000 ‘candid’ photographs during someone’s wedding will result in at least one or two good photographs that the client will like.
After all, years of rants from a professional photographer (who would maybe shoot 2-3 rolls of 120 at a wedding, and have 2-3 rolls of perfect imagery at the end of it) about amateurs tends to give you certain views on things.

As such, when Adobe released the pre-launch videos of “Content Aware Fill” in action, it gave me the taste of bile in the back of my throat, and a feeling that as a whole, we were taking yet another step towards the brink of no creativity whatsoever.  Take 1000 photographs, find a couple that came out semi-ok, and then content-aware-fill them to make them perfect; instead of spending time being creative, and taking two or three good photographs to begin with.

Today, I finally got my hands on a copy of Photoshop CS5, and was able to run a couple of my own photographs through it, to see just what this hype was all about.  What follows are the results.

The image below was taken moments after a storm passed, and a gap appeared in the clouds revealing the most amazing rays of sun.  I love sky photography, when it’s interesting.  While framing this shot, I had to make a judgement call about whether to include the near-horizon [with the lamp-post], or, to crop much of the sky and foreground out with a longer focal length.  I’m not a fan of removing things [except blemishes from dust, etc. on lenses] from photographs after the fact, and would much rather just scrap a photograph entirely if when I get it onto the laptop, I find an aspect that would require surgery to fix isn’t to my liking.
I’m quite satisfied with the outcome of the photograph below, but, I think it’s a perfect candidate for the new Content Aware Fill.

Sky, Before CAF
Camera: Canon EOS 30D - Exposure: 1/160 - Aperture: f/11 - Focal Length: 18mm - ISO: 160

At first, I tried using the Spot Healing Brush Tool (keyboard shortcut J), set to Content Aware mode.  The outcome was not at all what I expected, and in fact, worse than if I’d use the clone tool to manually fill that area.  Note the shift downwards, of the silhouetted bushes, and the hard blurring into the sky.

Sky, After CAF

After trying that a few times in different places, with similar results, I decided to give the select-delete-content-aware-fill method a try.  In this, you just use the marquee tool (M), to select an area, then hit the delete key, which will then trigger it asking you how you’d like it filled.  Choose content-aware, and await the horrendous results:

After CAF-2

I gotta say, so far, I’m completely unimpressed by this new ‘feature’.  I’m doing everything exactly the same as they did on the hype-videos, and the effect I’m getting is completely different.

I will admit, the first time a friend linked me to the video showing Content-Aware-Fill in action, and asked for my response, it was one of both complete anger, combined with wondering whether this would make it possible to easily create that Matrix effect of lips being sealed together into nothingness.  I have to say, it succeeds quite well at that:

If he was born like this, the UK would be a better place.
Public domain image from Wikipedia Commons

So, there we have it… if you’re a satirist, Content Aware Fill is likely for you.  If you’re a photochopper of images, you can probably get better results the old fashioned way.  I did look through the preferences for CS5, but couldn’t find anything related to content-aware-fill… so I’d be happy to hear from anyone who actually managed to get it to work.

An open letter to Lord Carter of Barnes

January 30, 2009 at 8:59 pm

After reading http://www.theregister.co.uk/2009/01/29/carter_net_neut/ and http://www.theregister.co.uk/2009/01/30/isp_carter_music_policing/, I got a sudden urge to write to the idiot that is promoting this stuff:

Lord Carter of Barnes
House of Lords
London
SW1A 0PW

Re: Your quaint ideas about the internet

Dear Lord Carter of Barnes,

On behalf of everyone who actually understands The Internet (it’s not actually a series of tubes), those who oppose dictatorship in its many forms, and the fair people who don’t have their head stuck so far up the outmoded, antediluvian and superannuated backsides of the music industry that they can no longer see sense; I would like to respectfully say ‘Fuck you, and the horse you rode in on’.

Consider this: you are attempting to push laws through to support an industry that is flailing around in its death throes. You are also going to be solely responsible for putting the United Kingdom on a par with China in terms of Internet freedom; or lack thereof.
I realise you have no problem sleeping at night while considering pushing for these things to happen; with respect however, I believe your ability to sleep at night is merely because you are so out of touch with reality that you shouldn’t really be in charge of your own sleeping arrangements.

Milord, I put it to you that perhaps you should ask your children (or if you don’t have any, someone elses children; and at that, children who actually have used the internet) to explain to you the freedoms that the internet gives people in an already heavily oppressed society; and why enforcing ridiculous laws undermine its very nature and cast questions on the very possibility of any further technological advancement on these shores.
Do you really want the legacy you are remembered for throughout history to be as the man who wasn’t strong enough to see sense or find the truth, and let a dying business ruin the future for generations of people?

Yours, very sincerely and respectfully

MacBook tanka

December 22, 2008 at 11:42 am

It is a design feature;
Steve Jobs collects the souls;
So cutting peoples wrists on the MacBooks;
Means quicker soul harvesting.

Also, I need a sticker for my new MacBook… one which reads “Built from aluminum tempered with the charred, crushed skulls of pretentious mac users

Monitoring your network with nmap

December 15, 2008 at 10:56 pm

This all came about while I was pondering the best way to dump an overview of what was sat on my network in the datacenter; the main reason being a lack of useful documentation telling me what IPs were in use to narrow it down at all. The idea was that it’d dump in CSV format something along the lines of:

IP,TCP Ports
10.0.0.1,22 143 5000 12345 31337

Of course, once I had this data, my mind started down the path of ‘wouldn’t it be nice to have an automated system that would e-mail me and tell me if any ports change (read: “if any developers set something up without my knowledge”), and also tell me if any hosts are added to our network.  I present to you an automated network monitoring script, this will scan your network and send you a detailed report (with port probing), via a direct SMTP connection to your remote mail server - which is useful in the event that your network gets compromised and you can no longer trust any binaries.  All that you need to do is put it somewhere, make it executable, and add it to a cronjob - mine runs hourly, but I’m paranoid.

0 */1 * * * /root/bin/nmap.pl auto >/dev/null 2>&1

The e-mails look something similar to this:

Nmap Scan Report. Hosts/Ports changed!
Generated on: 2008-12-08 18:39:44

——–BEGIN——–
10.0.0.1 is a new host with 3 ports open/filtered.

10.0.0.1 has these ports open: 22,111,5000
22 might be ssh
111 might be rpcbind
5000 might be vtun
——–END——–

Creative Commons LicenseAll code that I’ve written is licensed under the Creative Commons Attribution-Non-Commercial-Share Alike 2.0 UK: England & Wales Licence.  Where non-commercial means don’t sell it, not ‘you can’t use it in your company’. =]

?Download nmap.pl
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#!/usr/bin/perl
use File::Copy;
use Nmap::Parser;
use Net::DNS::Sendmail;
use warnings;
use strict;
 
#config begin
my $nmap_path = "/usr/bin/nmap"; #path to nmap binary
my $nmap_args = "-T5 -F -sV"; #nmap arguments (accepts multiple), do not specify any output arguments!
my $ips = ""; #networks to scan, accepts standard nmap input
my $save_as = "/root/parser-cache.xml"; #path to storage file - this file is used for comparative scans, so it's best not to place it in /tmp.
my $email_from_address = ''; #from address to use when sending mail - should probably exist to avoid sender callouts
my $email_to_address = ''; #address you want results delivered to
my $email_sender_domain = ''; #domain to masquerade as - useful in cases where remote mta checks helo.
my $email_subject = "Nmap Network Scan Results"; #subject for email.
my $debug = "false"; #enables some output if you need to test auto on the cli - i.e. why mail isn't being sent.
#config end
 
my $np = new Nmap::Parser;
my $old = new Nmap::Parser;
my $curr = new Nmap::Parser;
my $tempstore = "/tmp/parser-cache.tmp";
my $emailfile = "/tmp/nmap-notify";
my $newmachines = 0;
my $auto = (lc($ARGV[0]) eq "auto");
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
 
sub debug
{
    print "@_\n" if($debug eq "true");
}
 
sub print_twice
{
    print "@_";
    print EMAIL "@_";
}
 
sub create_files
{
    foreach (@_)
        {
            if(!-e $_)
                {
                    print "$_ does not exist... creating\n" if(!$auto);
                    open(TEMP,">$_") or die "Can't create $_: $!";
                    close(TEMP) or die "Couldn't close $_: $!";
                }
        }
}
 
create_files($save_as,$tempstore);
 
if($auto)
{
    open(EMAIL,">$emailfile") or die "Can't create $emailfile: $!";
    print EMAIL "Nmap Scan Report.  Hosts/Ports changed!\nGenerated on: ";
    printf EMAIL "%4d-%02d-%02d %02d:%02d:%02d\n\n",$year+1900,$mon+1,$mday,$hour,$min,$sec;
    print EMAIL "--------BEGIN--------\n";
}
 
if($auto)
{
    debug("Running auto mode");
 
    if(-s $save_as)
    {
        $old->parsefile($save_as); #load previous state
        $curr->cache_scan($tempstore); #set temporary file to store xml after we're done
        $curr->parsescan($nmap_path, $nmap_args, $ips); #scan current hosts
 
        for my $ip ($curr->get_ips('up'))
        {
            my $ip_old = $old->get_host($ip);
            my $ip_curr = $curr->get_host($ip);
            my @alltcp = $ip_curr->tcp_open_ports();
            my $numtcp = $#alltcp + 1;
            if(!$ip_old)
            {
                print_twice("$ip is a new host with".$numtcp."ports open/filtered.\n");
                ++$newmachines;
            }
        }
 
        print_twice("\n") if($newmachines != 0);
 
        for my $ip ($curr->get_ips('up'))
        {
            my $ip_old = $old->get_host($ip);
            my $ip_curr = $curr->get_host($ip);
            my %port = ();
 
            if($ip_old)
            {
                my @tcpdiff = grep { $port{$_} < 2}
                                    (map {$port{$_}++; $_}
                                    ( $ip_curr->tcp_open_ports , $ip_old->tcp_open_ports));
 
                if(scalar @tcpdiff)
                {
                    print_twice("$ip has these new ports open: ".join(',',@tcpdiff)."\n");
                    for (@tcpdiff)
                    {
                        print_twice("\t"."$_ might be ",$ip_curr->tcp_service($_)->name,"\n");
                    }
                    print_twice("\n");
                }
            }else{
                my @tcp = (map {$port{$_}++; $_}
                            ( $ip_curr->tcp_ports('open') ));
 
                if(scalar @tcp)
                {
                    print_twice("$ip has these ports open: ".join(',',@tcp)."\n");
                    for (@tcp)
                    {
                        print_twice("\t"."$_ might be ",$ip_curr->tcp_service($_)->name,"\n");
                    }
                    print_twice("\n");
                }
            }
        }
    }else{
        $curr->cache_scan($tempstore); #set temporary file to store xml after we're done
        $curr->parsescan($nmap_path, $nmap_args, $ips); #scan current hosts
 
        for my $ip ($curr->get_ips('up'))
        {
            my $ip_curr = $curr->get_host($ip);
            my @alltcp = $ip_curr->tcp_open_ports();
            my $numtcp = $#alltcp + 1;
            print_twice("$ip is a new host with ".$numtcp." ports open/filtered.\n");
            ++$newmachines;
        }
 
        print_twice("\n") if($newmachines != 0);
 
        for my $ip ($curr->get_ips('up'))
        {
            my $ip_curr = $curr->get_host($ip);
            my %port = ();
 
            my @tcp = (map {$port{$_}++; $_}
                      ( $ip_curr->tcp_ports('open') ));
 
            if(scalar @tcp)
            {
                print_twice("$ip has these ports open: ".join(',',@tcp)."\n");
 
                for (@tcp)
                {
                    print_twice("\t"."$_ might be ",$ip_curr->tcp_service($_)->name,"\n");
                }
 
                print_twice("\n");
            }
        }
    }
    move($tempstore, $save_as);
    print EMAIL "--------END--------";
    close EMAIL;
 
    open(EMAIL,"<$emailfile") or die "Can't read $emailfile: $!";
    my $mail = Net::DNS::Sendmail->new();
    $mail->verbose() if($debug eq "true");
    $mail->senderdomain( "$email_sender_domain" );
    $mail->to( "$email_to_address" );
    $mail->from( "$email_from_address" );
    $mail->subject( "$email_subject" );
    while () { $mail->data($_); }
    $mail->sendmail() if($newmachines != 0);
    debug("mail sent");
    close EMAIL;
} else {
    #Unsure whether or not to move the output of this into $save_as... it may
    #be that someone runs this, and doesn't take care of the output, in which
    #case, we still want to be notified that night.
    $np->cache_scan($save_as);
    $np->parsescan($nmap_path, $nmap_args, $ips);
    print "IP,OPEN TCP PORTS\n";
    for my $ip ($np->get_ips('up'))
    {
        my $ip_check = $np->get_host($ip);
        my %port = ();
 
        my @tcp = (map {$port{$_}++; $_}
                  ( $ip_check->tcp_ports('open') ));
 
        print "$ip,".join(' ',@tcp)."\n" if(scalar @tcp);
    }
}

My little^dHUGE computer

June 12, 2008 at 12:24 am

That title really wasn’t supposed to sound as phallic and egotistical as it appears to be.. it really is huge. No, really, it is. Okay, I’ll stop. Last week, I got my hands on a Dell XPS 730 H2C, and then spent the next day (i kid you not) reinstalling it, and making it function properly. I read many reviews online about it before picking it up, and I believe that some of them were… set up. In all cases, they claim that the machine comes with nothing on it, bar 3dmark06, and that the configuration it ships with is just fine for gameplaying. That really isn’t the case - or perhaps I just have really bad luck; that, or the UK market makes things worse. In any case, having spent a good several hours installing games and other software, I found that most were unplayable - black screens, crashes, slow FPS. Blowing it away was the best, and worst, thing I’ve done thus far. The biggest bone of contention was getting CrossfireX to function afterwards - it’s very new tech, and being ATI, there is zero output from the Catalyst Control Center with regards to crossfire (they decided it would be a good idea to remove the check box for it on HD3870X2 cards).

I discovered, somewhere on the internets that the way to get crossfire functioning correctly is to remove a card, install the driver, reboot, install the second card, reboot, connect the crossfire connector, reboot. It worked. I shit you not. 90FPS in crysis, biotches.

Unfortunately, and here’s where things go downhill entirely, the fan management on this thing is less than adequate. ATI wholeheartedly believe that GPUs don’t need their fans to run while under heavy load; that’s about what I can figure at least - the fans are completely manual, they do not engage automatically. I have to run rivatuner if I don’t want everything to crash horribly with massive graphics corruption.
Dell appear to have followed suit, giving zero control over what the fans are doing, except by way of the nVidia ESA Control Panel, which is pretty awful at controlling anything - except for the LEDs. To top that off, today, 5 minutes into playing Neverwinter Nights 2 -hardly the most intensive game- I leapt from my seat as a nuclear launch sequence kicked in, every fan in the thing went batshit insane, air-raid sirens sounded, the ground shook -okay, so it wasn’t quite like that.. it certainly seemed like that at the time- I bring up the system monitor (thanks nVidia), and find out that my CPUs are hitting 212F (100c for you metric folk), and discover to my horror that the “Front CPU Fan” (read: Radiator Fan - it’s watercooled) is not running, at all. It has been told to run at 100%, but it’s doing absolutely jack shit.

Dell give you a nice tool kit, and a nice pen with a torch/laser built into it; now I know why. I stripped the thing down to re-seat all the wiring for the overly complex cooling setup, and this took me about 45 minutes to do. The radiator itself requires the system to be drained if you want to lift it off the radiator fan to get to the wiring that comes out the back of it, and the control unit for all the cooling/extras sits neatly behind that, a huge air intake and the front drive bays. They also use self-tapping screws into plastic, which is evil if you actually want to be able to put what you take apart back together. The radiator fan is still dicking around, ignoring calls to increase speed by the system from what I can tell through the system monitor, however, it is at least running now, and efficient enough to keep the CPUs at 104F (40c) during normal load. I think perhaps I shall be giving Dell a call at some point to get this fixed properly. It’s a lovely system, looks mean, is mean, plays everything I throw at it at 1680×1050 and max performance settings without even blinking. I’m still unsure whether it’s worth almost $7k though.