8
votes

I am having a (mathematica 8.0.1.0-) problem which I cannot solve by myself. I have measurement data in a matrix, I want to select some of them and then add them up.

To explain my problem better, here an easy example. The data can be produced by a matrix S:

S = Table[ -Sin[i/2] - Sin[j/2], {i,20}, {j,20}];

They can be nicely plotted with:

xmin = N[Min[S]]; 
xmax = N[Max[S]]; 
mycolorfun = Function[ Blend[{Blue,Cyan,Green,Yellow,Red},#] ];

and

MatrixPlot[S, PlotRange -> {All,All,All}, AspectRatio -> 1/1,
   ColorFunction -> (mycolorfun[ Rescale[ #1{xmin,xmax} ] ]&),
   ColorFunctionScaling -> False, MaxPlotPoints -> Automatic,
   FrameLabel -> {y,x} ]

Then one should get a picture similar to this one:

enter image description here

Now I want to select the data which are inside of the brown drawn polygon. These data should be added up at the end.

How can I do this? Ok, I could use rectangles and build a sub-matrix by choosing/guessing good start and end indices. Then I just have to build the sum of this sub-matrix. But I would prefer polygons (more precise if we do not argue about little problems with the matrix values which are crossed by the line of the polygon). And I would love it if I could select my region of interest (ROI) directly by “painting” the polygon into the Matrix (no more time consuming choosing/guessing of matrix indices).
Could somebody here help me with my problem? If it is not solvable with mathematica, is there some other program which I could use?

I would be very happy about some help and hints!

3
A point of note, the code blocks require a blank line preceding them, so I fixed it for you. I also reformatted the code a bit and hid the link behind clickable text for readability. - rcollyer
Thank you for editing my question! Since I am new here, I had some problems with editing by myself. I try to make it better next time. - partial81
Not a problem. Your new here, and laying out your questions/answers takes practice. - rcollyer
Thank you @belisarius and @rcollyer for editing my text. It is really nice to see that my picture is directly in my post now. That makes it more understandable! - partial81

3 Answers

10
votes

If selecting the area of interest graphically by hand is not a problem, then you could:

First, create an image out of your data, using a visualization which makes it easy for you to select manually afterward:

S = Table[-Sin[i/50.] - Sin[j/50.], {i, 400}, {j, 400}];
img = ReliefImage@S

Then use the Front End Graphic Tools to draw the polygon over the region that interests you (right click mouse button):

enter image description here

Follow by getting the mask that corresponds to your polygon (again, right click button):

enter image description here

Finally, make a binary image out of the mask and use it to recover the sum of the pixel inside the polygon:

Total[S*ImageData@mask, Infinity]

The whole process looks like this:

enter image description here

EDIT: If you'd like to define your area of interest using a free-hand contour, use the Free-hand line tool instead of polygon. Make sure to increase the width of the stroke so that it is easy to close the contour when drawing. You may do so by moving the Stroke>Thickness slider to the right.

That would look like this:

enter image description here

Then create the mask by filling the inside of the free-hand contour using the function FillingTransform, and proceed as before:

enter image description here

5
votes

Perhaps this:

upl = 20;
s = Table[-Sin[i/2] - Sin[j/2], {i, upl}, {j, upl}];

xmin = N[Min[s]]; xmax = N[Max[s]]; mycolorfun = 
Function[Blend[{Blue, Cyan, Green, Yellow, Red}, #]];

mp = MatrixPlot[s, PlotRange -> {All, All, All}, AspectRatio -> 1/1, 
ColorFunction -> (mycolorfun[Rescale[#1, {xmin, xmax}]] &), 
ColorFunctionScaling -> False, MaxPlotPoints -> Automatic, 
FrameLabel -> {"y", "x"}];
Manipulate[
{{x1, y1}, {x2, y2}} = 
 Floor /@ {{p1[[1]], upl - p1[[2]]}, {p2[[1]], upl - p2[[2]]}};
    mp,
{{p1, {1, 1}}, Locator}, {{p2, {19, 19}}, Locator}]

Dynamic[{{x1, y1}, {x2, y2}}]
Dynamic[N@s[[y2 ;; y1, x1 ;; x2]] // MatrixForm]

which produces things like enter image description here with the part of the matrix updated live as you move the locators.

To create polygons instead, just add more locators. Selecting the part of the matrix is then more complicated and it depends on how you want things output.

5
votes

If I got it right, you need to find a connected component of similar pixel values.

You can use image processing functions:

First Binarize the image using an appropriate threshold. Then use MorphologicalComponents that will identify all connected regions. Finally, you can extract the image data and use Pick to get the pixel values corresponding to the component you are interested in.

EDIT: Here's an illustration of the concept:

enter image description here