Counting birds problem

Dear all,

I have several thousand images and I want to count the number of birds in them. 10 cameras were sited at 10 farms and they took pictures of birds scrounging off cattle feed every 5 minutes for 6 days between 0700 and 1700. The birds are dark brown and the cattle feed is light brown. Since the ambient lighting varies through the day, I am struggling to extract particle counts of birds using a batch process involving thresholding.

A colleague suggested I subtract each image from the previous image in order to more easily identify birds, compared to colour thresholding. This seems to work pretty well and I am able to extract a reasonably accurate count by comparing two pictures. However… I would like to automate this process to work on all pairs of images that are temporally adjacent in a specific folder.

I would like to be able to:

  1. Take my stack of images and use it to produce a new stack of images that only show the differences between adjacent images in the original stack. (similar to Process>Image Calculator>Subtract)
    2.Turn each of these RGB image into a binary 8-bit B&W image.
  2. Set minimum and maximum particle size (necessary to adjust since particle size varies between farms depending on how far away the camera was from the birds in the target area).
  3. Output a list of the new image names/locations and the particle count for each image. I don’t need to know exactly where each particle/bird was so I don’t want a huge spreadsheet of coordinates, but having the ability to compare my new stack with the original stack would be nice for validating counts.

I am very new to image analysis, and I’m struggling to find a macro/plugin that will do this. Any help would be very much appreciated!

Many thanks, Richard

Hi Richard,

You could try to run the following script to answer your first question:

# @ImageJ ij

import glob
from jarray import array

path = "/path/to/your/images/*"
files = glob.glob(path)

liste = []
for file1, file2 in zip(files[:-1], files[1:]):
	img1 = ij.io().open(file1)
	img1_32 = ij.op().convert().float32(img1)
	img2 = ij.io().open(file1)
	img2_32 = ij.op().convert().float32(img2)	
	result = ij.op().math().subtract(img1_32, img2_32)
	liste.append(result)
stack = ij.op().transform().stackView(liste)

For your second question you could use the difference of gaussian and then adjust the sigma (not sure what your image look like though…):

from net.imglib2.algorithm.dog import DogDetection 

# FIND PEAKS
# sigmaSmaller ==> Size of the smaller dots (in pixels)
# sigmaLarger ==> Size of the bigger dots (in pixels)
# minPeakValue ==> Intensity above which to look for dots

calibration = [1.0 for i in range(ip1_1.numDimensions())]
sigmaSmaller = 3 
sigmaLarger = 15 
extremaType = DogDetection.ExtremaType.MINIMA  
minPeakValue = 500 
normalizedMinPeakValue = False  

dog = DogDetection(ip1E, ip1_1, calibration, sigmaSmaller, sigmaLarger,  
  				   extremaType, minPeakValue, normalizedMinPeakValue)

peaks = dog.getPeaks() 

you could also use:

dog = ij.op().filter().dog(imageToProcess, sigma1, sigma2)

For your last question the peaks variable will hold the position of the peak.

To know the number you can use:

len(peaks)

Note that everything is in Python.

Let me know if that help, I didn’t have a chance to test it.
Cedric

Wow, Thanks Cedric!

I’ll try this today and let you know how I get on.

Many thanks!
Richard