# Extracting image value along circle of an image

I want to extract the ImageValue (along yellow circle) of an given below image

I try with the below code to find the ImageValue along the line, but I want to extract and plot the ImageValue along the yellow circle.

        With[{img = image},
Manipulate[
ListLinePlot[ImageValue[img, {All, row}],
PlotRange -> {{100, 350}, {0.1, .71}}], {row, 207, 500 - 0.5, 1}]]

• Interpolation together with a parametrization of the circle & Table should work – Lukas Lang Jun 9 '18 at 20:53
• @Mathe, I am new in Mathematica, Please explore your idea. – praksh Jun 9 '18 at 21:04
• Try to read the documentation pages for the linked symbols, they are very instructive on how to use the functions. The rest is just Maths. Here is something to get you started: Table[Interpolation[data][r {Cos[ϕ]r, Sin[ϕ]}], {ϕ, 0, 2π, π/10}], where data is the data you used for the plot, and r is the radius of the circle – Lukas Lang Jun 9 '18 at 21:08
• @praksh Your question lacks important details that are needed to give an answer. If you ask for the intensity profile of the given image along the yellow circle, then the answer is simple: You have constantly yellow. I'm sure this is not what you want. Please provide example code and edit your question. Additionally, Mathe172 basically answered how you can achieve what you are looking for. – halirutan Jun 10 '18 at 1:30
• OK, it is still not a great question, as I'm still unsure what you really want. If you extract the image-data exactly along the yellow line, you will get a constantly yellow color or (since you turned it into a gray image) a constant gray value. I would guess you are interested in the values along a circle that is placed in the symmetry-center of the underlying data, but again, I'm not sure. Question: Do you have only the image or do you have also the data that was used in the density plot? – halirutan Jun 10 '18 at 9:19

Here is my go on the question. You need to import the image and then use ImageData to get the pixel matrix. When you want to plot a column or row of the image only, you can simply extract a column or row of the pixel matrix. A circle is a bit different because you don't hit exact pixel positions on your way along the circular path.

That is the reason you need to interpolate the data. Another good thing with interpolation is that you can specify the range of your data. If you use {{-1,1},{-1,1}} then your interpolated data will have the center of your image directly at {0,0}. The parametric formula for a circle around {0,0} with radius r is

$$\{r\cdot\cos\phi, r\cdot\sin\phi\}$$

and this is what we will use to extract the data along the circular path. Here is a simple demonstration:

Manipulate[
ParametricPlot[r*{Cos[phi], Sin[phi]}, {phi, 0, 2 Pi},
PlotRange -> {{-1, 1}, {-1, 1}}],
{r, 0.01, 1}
]


If you interpolate your data like I will do, r can range from $0<r<=1$. Here we go:

img = ColorConvert[Import["https://i.stack.imgur.com/3RpmA.jpg"], "Grayscale"];
data = ImageData[img];
ip = ListInterpolation[data, {{-1, 1}, {-1, 1}}];


The next function will give you n data-points along the circle with radius r

circleData[r_, n_Integer] := Table[ip @@ (r*{Cos[phi], Sin[phi]}),
{phi, 0., 2 Pi, 2 Pi/(n - 1)}];


Quick check if everything works

Manipulate[
ListLinePlot[circleData[r, 200], PlotRange -> {Automatic, {0, 1}}],
{r, .01, 1}
]


It seems r=0.293 is about the radius where your circle goes directly through the smaller gray spots that are in the brighter spots. To get the 512 sampling points along this circle you can therefore use

cData = circleData[0.293, 512];
ListPlot[cData]


# Edit

How to combine ParametricPlot of circle for given r and image? Show[circle,image] is not working.

An easy (but not so fast) way is to directly use the interpolation function ip

Show[
DensityPlot[ip[x, y], {x, -1, 1}, {y, -1, 1},
ColorFunction -> GrayLevel, PlotPoints -> ImageDimensions[img],
MaxRecursion -> 0],
ParametricPlot[.293*{Cos[phi], Sin[phi]}, {phi, 0, 2 Pi},
PlotStyle -> {Dashed, Red}]
]


• Thanks very much @halirutan – praksh Jun 10 '18 at 19:08
• How to combine ParametricPlot of circle for given r and image? Show[circle,image] is not working. – praksh Jun 10 '18 at 19:49
• Please see the edit at the end of my answer. – halirutan Jun 12 '18 at 21:41

This would be one way to do it.

1. Take the image.

img = Import["image_preview.jpeg"]

1. Create a new image of same size with circle.

cen = ImageDimensions[img]/2; rad = 80; img1 = Rasterize[Show[img, Epilog -> {Yellow, Thick, Circle[cen, rad]}]]

1. Locate coordinate for yellow dots and find the ImageValue.

d = 0.01; pts = PixelValuePositions[img1, Yellow, d]; npts = Length[pts] cols = ImageValue[img, #] & /@ pts; Graphics[{RGBColor[cols[[#]]], Point[pts[[#]]]} & /@ Range[npts], PlotRange -> {{0, ImageDimensions[img][[1]]}, {0, ImageDimensions[img][[2]]}}, Frame -> True, FrameTicks -> None]

Increasing d will increase the number of points. This would work for any arbitrary line and colour.

For Grayscale

img = ColorConvert[img, "Grayscale"];
cen = ImageDimensions[img]/2; rad = 80;
img1 = Rasterize[Show[img, Epilog -> {Yellow, Thick, Circle[cen, rad]}]]

d = 0.01;
pts = PixelValuePositions[img1, Yellow, d];
npts = Length[pts]
cols = ImageValue[img, #] & /@ pts;
Graphics[{GrayLevel[cols[[#]]], Point[pts[[#]]]} & /@ Range[npts],
PlotRange -> {{0, ImageDimensions[img][[1]]}, {0,ImageDimensions[img][[2]]}},
Frame -> True, FrameTicks -> None]

data=Join[pts[[#]], {cols[[#]]}] & /@ Range[npts];
ListPointPlot3D[data]


• Thanks@ sumit, As you can see intensity or pixel value in not constant each points on the circle, How to plot according to their pixel value just like in line profile. – praksh Jun 10 '18 at 13:24
• You can increase d, then it will pick both yellow and yellowish points. The 3d point plot I get looks similar to yours. So increasing d you may get what you are looking for. – Sumit Jun 10 '18 at 13:35

You can use CirclePoints[center, r, n] to get n points along a circle around center with radius r, and then ImageValue[img, circlePoints] to get the interpolated image value at these points. This returns a list of RGB values for each pixel. Use [[All,1]] to show only the Red channel:

img = Import["https://i.stack.imgur.com/I3mo6.png"]

center = ImageDimensions[img]/2;
r = 100;

circlePoints = CirclePoints[center, r, 360];
rgb = ImageValue[img, circlePoints];
red = rgb[[All, 1]];

Row[{
Show[img, Graphics[{Yellow, Line[circlePts]}]],
ListLinePlot[red, ImageSize -> 500]
}]


ImageValue is quite fast, so you can even use this dynamically:

Row[{
VerticalSlider[Dynamic[r], {0, 200}],
LocatorPane[Dynamic[center],
Dynamic[Show[img, Graphics[{Yellow, Circle[center, r]}]]]],
Dynamic[
ListLinePlot[
ImageValue[img, CirclePoints[center, r, 360]][[All, 1]],
ImageSize -> 500]]
}]


Here you can change the radius and center and see the change in real time: