So I calculate the disparity between 2 stereo images(left and right).It looks correct
(because it is somewhat similar in shape to the original image).After this I use the line :-
cvReprojectImageTo3D(&disparity, threeDimage, &Q);
and get the answers in threeDimage.It is a matrix and I access it as :-
for(int ii=0;ii<threeDimage->rows;ii++)
{
float *data = (float *)(threeDimage->data.ptr + ii * threeDimage->step);
for(int jj=0;jj<threeDimage->cols*3;jj=jj+3)
{
float a=data[jj];
float b=data[jj+1];
float c=data[jj+2];
fprintf(fpp,"%f %f %f \n", a,b,c);
}
}
But the problem is it doesnt seem to give me a correct answer.I get lot of repeated values in my file.Any hint on what might be going wrong?Is the traversal of the matrix correct?
You can only get a different 3D distance from points where there is an edge in the disparity map. If you have large areas of the same disparity (flat grey in the input image) then they will have the same Z.
Related
I am working on CT scan images and I want to extract a small patch from cancer location of scans for example (16,40,40)(z,y,x), sometimes the location are on the corners and cannot get the size that decided before, for solving that problem tried to do padding in all side, here is my code:
M,N,P=(16,40,40)
temp_img = np.ndarray([16,40,40],dtype=np.float32)
center = np.array([node_z, node_y, node_x]) # nodule center
v_center = np.rint((center-origin)/spacing) # nodule center in voxel space (still x,y,z ordering)
temp_imgtemp_img[:,:,:] = img_array[int(v_center[0]-(M/2)):int(v_center[0]+(M/2)),\
int(v_center[1]-(N/2)):int(v_center[1]+(N/2)),\
int(v_center[2]-(P/2)):int(v_center[2]+(P/2))]
m,n,p=temp_img.shape
a1,a2,b1,b2,c1,c2=0,0,0,0,0,0
if (m,n,p) != (M,N,P):
if m != M:
a=M-m
a1=a/2
a2=a-a1
if n != N:
b=N-n
b1=b/2
b2=b-b1
if p != P:
c=P-p
c1=c/2
c2=c-c1
transform=((a1,a2),(b1,b2),(c1,c2))
temp_img = np.pad(temp_img,transform,'linear_ramp')
plt.imshow(temp_img[5], cmap='gray')
plt.title('image')
plt.grid(which='major', linewidth='0.8', color='red')
plt.show()
but I get an error:
TypeError: `pad_width` must be of integral type.
by changing a1=a/2 to a1=a//2 as suggested in one of the answers below the above problem is solved but I get the new error:
could not broadcast input array from shape (20,50,50) into shape (25,50,50)
which means that my real problem is not solved, cuz when tried this solution the value is rounded and the shape gets smaller or begger than specified shape.
The error stems from here:
a1=a/2
If a is odd, a1 will be a floating point number. So you should do a truncating divide like a//2 or round and cast back to int like int(round(a/2)).
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);
}
I am currently working on a project called "Raytracer" in c.
I encounter a problem, the spheres are oval when they are not centered.
Here is an excerpt of my code:
int i;
int j;
t_ray vect;
i = -1;
vect.x = 100. - cam.x;
while (++i < screenx)
{
j = -1;
vect.y = ((screenx / 2.) - i - cam.y) * -1.;
while (++j < screeny)
{
vect.z = (screeny / 2.) - j - cam.z;
}
}
This is likely not a bug, but simply a reality of how perspective projections work. When the camera is directly looking at a sphere, the projection is circular, but as it moves away from the center, it distorts. For more info read this link in the POV-Ray wiki: http://wiki.povray.org/content/Knowledgebase:Misconceptions#Topic_3
In that way the vector has different length on different pixels. You should normalize the vector at the end (dividing the components by the vector length)
It's probably late now, but to give you an answer, your "problem" is in reality called "fish-eye". I encounted this problem too. there're many ways to avoid this problem. The easiest is to increase the distance between the camera and your scene. It's not the cleaner way.
You also can normalize your rays, here are some reasons :
.keep the same distance ratio for every rays
.keep the same angle difference between every ray and its neighbors
.it makes many intersection computations ways easier
Is there a fast way to do this? Searching online shows convexity of functions or single polygons. But I need the ability to check this for the whole model. An object can have convex faces but can be concave as a whole like a torus.
Kneejerk: if you build a leafy BSP tree and end up with all your geometry at one node, the object is convex.
Slightly smarter way to approach the same solution: for each polygon, get the hyperplane. Make sure every vertex in the model is behind that hyperplane.
Equivalently: check the line segment between every pair of vertices; if it doesn't intersect any faces then the object is convex.
I guess you could also get the convex hull, via quickhull or whatever, and compare it to the original object. Or, similarly, get the convex hull and check that every vertex of the original object lies on a face of the hull.
For every face, compute the equation of the plane of support and check that all vertices* yield the same sign when plugged in the plane equation.
Will take time O(F.V), for F faces and V vertices.
*For safety, disregard the vertices of the face being processed.
Alternatively, compute the 3D convex hull, in time O(V.Log(V)). If at any stage in the algorithm a vertex gets discarded, then the polyhedron was not convex.
bool IsConvex(std::vector<vec3> &points, std::vector<int> &triangles, float threshold = 0.001)
{
for (unsigned long i = 0; i < triangles.size() / 3; i++)
{
vec3 Atmp = points[triangles[i * 3 + 0]];
vec3 Btmp = points[triangles[i * 3 + 1]];
vec3 Ctmp = points[triangles[i * 3 + 2]];
btVector3 A(Atmp.x, Atmp.y, Atmp.z);
btVector3 B(Btmp.x, Btmp.y, Btmp.z);
btVector3 C(Ctmp.x, Ctmp.y, Ctmp.z);
B -= A;
C -= A;
btVector3 BCNorm = B.cross(C).normalized();
float checkPoint = btVector3(points[0].x - A.x(), points[0].y - A.y(), points[0].z - A.z()).dot(BCNorm);
for (unsigned long j = 0; j < points.size(); j++)
{
float dist = btVector3(points[j].x - A.x(), points[j].y - A.y(), points[j].z - A.z()).dot(BCNorm);
if((std::abs(checkPoint) > threshold) && (std::abs(dist) > threshold) && (checkPoint * dist < 0))
{
return false;
}
}
}
return true;
}
trimesh is a Python library that can load a 3D mesh and evaluates if mesh is convex or not.
import trimesh
mesh = trimesh.load('my_mesh_file')
print(mesh.is_convex)
Code is given here.
It can be run from a command line with the following instructions:
python -m pip install trimesh
python -c "import trimesh; mesh = trimesh.load('my_mesh_file'); print(mesh.is_convex)"
You can accelerate the plane-vertex tests by adding all vertices to a tree structure first, so you can reject whole leaves if their bounds don't intersect the plane.
The BSP idea should actually be identical to testing all triangle planes, as no BSP leaf will be able to subdivide the set of vertices for a convex object.
You probably want to include an epsilon for your plane tests, as both floating point precision and modelling precision for manually created meshes can result in vertices slightly above a plane.
So let's say I want to mix these 2 audio tracks:
In Audacity, I can use the "Mix and Render" option to mix them together, and I'll get this:
However, when I try to write my own code to mix, I get this:
This is essentially how I mix the samples:
private function mixSamples(sample1:UInt, sample2:UInt):UInt
{
return (sample1 + sample2) & 0xFF;
}
(The syntax is Haxe but it should be easy to follow if you don't know it.)
These are 8-bit sample audio files, and I want the product to be 8-bit as well, hence the & 0xFF.
I do understand that by simply adding the samples, I should expect clipping. My issue is that mixing in Audacity doesn't cause clipping (at least not to the extent that my code does), and by looking at the "tail" of the second (longer) track, it doesn't seem to reduce the amplitude. It doesn't sound any softer either.
So basically, my question is this: what's Audacity doing that I'm not? I want to mix tracks to sound exactly as if they're being played on top of one another, but I (obviously) don't want this horrendous clipping.
EDIT:
Here is what I get if I sign the values before I add, then unsign the sum value, as suggested by Radiodef:
As you can see it's much better than before, but is still quite distorted and noisy compared to the result Audacity produces. So my problem still stands, Audacity must be doing something differently.
EDIT2:
I mixed the first track on itself, both with my code and Audacity, and compared the points where distortion occurs. This is Audacity's result:
And this is my result:
I think what is happening is you are summing them as unsigned. A typical sound wave is both positive and negative which is why they add together the way they do (some parts cancel). If you have some 8-bit sample that is -96 and another that is 96 and you sum them you will get 0. If what you have is unsigned audio you will instead have the samples 32 and 224 summed = 256 (offset and overflow).
What you need to do is sign them before summing. To sign 8-bit samples convert them to a signed int type and subtract 128 from all of them. I assume what you have are WAV files and you will need to unsign them again after the sum.
Audacity probably does floating point processing. I've heard some real dubious claims about floating point like that it has "infinite dynamic range" and garbage like that but it doesn't clip in the same determinate and obvious way as integers do. Floating point has a finite range of values same as integers but the largest and smallest values are much farther apart. (That's about the simplest way to put it.) Floating point can allow much greater amplitude changes in the audio but the catch is the overall signal to noise ratio is lower than integers.
With the weird distortion my best guess is it is from the mask you are doing with & 0xFF. If you want to actually clip instead of getting overflow you will need to do so yourself.
for (int i = 0; i < samplesLength; i++) {
if (samples[i] > 127) {
samples[i] = 127;
} else if (samples[i] < -128) {
samples[i] = -128;
}
}
Otherwise say you have two samples that are 125, summing gets you 250 (11111010). Then you unsign (add 128) and get 378 (101111010). An & will get you 1111010 which is 122. Other numbers might get you results that are effectively negative or close to 0.
If you want to clip at something other than 8-bit, full scale for a bit depth n will be positive (2 ^ (n - 1)) - 1 and negative 2 ^ (n - 1) so for example 32767 and -32768 for 16-bit.
Another thing you can do instead of clipping is to search for clipping and normalize. Something like:
double[] normalize(double[] samples, int length, int destBits) {
double fsNeg = -pow(2, destBits - 1);
double fsPos = -fsNeg - 1;
double peak = 0;
double norm = 1;
for (int i = 0; i < length; i++) {
// find highest clip if there is one
if (samples[i] < fsNeg || samples[i] > fsPos) {
norm = abs(samples[i]);
if (norm > peak) {
norm = peak;
}
}
}
if (peak != 0) {
// ratio to reduce to where there is not a clip
norm = -fsNeg / peak;
for (int i = 0; i < length; i++) {
samples[i] *= norm;
}
}
return samples;
}
It's a lot simpler than you think; although your original files are 8-bit, Audacity handles them internally as 32-bit floating point. You can see this in the screenshot, in the information panel to the left of each track. This means that adding 2 tracks together means adding two floating point samples at each point, and will simply yield sample values from -2.0 to +2.0, which are then clamped to the -1 to +1 range. By comparison, adding two 8-bit integers together will yield another 8-bit number where the value overflows and wraps around. (This can apply whether you use signed or unsigned values.)