Circle Finder


Circles are a notable class of feature in many images. This ImageJ macro provides a filter which assists in finding circles of a particular size (either hollow or filled) in an image. After filtering the centres of circles are bright spots.


//Circle finder
//This macro lets you automatically find circles in an image.
//It performs a set of image filters which convert regions in the
//image which are similar to a circle of the expected size into
//bright spots at the centre of the circle.
//Combine with a "Find Maxima..." search to identify circle centres.

//Global variables
var radius=10;
var inverted=false;
var filled=true;
var slices=true;
var diameter=2*round(radius)+1;

//The main macro
macro "Find Circles" {
    //Create and show the user input dialog
    Dialog.create("Find Circles");
        //Expected circle radius to search for
        //Diameter is derived from 2*round(radius)+1 (diameter must be odd)
        Dialog.addNumber("Expected radius: ", radius, 0, 5, "px");
        //Whether or not to invert the image for analysis
        //The macro searches for light circles on a dark background
        Dialog.addCheckbox("Invert image", inverted);
        //Whether or not to search for filled circles
        //The macro will find filled or hollow circles, but specifying it to expect hollow circles improves the results
        Dialog.addCheckbox("Find filled circles", filled);
        //Whether or not to process all slices
        if (nSlices()!=1) {
            Dialog.addCheckbox("Process all slices", slices);
        if (nSlices()!=1) {
    //Derive the diameter to search for

    //If RGB then convert to 8-bit for analysis
    if (bitDepth()==24) {
    //Pick a good value for maximum image value for image inversion
    if (bitDepth()==32) {
    } else {
        max=pow(2, bitDepth())-1;

    //Derive the slice range to analyse
    if (nSlices==1) {
    } else {
        if (slices==true) {
        } else {

    for (i=startSlice; i<=endSlice; i++) {
        //Invert (if selected)
        if (inverted==true) {
            run("Macro...", "code=[v="+max+"-v] slice");
        //Find edges in the image prior to analysis (if optimised to also find filled circles)
        if (filled==true) {
            run("Find Edges", "slice");
        //Find circles in the image

//Function to generate and apply a circle shaped kernel
//The diameter must be odd and greater than zero, very large diameters are slow
function circleKernel(diameter) {
    //Make an image to generate the kernel pattern in
    newImage("Kernel", "8-bit Black", diameter, diameter, 1);
    //And make a hollow circle 1px in thickness with a value of one
    makeOval(0, 0, diameter, diameter);
    makeOval(1, 1, diameter-2, diameter-2);
    run("Select None");
    setMinAndMax(0, 1);

    //Record the kernel by reading the image values to a 2D array
    for (x=0; x<diameter; x++) {
        for (y=0; y<diameter; y++) {
            kernel[x+y*diameter]=getPixel(x, y);
            kernelstring+=""+getPixel(x, y)+" ";
    //And close the kernel image

    //Apply the kernel to the image
    run("Convolve...", "text1=["+kernelstring+"] normalize slice");

ImageJ Macros Gallery