computed slice position is different from the one in DICOM file - dicom

I am implementing a method to spatially sort DICOM slices in a volume. The way I am doing it is to sort by the position along the slice normal. This is computed as:
slice_normal = [0, 0, 0]
dir_cosines = ds[0x0020, 0x0037] # Direction cosines
slice_normal[0] = dir_cosines[1] * dir_cosines[5] - dir_cosines[2] * dir_cosines[4]
slice_normal[1] = dir_cosines[2] * dir_cosines[3] - dir_cosines[0] * dir_cosines[5]
slice_normal[2] = dir_cosines[0] * dir_cosines[4] - dir_cosines[1] * dir_cosines[3]
image_pos = ds[0x0020, 0x0032] # IPP
distance_along_normal = 0
for i in range(len(slice_normal)):
distance_along_normal += slice_normal[i] * image_pos[i]
Now this value distance_along_normal should be equal to the slice location(0x0020, 0x1041), except in my case it has the opposite sign. So the slice ordering seems to be reversed than what it should be. I would like to know ehat else must I need to take something else into account to compute the correct slice ordering.

There is no reason to expect that the sign or the value of the offset calculated by your implementation should be the same as the sign or the value of the Slice Location (0020,1041) value. As per DICOM specification
Slice Location (0020,1041) is defined as the relative position of the
image plane expressed in mm. This information is relative to an
unspecified implementation specific reference point.
Note that the direction of location is not specified at all, and it is explicitly said that the origin is arbitrary, which means that the only thing guaranteed to match between your calculation and the Slice Location is the distance (absolute value of the difference) of the positions of any 2 slices.
Also note that Slice Location is Type 3 - it does not have to be provided at all.
With regards to slice ordering - the presentation order is your decision. If you want spatial ordering, you need to decide the criteria for your ordering. For example, should axial slices be presented beginning from the head, or from the feet? That is your call completely and it will depend on the application (intended use) of your software.
If you do NOT care for the geometry, you can present images ordered for example by Instance Number (0020,0013). But there is no guarantee the ordering will have any geometrical meaning (although it usually has).

Related

What direction do the DICOM instance numbers grow along?

By direction I mean for example from a patient's head to bottom or from his bottom to head. The CHEST CT scans I have seen so far indicates that Instance Number 1 slice is usually the first one down from the upper part of the body but I don't know whether this is part of the standard or there are some other tags that I should inspect into to determine.
There is no rule in DICOM that requires the Instance Number to be related to the slice position in a particular way. The link of Bartloimiej shows that there is a rule how the slice coordinates defined by Image Position Patient (0020,0027) and Image Orientation Patient (0020, 0037) are related to directions in the patient's body (head, feet, etc.)
So if you want to apply spatial ordering, these attributes are what you want to use. Slice Location (0020,1041) will not help you as well:
C.7.6.2.1.2 [...] This information is relative to an unspecified implementation specific reference point.
For original (i.e. Image Type (0008,0008) is ORIGINAL\PRIMARY...) CT slices, it is quite safe to assume that some growth in the Z-Direction is always present in a volumetric dataset. But for MRI or for reconstructed CT-slices (MPR), you may find datasets in which slices are parallel to the xz or yz plane. If your application is supposed to handle such images, make sure to avoid division by zero...
Yes, the standard defines it. DICOM PS3.3, part C.7.6.2:
The direction of the axes is defined fully by the patient's orientation.
If Anatomical Orientation Type (0010,2210) is absent or has a value of BIPED, the x-axis is increasing to the left hand side of the patient. The y-axis is increasing to the posterior side of the patient. The z-axis is increasing toward the head of the patient.
There is also a tag (0020,0037), Image Orientation (Patient), which relates actual position of the patient to the global coordinate frame. In trunk CT it is almost always 1 0 0 0 1 0 (no rotation) and you don't need to deal with it. Otherwise, see comments under the link above.
You are correct. The chest CT series are sorted from head to feet. The slice closest to the head should have the lowest Instance Number.
I don't know if this is defined by the DICOM standard or not, but I have seen a lot of DICOM images and the convention is this:
AXIAL - sorted by Z axis high to low (head to feet)
CORONAL - sorted by Y axis high to low (back to front)
SAGITTAL - sorted by X axis low to high (right to left)
Notice in all cases, the first slice in the series will be farthest from the observer.
If you need to generate Instance Number, you should sort the images by the dot product of Image Position Patient and (1,-1,-1) from low to high. In the rare degenerate case (all dot products are the same), I don't know. Pick another direction to sort, but probably (0,-1,-1) would be a good choice.
EDIT: I just discussed this with a friend who is more experienced. He said it varies. Some departments prefer back to front order, some prefer front to back. Also some DICOM viewers will give users the choice of how the slices are sorted (by Instance Number, Slice Location, IPP, Content Time, etc)

Get Dicom image position into a sequence

A simple question as i am developing a java application based on dcm4che ...
I want to calculate/find the "position" of a dicom image into its sequence (series). By position i mean to find if this image is first, second etc. in its series. More specifically i would like to calculate/find:
Number of slices into a Sequence
Position of each slice (dicom image) into the Sequence
For the first question i know i can use tag 0020,1002 (however it is not always populated) ... For the second one?
If you are dealing with volumetric image series, best way to order your series is to use the Image Position (Patient) (0020, 0032). This is a required Type 1 tag (should always have value) and it is part of the image plane module. It will contain the X, Y and Z values coordinates representing the upper left corner of the image in mm. If the slices are parallel to each other, only one value should change between the slices.
Please note that the Slice Location (0020, 1041) is an optional (Type 3) element and it may not exist in the DICOM file.
We use the InstanceNumber tag (0x0020, 0x0013) as our first choice for the slice position. If there is no InstanceNumber, or if they are all the same, then we use the SliceLocation tag (0x0020, 0x1041). If neither tag is available, then we give up.
We check the InstanceNumber tag such that the Max(InstanceNumber) - Min(InstanceNumber) + 1 is equal to the number of slices we have in the sequence (just in case some manufacturers start counting at 0 or 1, or even some other number). We check the SliceLocation the same way.
This max - min + 1 is then the number of slices in the sequence (substitute for tag ImagesInAcquisition 0x0020, 0x1002).
Without the ImagesInAcquisition tag, we have no way of knowing in advance how many slices to expect...
I would argue that if the slice location is available, use that. It will be more consistent with the image acquisition. If it is not available, then you'll have to use or compute from the image position (patient) attribute. Part 3 section C.7.6.2.1 has details on these attributes.
The main issue comes when you have a series that is oblique. If you just use the z-value of the image position (patient), it may not change by the slice thickenss/spacing between slices attributes, while the slice location typically will. That can cause confusion to end users.

Math/Physics: Given angle and vector find point of intersection?

I have two objects and I need to determine whether they will collide at some time in the future. Say the two objects are trucks, each in their separate lane. The first truck wants to change lanes, but will the trucks collide?
Both objects are moving forward, but only the first has an angle. The objects are moving at different, varying velocities, yet only the velocity of the second object is known. Also, the two objects are operating on separate coordinate systems (meaning each object has a new origin), with varying distance between the objects.
I don't have a vector for the first object, but I do have an angle (not fixed) at which it is headed, relative to the x-axis.
For the second object, I have a vector, and it is headed straight.
Please refer to the picture below:
How can I find the point of intersection, based on these criteria? I imagine the angle is an infinite line, which at some point will cross the vector magnitude of the second object. I don't suppose this is as straight forward as calculating the point of intersection of two lines.
Wrapup:
Velocity of the second object is known (but varying)
Angle of the first object is known
Distance between the objects is known (but varying)
Acceleration in the x-direction of the first object is known (But I CANNOT use this to find the velocity due to limitations)
I have redrawn your image with a few more labels on it.
First we need to be working in one coordinate system. I have chosen to use the system with object 1 at (0,0). This means that object 2 is at position (Xd,Yd).
Then we find the point of intersection. In these coordinates this point will be x=0 and y=y1 (0,y1). Now we want to know what this is in terms of y2, yd and the angle theta.
Using what you know this now tells us where the intersection point is. We need to find out how long it takes each object to get to that point. Taking this time for each and setting them equal to each other will give us the conditions on the velocity and acceleration of each object that will make them collide. Starting with the constant acceleration equation for object 1 and 2 (find these in any intro physics book):
where y0 is the starting position, V0 is the initial velocity, and a is the acceleration.
y0 for object 1 will be 0 since we called that the origin and y0 for object 2 will just be yd.
Now solve for t in each of these and set them equal to each other. Since these are just quadratic in t we can use the quadratic equation. After this you should get:
with,
Then plug in the values you know for velocities, accelerations and positions. If both sides are equal they collide, if not, they dont. This essentially sets conditions on these quantities that have to be met in order for them to be at the same place, at the same time, i.e. a collision.

OpenCL image2d and image3d memory layout

When transferring a 2d image stored in host memory to OpenCL, how is it reading the values - row major or column major? Let's assume row major.
index = row*NUM_COLS + col
How about 3d image stored in host memory? I believe that's treated as a stack of 2D images (which was assumed to be row major). Then pixel (row,col,slice) for limits (NUM_ROWS,NUM_COLS,NUM_SLICES) in terms of OpenCL is at:
index = slice*NUM_ROWS*NUM_COLS + row*NUM_COLS + col
However, according to wikipedia formulas the 3d Row Major indexing should be:
index = slice + NUM_SLICES*(col + NUM_COLS*row)
= row*NUM_COLS*NUM_SLICES + col*NUM_SLICES + slices
According to same article Column Major Ordering access should be:
index = row + NUM_ROWS*(col + NUM_COLS*slice)
= slice*NUM_ROWS*NUM_COLS + col*NUM_ROWS + row
None of which seems to match what OpenCL is doing in 3d case.
So I guess I really have 2 questions
How do I lay out my memory for transfering 2d and 3d images to OpenCL?
Why does it seem like OpenCL has chosen a non standard memory layout in 3d case?
Edit
I view wikipedia article as a generic layout scheme. "row" or "column" are secondary label words. Whether you are dealing with tuples (row, col, slice) limited to (NUM_ROWS, NUM_COLS, NUM_SLICES) or (x,y,z) (WIDTH, HEIGHT, DEPTH) doesn't matter as long as it's consistent. It just tells you which dimension is continuous in memory. In "row major" it's the last dimension - z values that are next to each other, in column major it's the first dimension - x.
So once again I think "row major" layout for x,y,z 3d image indexing should have been:
index = z + DEPTH * (y + HEIGHT * x) = x * HEIGHT * DEPTH + y * HEIGHT + z
It isn't. But, I suppose you can chose whatever scheme you want.
First of all, your assumptions about the OpenCL layout are correct. OpenCL indeed uses the layout you describe and the formulas you provide for both the 2D and the 3D case are correct, component after component, pixel after pixel, row after row, slice after slice. And I (having an OpenGL background) consider this pretty standard.
Yet there is a bit of a naming confusion here, since what row-major in general means is what Wikipedia says, the first dimension changes with the lowest frequency and the last dimension is contiguous. Yet with images, the row isn't actually the first dimension, but the y-dimension, and columns are x. So while OpenCL (at least in 2D) uses literal "row-major" layout (since rows change less often), it is generally seen (in the terminology as used by Wikipedia) rather column-major, since the first dimension (x) is contiguous. And this translates well to 3D, where the last dimension (z) changes with lowest frequency. So you got Wikipedia wrong, what it is actually saying is that general column-major (as extended to 3D) is
index = z*WIDTH*HEIGHT + y*WIDTH + x
which, given that x=col and y=row, is indeed
index = slice*NUM_ROWS*NUM_COLS + row*NUM_COLS + col
which is exactly what OpenCL uses. So to answer you actual questions:
Exactly like you explained in the first part of your question.
Because you got Wikipedia wrong and confused matrix-based (row,col)-indexing with image-based (x,y)-indexing and what OpenCL uses corresponds to what Wikipedia generally calls column-major.
EDIT: This confusion of index-based addressing (like matrices) and coordinate-based addressing (like images) is a common source of confusion. For example in OpenCV (a famous image processing library) images are represented and addressed as matrices and thus like (row,col), which for an actual image means (y,x).

What is a 3D Vector and how does it differ from a 3D point?

Does a 3D vector differ from a 3D point tuple (x,y,z) in the context of 3D game mathematics?
If they are different, then how do I calculate a vector given a 3d point?
The difference is that a vector is an algebraic object that may or may not be given as the set of coordinates in some space. (thanks to bungalobill for correcting my sloppiness).
A point is just a point given by coordinates. Generally, one can conflate the two. If you are given a set of coordinates, and told that they constitute a 'point' with no further information (choice of basis, etc), then you can just hand that set of numbers back and legitimately claim to have produced a vector.
The largest difference between the two is that it makes no sense to do things to one that you can do to the other. For example,
You can add vectors: <1 2 3> + <3 2 1> = <4 4 4>
You can multiply (or scale) a vector by a number (generally called a scalar)
2 * <1 1 1> = <2 2 2>
You can ask how far apart two points are: d((1, 2, 3), (3, 2, 1) = sqrt((1 - 3)2 + (2 - 2)2 + (3 - 1)2) = sqrt(8) ~= 2.82
A good intuitive way to think about the association between a vector and a point is that a vector tells you how to get from the origin (that one point in space to which we assign the coordinates (0, 0, 0)) to its associated point.
If you translate your coordinate system, then you get a new vector for the same point. Although the coordinates that make up the point will undergo the same translation so it's a pretty easy conflation to make between the two.
Likewise if rotate the coordinate system or apply some other transformation (e.g. a shear), then the coordinates and vector associated to the point will also change.
It's also possible for a vector to be something else entirely, for example a bounded function on the interval [0, 1] is a vector because you can multiply it by a real number and add it to another function on the interval and it will satisfy certain requirements (namely the axioms of a vectorspace). In this case one thinks of having one coordinate for each real number, x, in [0, 1] where the value of that coordinate is just f(x). So that's the easiest example of an infinite dimensional vector space.
There are all sorts of vector spaces and the notion that a vector is a 'point and a direction' (or whatever it's supposed to be) is actually pretty vacuous.
A vector represents a change from one state to another. To create one, you need two states (in this case, points), and then you subtract the initial state from the final state in order to get the resultant vector.
Vectors are a more general idea that a point in 3D space.
Vectors can have 2, 3, or n dimensions. They represent many quantities in the physical world (e.g., velocity, force, acceleration) besides position.
A mathematician would say that a vector is a first order tensor that transforms according to this rule:
u(i) = A(i, j)v(j)
You need both point and vector because they are different. A point in 3D space denoting position is a vector, but every vector is not a point in 3D space.
Then there's the computer science notion of a vector as a container - it's an abstraction for an array of values or references. This is a different concept from a mathematician's idea of a vector, because every vector container need not obey the first order tensor transformation law (e.g. a Vector of OrderItems). That's yet another separate idea.
It's important to keep all these in mind when talking about vectors and points.
Does a 3D vector differ from a 3D point tuple (x,y,z) in the context of 3D game mathematics?
Traditionaly vector means a direction and speed. A point could be considered a vector from the world orgin of one time step. (even though it may not be considered mathematically pure)
If they are different, then how do I calculate a vector given a 3d point?
target-tower is the common mnemonic.
Careful on your usage of this. The resulting vector is really normal*velocity. If you want to change it into something useful in a game application: you will need to normalize the vector first.
Example: Joe is at (10,0,0) and he wants to go to (10,10,0)
Target-Tower: (10,10,0)-(10,0,0)=(0,10,0)
Normalize the resulting vector: (0,1,0)
Apply "physics": (0,1,0) * speed*elapsed_time < speed = 3 and we'll say that the computer froze for a whole 2 seconds between the last step and this one for ease of computation >
=(0,6,0)
Add the resulting vector to Joes current point in space to get his next point in space: ... =(10,6,0)
Normal = vector/(sqrt(x*x+y*y+z*z))
...I think I have everything here
Vector is the change in the states. A point is the static point. Two vectors can be parallel or perpendicular. You can have product of two vectors which is a third vector. You can multiply a vector by a constant. You can add two vectors.
All these operations are not allowed on point. So program wise if you think both as a C++ class, there will be many such methods in the vector class but probably only Get and Set for point.
In the context of game mathematics there is no difference.
Points are elements of an affine space.† Vectors are elements of a vector (aka linear) space. When you choose an origin in an affine space it automatically induces a linear structure on that affine space. The contrary is also true: if you have a vector space it already satisfies all the axioms of an affine space.
The fact is that when it comes to computation, the only way to represent an affine space numerically is to use tuples of numbers, which also form a vector space.
Each object in a game always has an origin, and it is crucial to know where it is. That origin is set relative to the origin of the world, which is set relative to the origin of the camera/viewport. The vertices of the object are represented as vectors -- offsets from the object origin. You use matrix multiplication to transform the objects -- that is too a purely vector space operation (you cannot multiply an affine point by a matrix without specifying the origin first). Etc, etc... As we see all those triplets of numbers that we might think of as 'points' are actually vectors in the local coordinate system.
So is there any reason to distinguish between the two outside the study of algebra? It is an unnecessary abstraction, and unnecessary abstractions are harmful (KISS). So my answer is no, just go with a single vector type.
† Or any topological space outside the context of game development.
A vector is a line, that is a sequence of points but that it can be represented by two points, the starting and the ending point.
If you take the origin as the starting point, then you can describe your vector giving only the ending point.

Resources