Find the centroid of an image and profile
Ann
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
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
The radial profiler package could do as a good start for what you need. See the discussions and packages at the links below.
https://www.wavemetrics.com/code-snippet/radial-profiler
https://www.wavemetrics.com/node/21289
https://www.wavemetrics.com/node/21002
Alternatively, I am certain also that others on this forum as well as at Wavemetrics can give good recommendations for a "do your own code" approach.
August 15, 2022 at 12:37 pm - Permalink
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
August 15, 2022 at 01:17 pm - Permalink
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.
August 15, 2022 at 02:54 pm - Permalink
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
August 16, 2022 at 08:40 am - Permalink
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.
August 16, 2022 at 09:58 am - Permalink
Your problem sounds relatively simple, especially if your intensity profile is close to a simple Gaussian. Could you attach a sample image?
August 16, 2022 at 10:21 am - Permalink
In reply to Your problem sounds… 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
August 16, 2022 at 10:43 am - Permalink
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.
August 16, 2022 at 11:44 am - Permalink
A 2D Gaussian is not really appropriate as you can see from the attached plot.
August 16, 2022 at 11:57 am - Permalink
In reply to Why not simply select the… by ilavsky
I tried t 2D but it doesn't exactly describe the distribution. Also, I was looking for radial distribution function. Anyways, thank you so much.
August 16, 2022 at 12:03 pm - Permalink
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.
August 16, 2022 at 12:15 pm - Permalink
In reply to It might help if you… 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
August 16, 2022 at 12:36 pm - Permalink
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.
August 16, 2022 at 12:58 pm - Permalink
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.
August 16, 2022 at 10:15 pm - Permalink
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.
// 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
August 17, 2022 at 02:05 am - Permalink
This is the result of that. The cursor shows the highest data point. That looks like a pretty good center to me.
August 17, 2022 at 02:17 am - Permalink
In reply to I had a look at your data… 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
August 22, 2022 at 07:14 am - Permalink
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.
August 22, 2022 at 07:43 am - Permalink
This will allow you recreate the image from the radial distribution wave:
MultiThread ImageWave[][]=ProfileFromImage(Sqrt((x-CenterX)^2+(y-CenterY)^2))
August 22, 2022 at 07:50 am - Permalink
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
August 22, 2022 at 09:07 am - Permalink
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.
August 22, 2022 at 10:12 am - Permalink