in reply to Re: pixel counting
in thread pixel counting

Yup - quite nonrectangular - the initial images will look somewhat like this - although larger and more diverse (and if ya wanna know what all of that stuff is, msg me and I'll be happy to talk about it)- and I would like to be able to select and cut out the portion of the photo that pertain to each species, dump them in a seperate file (I was thinking transparent gif or png, so the only pixels are those that are from the species), then I'd like to run a script that counts the total number of pixels taken up by the selection.

So, in really ugly psuedocode
my $referencepixels=countpixels($referencefile); @data=ls($datadir) foreach my $file (@data){ my $cover=countpixels($file)/$referencepixels; $datahash{$file}=$cover; } output_to_datafile(%datahash);

Replies are listed 'Best First'.
Re: pixel counting on a fouling panel
by Arguile (Hermit) on Jun 09, 2003 at 01:09 UTC

    This is untested; just going from memory and a quick look at the Image::Magick API Reference. Basically it should read in the image, figure out which colour is transparent, then loop through every pixel and increment a counter when the pixel isn’t transparent. Again, it’s untested. I’m unsure if the pixel index starts at 1 (as I used) or 0. I’m also not totally sure on the $image->Get('transparent') call -- read the API for the exact method -- it’s been a while since I've used it. This should give you a good jumping off point though.

    use Image::Magick; my $image = new Image::Magick; $image->Read('foo.png'); my $count; # The number of non-tra +nsparent pixels. my $transparent = $image->Get('transparent'); # Index of the transpar +ent colour. my $height = $image->Get('height'); # Image height. my $width = $image->Get('width'); # Image width. for my $x ( 1 .. $height ) { for my $y ( 1 .. $width ) { $count++ if $image->Get("pixel[$x,$y]") != $transparent; } }

    If I get what you're trying to do, it might be beneficial to store each species as a mask. If you save it as a black and white bitmap counting becomes really fast, since you can read the file as one long binary string and just count the 1’s.

    Another possibility (again I’m assuming you're generating these masks by hand) is to use a format that allows multiple layers. Storing the image as a photoshop PSD or something similar would allow you to keep all the masks as named channels or layers. The Gimp might be a great tool here as it allows Perl extensions and has said layers. This way the masks stay embedded right in the original image for easy archiving, and you could even store the result of those counts in the image comments. With a little Perl magic, Gimp could become a biology workdesk :).

      Fantastic - thanks! Unfortunately, I can follow neither of your two above suggestions, although don't think I haven't contemplated it. Unfortunately a variety of the species involved have multiple color morphs, or are exactly the same color as another species (I mean you have to zoom in on individual zooids in a colony to tell the difference- hence we're using a high-res digital underwater camera).

      Saving different layers in a PSD would be nice, but the problem there is that often we have species overgrowing each other in a non-lethal way (e.g. a colonial sea squirt overgrows a mussel. Both live, and both need to be counted). The current scheme I'm going with is copying the area of each species, putting it into its own .gif, and using some filename information for the final data file.

      Although if you know a way to do all of that in GIMP, I'd love to hear it!

        As requested in CB, some clarification...

        From what you’ve said you’ll be hand drawing outlines of what you believe to be the extent of each species boundry; even if another species happens to be overgrowing that boundry to some extent. In this case you’ll be guessing the exact extent and copying that whole area into a new image.

        What I propose is creating a layer or channel** for each species in the image. So for each species:

        1. Create a layer or channel
        2. Turn on their layer (to around 50% transparency so you can see the image underneath)
        3. Use a paintbrush to mask the areas you think they exist in, even if partially covered by another species.
        4. Turn off the layer.

        This will essentially give you a one bit mask that represents the living area of each species. The layers can all overlap without interfering with each other. In addition all the data is stored in one file, easy to keep track of or change.

        This could also work very well for quick visual surveys if you wanted to get fancy. Assign each species-layer a colour and then turn the ones of interest on with a high transparency. You’ll see a montage of interacting colour representative of that species living areas and their overlaps.

        Anyways, enough talk. On to some code!

        use Gimp qw(:auto); use Gimp::Fu; # ... my @species = qw( mussels squid octocerata ); # Our species of intere +st. # Create a layer for each species (labelled for that species) and add +it to # the image. foreach my $specie ( @species ) { my $layer = gimp_layer_new( $img, $w, $h, RGB, $specie, 50, NORMAL +_MODE); gimp_image_add_layer($layer, -1); } # ...

        Adding a zillion layers (one for each specie) to each image would be boring manual work (colouring will be boring enough), so in the above partial snippet we let a Gimp script do that for us. In production you’d probably pull this from a file or database. Anything else you'd normally do to preprocess the image could be done here as well, for example autolevels or auto contrast.

        It’s late, so I think I’ll stop here. For now I’ll leave you with some reference material to look over.

        See Also:


        ** Layers and channels are different, which you use will depend on exactly what you want to do with it. If all you need is a one bit mask then channels would be your best choice. For simplicity sake I’ll refer to the choice as layers throughout the post.

        *** Spiffy title eh? :)

Re: pixel counting on a fouling panel
by BrowserUk (Patriarch) on Jun 09, 2003 at 03:53 UTC

    That's what I figured. Have you decided yet how (ie. what tools. I can see the process will probably need to be manual) you are to use to create the cut-outs?


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller


      Oh, it's a manual process given the complexity of species identification, etc.

        Yes. I can understand that, but I meant what utility will the person selecting the cut-out use to select the odd shape and produce the resultant gif with its transparent background?

        Or will this be done by cutting up prints and then rescanning the pieces?


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller