convert between image coordinates (i-j-k) and world coordinates (x-y-z) vtk in C# - vtk

Does anyone knows how can I convert from image coordinates acquired like this:
private void renderWindowControl1_Click(object sender, System.EventArgs e)
{
int[] lastPos = this.renderWindowControl1.RenderWindow.GetInteractor().GetLastEventPosition();
Z1TxtBox.Text = (_Slice1 + 1).ToString();
X1TxtBox.Text = lastPos[0].ToString();
Y1TxtBox.Text = (512 - lastPos[1]).ToString();
}
into physical coordinates.
TX Tal

VTK may have an elegant method call, but in general you will need to use the information in your image's image plane module (specifically Equation C.7.6.2.1-1).
http://dicom.nema.org/medical/dicom/current/output/html/part03.html#sect_C.7.6.2

in order to convert between a click and physical location:
There is some insights I got from working on this project:
int[] lastPos = this.renderWindowControl1.RenderWindow.GetInteractor().GetLastEventPosition();
returns the pixel location of the click in the control. It is a problem because if the user zooms in, lastPos does not represent the location in the dicom.
The solution I have found, was to use vtkPropPicker class. Code example can be found here and here.
image_coordinate are in world coordinates but without the origin offset. which mean, that:
1. if we want to get the pixel location (in 512x512 grid): the x,y value should be normalized by pixel spacing, and image orientation. the value of these parameters can be acquired using the equation mentioned in the answer above me Equation C.7.6.2.1-1.
vtkDICOMImageReader _reader;
reader.GetPixelSpacing();
reader.GetImageOrientationPatient();
If we need world physical location, we should add the origin offset for x and y:
reader.GetDataOrigin();
As for Z axis: I didn't need it, so I am not sure.
That is my dime on the matter, maybe there are some more elegant ways, I haven't found them.

Related

Strange artifacts when ray casting a volume

So I am writing a volume ray caster (for the first time ever) in Java, learning from the code of the great VTK toolkit written in C.
Everything works almost exactly like VTK, except I get this strange artifacts, looking like elevation lines on the volume. I've noticed that VTK also shows them when manipulating the image, but they disappear when the image is static.
I've looked though the code multiple times, and can't find the source of the artifacts. Maybe it is something simple a computer graphics expert knows from the top of his head? :)
More info on my implementation
I am using the gradient method for normal calculations (a standard from what I've found on the internet)
I am using trilinear interpolation for ray point values
This "elevation line" artifacts look like value rounding errors, but I can't find any in my code
Increasing the resolution of the render does not solve the problem
The artifacts do not seem to be "facing" any fixed direction, like the camera position
I'm not attaching the code since it is huge :)
EDIT (ray composite loop)
while (Geometry.pointInsideCuboid(cuboid, position) && result.a > MINIMAL_OPACITY) {
if (currentVoxel.notEquals(previousVoxel)) {
final float value = VoxelUtils.interpolate(position, voxels, buffer);
color = colorLUT.getColor(value);
opacity = opacityLUT.getOpacityFromLut(value);
if (enableShading) {
final Vector3D normal = VoxelUtils.getNormal(position, voxels, buffer);
final float cos = normal.dot(light.fixedDirection);
final float gradientOpacity = cos < 0 ? 0 : cos;
opacity *= gradientOpacity;
if(cos > 0)
color = color.clone().shade(cos, colorLUT.diffuse, colorLUT.specular);
}
previousVoxel.setTo(currentVoxel);
}
if(opacity > 0)
result.accumulate(color, opacity);
position.add(rayStep);
currentVoxel.fromVector(position);
}

Merging overlapping transparent shapes in directx

This is the problem I am facing simplified:
Using directx I need to draw two(or more) exactly (in the same 2d plane) overlapping triangles. The triangles are semi transparent but the effect I want to release is that they clip to transparency of a single triangle. The picture below might depict the problem better.
Is there a way to do this?
I use this to get overlapping transparent triangles to not "accumulate". You need to create a blendstate and set it on output merge.
blendStateDescription.AlphaToCoverageEnable = false;
blendStateDescription.RenderTarget[0].IsBlendEnabled = true;
blendStateDescription.RenderTarget[0].SourceBlend = D3D11.BlendOption.SourceAlpha;
blendStateDescription.RenderTarget[0].DestinationBlend = D3D11.BlendOption.One; //
blendStateDescription.RenderTarget[0].BlendOperation = D3D11.BlendOperation.Maximum;
blendStateDescription.RenderTarget[0].SourceAlphaBlend = D3D11.BlendOption.SourceAlpha; //Zero
blendStateDescription.RenderTarget[0].DestinationAlphaBlend = D3D11.BlendOption.DestinationAlpha;
blendStateDescription.RenderTarget[0].AlphaBlendOperation = D3D11.BlendOperation.Maximum;
blendStateDescription.RenderTarget[0].RenderTargetWriteMask = D3D11.ColorWriteMaskFlags.All;
Hope this helps. Code is in C# but it works the same in C++ etc. Basically, takes the alpha of both source and destination, compares and takes the max. Which will always be the same (as long as you use the same alpha on both triangles) otherwise it will render the one with the most alpha.
edit: I've added a sample of what the blending does in my project. The roads here overlap. Overlap Sample
My pixel shader is as:
I pass the UV co-ords in a float4.
xy = uv coords.
w is the alpha value.
Pixel shader code
float4 pixelColourBlend;
pixelColourBlend = primaryTexture.Sample(textureSamplerStandard, input.uv.xy, 0);
pixelColourBlend.w = input.uv.w;
clip(pixelColourBlend.w - 0.05f);
return pixelColourBlend;
Ignore my responses, couldn't edit them...grrrr.
Enabling the depth stencil prevents this problem

Convert Colored Image to Gray Scale In Codenameone

Can anyone tell me how to go about converting a RGB Image object to Gray Scale? I know there is a lot of information on how to do this in Java already, but I just wanted to get an answer specific to Codenameone so others can benefit.
I am trying to implement image binarization using Otsu’s algorithm
You can use Image.getRGB() then modify the array as explained in this answer:
Convert Image to Grayscale with array matrix RGB java
Notice that the answer above is a bit over simplistic as it doesn't take into account the correct weight per color channel for proper grayscale effect but this depends on your nitpicking levels.
Then use this version of createImage with the resulting array.
For anyone looking for a simplified way (not using matrices) of doing what Shai is hinting, here is some sample code
int[] rgb = image.getRGB();
for(int k = 0;k<rgb.length;k++)
{
if(rgb[k]!=0)
{
int r = rgb[k]/256/256;
rgb[k]=rgb[k]-r*0x10000;
int g = rgb[k]/256;
rgb[k]=rgb[k]-g*0x100;
int b = rgb[k];
int intensity = (int)Math.round(((r+g+b)/(256.0*3.0))*256);
rgb[k] = intensity+(intensity*256)+intensity*(256*256);
}
}
Image grayImage = Image.createImage(rgb,image.getWidth(),image.getHeight());

JTS : distance between two geometries bypassing another one in the middle

Let's say that I want to calculate the distance between two geometries with JTS, but there is another one in the middle that I can't go across (as if it was a wall). It could look like this :
I wonder how I could calculate that.
In this case, these shapes geom1 and geom2 are 38.45 meters away, as I calculate it straight away. But if I don't want go across that line, I should surround it by the Northern sides, and distance would probably be more than 70 meters away.
We can think that we could have a line a polygon or whatever in the middle.
I wonder if there is any built in function in JTS, or some other thing I could you. I guess if there is anything out there, I should check for some other workaround, as trying to solve complex routing problems is beyond my knowledge.
This is the straight away piece of code using JTS for the distance, which would not still take into account the Geometry in the middle.
import org.apache.log4j.Logger;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;
public class distanceTest {
private final static Logger logger = Logger.getLogger("distanceTest");
public static void main(String [] args) {
//Projection : EPSG:32631
// We build one of the geometries on one side
String sGeom1="POLYGON ((299621.3240601513 5721036.003245114, 299600.94820609683 5721085.042327096, 299587.7719688322 5721052.9152064435, 299621.3240601513 5721036.003245114))";
Geometry geom1=distanceTest.buildGeometry(sGeom1);
// We build the geometry on the other side
String sGeom2=
"POLYGON ((299668.20990794065 5721092.766132105, 299647.3623194871 5721073.557249224, 299682.8494029705 5721049.148841454, 299668.20990794065 5721092.766132105))";
Geometry geom2=distanceTest.buildGeometry(sGeom2);
// There is a geometry in the middle, as if it was a wall
String split=
"LINESTRING (299633.6804935104 5721103.780167559, 299668.99872434285 5720999.981241705, 299608.8457218057 5721096.601805294)";
Geometry splitGeom=distanceTest.buildGeometry(split);
// We calculate the distance not taking care of the wall in the middle
double distance = geom1.distance(geom2);
logger.error("Distance : " + distance);
}
public static Geometry buildGeometry(final String areaWKT) {
final WKTReader fromText = new WKTReader();
Geometry area;
try {
area = fromText.read(areaWKT);
}
catch (final ParseException e) {
area = null;
}
return area;
}
}
This works for SQL, I hope you have the same or similar methods at your disposal.
In theory, in this instance you could create a ConvexHull containing the two geometries AND your "unpassable" geometry.
Geometry convexHull = sGeom1.STUnion(sGeom2).STUnion(split).STConvexHull();
Next, extract the border of the ConvexHull to a linestring (use STGeometry(1) - I think).
Geometry convexHullBorder = convexHull.STGeometry(1);
EDIT: Actually, with Geometry you can use STExteriorRing().
Geometry convexHullBorder = convexHull.STExteriorRing();
Lastly, pick one of your geometries, and for each shared point with the border of the ConvexHull, walk the border from that point until you reach the first point that is shared with the other geometry, adding the distance between the current and previous point at each point reached. If the second point you hit belongs to the same geometry as you are walking from, exit the loop and move on to the next to reduce time. Repeat for the second geometry.
When you've done this for all possibilities, you can simply take the minimum value (there will be only two - Geom1 to Geom2 and Geom2 to Geom1) and there is your answer.
Of course, there are plenty of scenarios in which this is too simple, but if all scenarios simply have one "wall" in them, it will work.
Some ideas of where it will not work:
The "wall" is a polygon, fully enveloping both geometries - but then how would you ever get there anyway?
There are multiple "walls" which do not intersect each other (gaps between them) - this method will ignore those passes in between "walls". If however multiple "walls" intersect, creating essentially one larger "wall" the theory will still work.
Hope that makes sense?
EDIT: Actually, upon further reflection there are other scenarios where the ConvexHull approach will not work, for instance the shape of your polygon could cause the ConvexHull to not produce the shortest path between geometries and your "walls". This will not get you 100% accuracy.

transition a circle into a line by unrolling it with SVG and d3

For a project we are trying to make a circle into a line (and back again) while it is rotating along a linear path, much like a tire rotates and translates when rolling on a road, or a curled fore finger is extended and recurled into the palm.
In this Fiddle, I have a static SVG (the top circle) that rotates along the linear black path (which is above the circle, to mimic a finger extending) that is defined in the HTML.
I also use d3 to generate a "circle" that is made up of connected points (and can unfurl if you click on/in the circle thanks to #ChrisJamesC here ), and is translated and rotated
in the function moveAlongLine when you click on the purple Line:
function moveAlongLine() {
circle.data([lineData])
.attr("transform", "translate(78.5,0) rotate(-90, 257.08 70) ")
.duration(1000)
circle.on("click", transitionToCircle)
}
The first problem is that the .duration(1000) is not recognized and throws a Uncaught TypeError: Object [object Array] has no method 'duration' in the console, so there is a difference between the static definition of dur in SVG and dynamically setting it in JS/D3, but this is minor.
The other is should the transform attributes be abstracted from one another like in the static circle? in the static circle, the translate is one animation, and the rotation is another, they just have the same star and duration, so they animate together. How would you apply both in d3?
The challenge that I can not get, is how to let it unroll upwards(and also re-roll back), with the static point being the top center of the circle also being the same as the leftmost point on the line.
these seem better:
I should try to get the unfurl animation to occur while also rotating? This seems like it would need to be stepwise/sequential based...
Or Consider an octogon (defined as a path), and if it were to rotate 7 of the sides, then 6, then 5.... Do this for a rather large number of points on a polyhedron? (the circle only needs to be around 50 or so pixels, so 100 points would be more than enough) This is the middle example in the fiddle. Maybe doing this programmatically?
Or This makes me think of a different way: (in the case of the octogon), I could have 8 line paths (with no Z, just an additional closing point), and transition between them? Like this fiddle
Or anything todo with keyframes? I have made an animation in Synfig, but am unsure ho get it to SVG. The synfig file is at http://specialorange.org/filedrop/unroll.sifz if you can convert to SVG, but the xsl file here doesn't correctly convert it for me using xsltproc.
this seems really complicated but potential:
Define a path (likely a bézier curve with the same number of reference points) that the points follow, and have the reference points dynamically translate as well... see this for an concept example
this seems complicated and clunky:
Make a real circle roll by, with a growing mask in front of it, all while a line grows in length
A couple of notes:
The number of points in the d3 circle can be adjusted in the JS, it is currently set low so that you can see a bit of a point in the rendering to verify the rotation has occurred (much like the gradient is in the top circle).
this is to help students learn what is conserved between a number line and a circle, specifically to help learn fractions. For concept application, take a look at compthink.cs.vt.edu:3000 to see our prototype, and this will help with switching representations, to help you get a better idea...
I ended up using the same function that generates the circle as in the question, and did a bit of thinking, and it seemed like I wanted an animation that looked like a finger unrolling like this fiddle. This lead me to the math and idea needed to make it happen in this fiddle.
The answer is an array of arrays, with each nested array being a line in the different state, and then animate by interpolating between the points.
var circleStates = [];
for (i=0; i<totalPoints; i++){
//circle portion
var circleState = $.map(Array(numberOfPoints), function (d, j) {
var x = marginleft + radius + lineDivision*i + radius * Math.sin(2 * j * Math.PI / (numberOfPoints - 1));
var y = margintop + radius - radius * Math.cos(2 * j * Math.PI / (numberOfPoints - 1));
return { x: x, y: y};
})
circleState.splice(numberOfPoints-i);
//line portion
var lineState = $.map(Array(numberOfPoints), function (d, j) {
var x = marginleft + radius + lineDivision*j;
var y = margintop;
return { x: x, y: y};
})
lineState.splice(i);
//together
var individualState = lineState.concat(circleState);
circleStates.push(individualState);
}
and the animation(s)
function all() {
for(i=0; i<numberOfPoints; i++){
circle.data([circleStates[i]])
.transition()
.delay(dur*i)
.duration(dur)
.ease("linear")
.attr('d', pathFunction)
}
}
function reverse() {
for(i=0; i<numberOfPoints; i++){
circle.data([circleStates[numberOfPoints-1-i]])
.transition()
.delay(dur*i)
.duration(dur)
.ease("linear")
.attr('d', pathFunction)
}
}
(Note: This should be in comments but not enough spacing)
Circle Animation
Try the radial wipe from SO. Need to tweak it so angle starts at 180 and ends back at same place (line#4-6,19) and move along the X-axis (line#11) on each interation. Change the <path... attribute to suit your taste.
Line Animation Grow a line from single point to the length (perimeter) of the circle.
Sync both animation so that it appears good on all browsers (major headache!).

Resources