Find the centroid of an image and profile

Hi all,

I was wondering if there is any Igor built-in function to find the centroid and profile of an image.

Note that I am using Igo pro 7.

Ann 

Thanks for the information and tools. 

Seems like the last two packages throw error messages when I try to use them on my machine. Notice that I am using mac OS and Igor version 7.

 

Ann

The code was generated for IP 8.

I am glad to help troubleshoot the two packages off-line, but you must update Igor Pro. Alternatively, someone here may provide a "quick and dirty" approach to solve your need, especially if this is just a one-off analysis case.

As to finding the center, based on your starting assumptions about the profile shape, use the WaveStats command to find the maximum intensity.

Thank you so much. Maybe the problem is that I am using Igor version 7.

I am sorry to inform you that Igor doesn't allow me to update my version 7 to 8. If I want to do that, I will need to pay extra money for that which I don't wanna right now.

Do you have anything that is compatible with version 7?

 

Thanks,

Ann

 

 

Hello Ann,

I recommend updating your version of Igor when it is possible. 

If you are using IP7 or earlier you can use the ImageAnalyzeParticles operation.  This will require that you first threshold your image to convert it from grayscale to binary with values of 0 designating the "particle" in question.  Use the operation with the /E flag and the stats keyword.  This will produce the M_Moments wave that contains the relevant information (see the documentation for details).

I hope this helps,

A.G.

Your problem sounds relatively simple, especially if your intensity profile is close to a simple Gaussian. Could you attach a sample image?

In reply to by olelytken

Yes, it is nearly a Gaussian beam. 

 

Unfortunately, I can not add the image here, the forum does not give me to choose that. I don't know why it is like that.  

 

Thanks!

  Ann

Why not simply select the peak with cursors and fit Gauss2D? I tried and it works, using Igor GUI, just fine. The only trick is to add cursors to image which define leftTop and rightBottom corners of square covering the peak. 

As result you get center position as well as Gauss peak parameters. 

A 2D Gaussian is not really appropriate as you can see from the attached plot.

gizmo0.png (164.26 KB)

It might help if you provided more information about your application. 

Generally speaking, without some processing you can fit the data to a radially symmetric user function.  The fit can give you estimates for the center and width of the peak.  However, having looked at the image using ImageLineProfile (IP9) I can see that there is actually a 2D Gaussian-like structure away from the peak.  I do not know if that is significant/interesting in your application.

In reply to by Igor

The secondary peak is not a matter of interest in my case.

I was trying to make a model of a particle distribution function that will represent the particles in the image.

 

Thank you so much.

Ann

There is no built in function in Igor 7 (or up to 9 for that matter) which would do this directly. There are tools where some of us wrote code which does this or similar stuff (my Nika internally also has code which does this) and it is quite involved.  It may be easier to install Igor 9 as demo and run the "radial profiler package" mentioned above. Everything else I can imagine seems quite challenging. 

Once you have the center it's pretty easy to extract the radial distribution function. Fitting a 2D Gaussian may give you a good enough center to use to extract a radial distribution function.

If you need to extract both the center and radial distribution for a completely unknown distribution, things get a little more complicated. I remember an old post Fit concentric rings | Igor Pro by WaveMetrics where I came up with a code snippet to fit the center and radial distribution function of a diffraction image (concentric rings). You could use the same approach here, but it might be overkill.

Basically you guess a center and extract the radial distribution using that center. You then recreate the image using your extracted radial distribution and write a your own fit function trying to optimize the x,y position of the center to get the best match between the original image and the recreated image.

I had a look at your data. The noise is extremely low, so I don't think you have to worry about fitting the center position. You can just take the highest data point as jjweimer suggested and calculate the radial profile from that. That's easily done. The code below is an example of that.

Function/WAVE CreateRadialProfileFromImage(ImageWave, CenterX, CenterY)
//  Extracts the radial profile of the image for the center coordinates given
//  X and Y scaling of image must both be 1
Wave ImageWave
Variable CenterX, CenterY

    //  Calculates the size of the image
    Variable ImageXSize=DimSize(ImageWave, 0)
    Variable ImageYSize=DimSize(ImageWave, 1)
   
    //  Calculates the necessary length of the radial profile wave as the distance from the center to the furthest corner of the image
    Variable MaxCenterToCorner=sqrt((Max(CenterX, ImageXSize-CenterX-1))^2+(Max(CenterY, ImageYSize-CenterY-1))^2)
   
    //  Creates the waves to hold the radial profile
    Make/O/N=(Round(MaxCenterToCorner)+2) root:ProfileFromImage/WAVE=ProfileFromImage
    Make/O/FREE/N=(Round(MaxCenterToCorner)+2) ProfileFromImageWeight
    FastOP ProfileFromImage=0
    FastOP ProfileFromImageWeight=0

    //  Adds each data point in the image to the radial profile one at a time
    Variable i=0, ii=0, RadialPos=0, RadialPos1=0, RadialPos2=0
    for (i=0; i<ImageXSize; i+=1)
        for (ii=0; ii<ImageYSize; ii+=1)
            RadialPos=sqrt((i-CenterX)^2+(ii-CenterY)^2)
           
            //  The value of the point will be split between the two closest points in the radial profile wave
            RadialPos1=Floor(RadialPos)
            RadialPos2=Ceil(RadialPos)
           
            ProfileFromImageWeight[RadialPos1]+=1-(RadialPos-RadialPos1)
            ProfileFromImageWeight[RadialPos2]+=(RadialPos-RadialPos1)
           
            ProfileFromImage[RadialPos1]+=ImageWave[i][ii]*(1-(RadialPos-RadialPos1))
            ProfileFromImage[RadialPos2]+=ImageWave[i][ii]*(RadialPos-RadialPos1)
        endfor
    endfor
   
    //  Normalizes the radial profile with the number of image points added to each radial profile point
    ProfileFromImage=ProfileFromImage/ProfileFromImageWeight

    //  Returns the created profile
    Return ProfileFromImage
end

 

This is the result of that. The cursor shows the highest data point. That looks like a pretty good center to me.

In reply to by olelytken

Thanks, Olelytken, and others for your answers and suggestions. I played with the code, anyways am a little bit confused about dividing ProfileFromImage by ProfileFromImageWeight.

Ann

     

Let's say you have a pixel in the image at a distance 4.3 from the center and your radial distribution wave has an x step size of 1, that places the pixel between point 4 and point 5.

To account for that 70% of the value of the pixel is added to point 4 and 30% to point 5 of the radial distribution wave.

In that way each pixel in the image is added to the radial distribution wave. That's the for loop.

In the end each point in the radial distribution wave will now have a different number of pixels contributing to them. To correct for this each point is divided by the number of pixels that have contributed to it (the weight wave).

The radial distribution wave now has the value a pixel that distance from the center should have (In this case it is not the total integrated intensity).

To verify it worked correctly you can place a cursor in the image (Ctrl+I) and confirm the value in the radial distribution wave matches the value of the pixels that distance from the center.

This will allow you recreate the image from the radial distribution wave:

MultiThread ​​​​​​​ImageWave[][]=ProfileFromImage(Sqrt((x-CenterX)^2+(y-CenterY)^2))

 

Thank you for the clarification, got it.

One question, how can I know the pixel value? The image is a 2D wave, if I place the cursor on the image using Crtrl+I, it seems like the value in the radial distribution wave does match the pixel value. 

Ann

When you place the cursor on the image you will see an x, y and z value below the image. The z value is the value of the pixel the cursor is placed on.

The value of a pixel in the image a distance of 5 from the center should have, on average, the same value as the point in the radial distribution wave at an x value of 5.