3

I want to extract coordinates out of a Raster3D. It is possible to extract coordinates out of an Image3D by using PixelValuePositions. The coordinates extracted are not the coordinates i am looking for because Image3D uses a different coordinate system. Is it possible to extract coordinates from Raster3D? Or is it possible to translate the coordinates extracted from Image3D into the coordinates from Raster3D?

Alexey Popkov
  • 61,809
  • 7
  • 149
  • 368
tom
  • 31
  • 1

3 Answers3

5

Raster3D just holds a matrix and an optional data range list, so you can get coordinate postions like this:

raster = Raster3D[RandomReal[1, {3, 4, 5}], {{0, 0, 0}, {1,1,1}}];
dim = Dimensions@First@raster;
coordinates = raster[[2]];
p = Position[First@raster, x_ /; x < .1];
pos = Reverse[coordinates[[1]] - Subtract @@ coordinates/dim #] & 
          /@ (p - 1/2);
Graphics3D[{Opacity[.25], raster, PointSize[.05], Red, Point[pos]}]

enter image description here

if your raster doesn't have a coordinate specification use coordinates={{0,0,0},dim}

george2079
  • 38,913
  • 1
  • 43
  • 110
  • Note that dim includes the number of channels (i.e. 3 04) as its last element. If you just want the "data range list" if none is provided, you may wish to do a Drop[dim, -1]. – Spencer Rugaber Aug 25 '21 at 13:09
4

You can convert Raster3D into Image3D simply by applying Image3D and then use ImageValuePositions:

whitePos = {1, 2, 3};
raster = Raster3D[
   ReplacePart[RandomReal[1, {5, 5, 5, 3}], whitePos -> {1, 1, 1}]];
i3d = Image3D@raster

image

xyz = ImageValuePositions[i3d, White]
{{2.5, 1.5, 0.5}}
PixelValuePositions[i3d, White]
{{3, 2, 1}}

As you see from the above, the position returned by PixelValuePositions differs from position inside of Raster3D. According to the Documentation page for PixelValuePositions (the second point under the "Details" section),

In 3D, PixelValuePositions[image,val] returns the positions {xp,yp,zp}, such that pixel position {1,1,1} corresponds to the center of the bottom-left front pixel.

So the coordinate system used by PixelValuePositions is very similar to coordinate system of Graphics3D. But for direct use in Graphics3D you need ImageValuePositions which returns coordinates of centers of pixels rather than positions. Citing the Documentation page for ImageValuePositions (the first point under the "Details" section),

ImageValuePositions assumes the standard image coordinate system.

image

So ImageValuePositions is what you actually need. For example, you can place a black point inside of the white pixel as follows (warning: unfortunately this code crashes my Mathematica 10.4.1 on Windows 7 x64, so I have used version 10.0.1 for evaluating and exporting):

Graphics3D[{{Opacity[.25], raster}, {Black, PointSize[Large], Point[xyz]}}]

image

As george2079 correctly notices in his answer, if your Raster contains an optional data range list as the second argument, you should take it into account and Rescale your xyz coordinates accordingly.

Alexey Popkov
  • 61,809
  • 7
  • 149
  • 368
  • Thank you for your response. The problem is i start with an Image3D which i first have to convert to a Raster3D. Is there a solution to extract the same coordinates i would extract using Raster3D out of an Image3D? Or is it possible to convert Image3D to a Raster3D? – tom May 24 '16 at 09:40
  • @tom Of course you can use xyz = ImageValuePositions[Image3D[<...>], White] right from the start, then convert Image3D into Raster3D using Show[Image3D[<...>]][[1]]. – Alexey Popkov May 24 '16 at 09:44
  • When I use ImageValuePositions on an Image3D, I get coordinates which are from the Image3D coordinate system (x,y,z) starting in de left bottom corner. When i plot my coordinates in my ListPointPlot3D, these coordinates are different from my coordinates obtained from a Raster3D. So my Plots won't match. – tom May 24 '16 at 09:50
  • @tom Please check the example given at the bottom of my answer: it shows you that coordinates obtained from Image3D give exact match with the Raster3D: the black Point is placed exactly where it should be, i.e. in the center of the white pixel! – Alexey Popkov May 24 '16 at 09:54
  • Thank you for helping me! Sadly it didn't work. – tom May 30 '16 at 08:09
1

Because the solutions provided didn't work in my case, I tried something different. I extracted coordinates using different software which uses Slices, Rows and Columns as coordinates system (Msrc). I wanted to import this data in mathematica and import my Image3D object as well. When i imported the two, i realised that the coordinates didn't match.The dimensions of images and volumes, however, refer to graphic coordinates x, y, and z and are listed in reverse order.

An array of data is embedded in space like text in a book. The array starts on the top page, top-left corner and continues line by line to the bottom-right corner before it continues on the page below until it ends on the bottom page.

Index coordinates system

Graphic 3D coordinate system

In the examples above you can see that not only the coordinate system is different, but also your starting point is different. Index coordinates -> The first voxel is located at the top-left rear corner with coordinate center {1,1,1}. Graphic 3D coordinate system -> The first voxel is located at the bottom-left front corner with coordinate center {1/2,1/2,(1/2)}.

To adjust my Image3D to a point in which it should have the same starting position i used ImageReflect twice. First Top-> Bottom, Then Front->Back

<file=Import["file","Image3D"]>
<file=ImageReflect[file,Top->Bottom]>

<file=ImageReflect[file,Front->Back]>

I used PixelValuePositions to extract my coordinates needed

<PixelValuePositions[file,1]>

Because the vectors in the Msrc coordinate system are different from the xyz coordinate system, I multiplied the coordinates from my list (obtained with pixelValuePositions) by {-1,-1,1}. Slices is pointing in the opposite direction of the Z vector, so -1. Rows is pointing in the opposite direction of Y vector, so -1. Columns is pointing in the same direction of X vector so 1.

Multiplied the coordinates {x,y,z} by {-1,-1,1}

I think there will be an easier solution to the problem. This was the only thing i could come up with.

tom
  • 11
  • 3
  • 1
    Please take time to format your answer properly to facilitate browsing: http://mathematica.stackexchange.com/editing-help. Also, your answer is not really clear to me. If you provide working code (including sample data) would be the best way to make this answer useful for others. – Yves Klett May 30 '16 at 09:44