I need to convert a image (square) into a quadtree, in the 'usual' way - slice it in four, check if there's only one color into each piece; if yes: close the node, else: repeat;
Anyone know an opensource program to it?
Preferably in Java, but I can use any language.
Thanks.
I imagine you could easily write a program that does it for you in OpenCV. Provided you already have some data structure to hold the actual tree, the main function would look something like this (I've written it for gray images, but it's only the test that needs repeating three times for color):
void divideAndConquer(Mat im, QuadTree &tree, int parent){
if(parent<0)
return;
double min,max;
minMaxLoc(im,&min,&max);
if(max-min<0.01)
tree.addNode(parent,closed);
else{
tree.addNode(parent,open);
Mat im0=Mat(im,Range(0,image.rows/2-1),Range(0,image.cols/2-1));
Mat im1=Mat(im,Range(image.rows/2,image.rows),Range(0,image.cols/2-1));
Mat im2=Mat(im,Range(0,image.rows/2-1),Range(image.cols/2,image.cols));
Mat im3=Mat(im,Range(image.rows/2,image.rows),Range(image.cols/2-1,image.cols));
divideAndConquer(im0, tree, parent/4);
divideAndConquer(im1, tree, parent/4+1);
divideAndConquer(im2, tree, parent/4+2);
divideAndConquer(im3, tree, parent/4+3);
}
}
Related
I want to use Visual C++ to animate fill paths to screen. I have done it with C# before, but now switch to C++ for better perfomance and want do more complex works in the future.
Here is the concept in C#:
In a Canvas I have a number of Path. These paths are closed geometries combine of LineTo and QuadraticBezierTo functions.
Firstly, I fill Silver color for all path.
Then for each path, I fill Green color from one end to other end (up/down/left/right direction) (imagine a progress bar increase its value from min to max). I do it by set the Fill brush of the path to a LinearGradientBrush with two color Green and Silver with same offset, then increase the offset from 0 to 1 by Timer.
When a path is fully green, continue with next path.
When all path is fill with Green, come back first step.
I want to do same thing in Visual C++. I need to know an effective way to:
Create and store paths in a collection to reuse. Because the path is quite lot of point, recreate them repeatly take lots of CPU usage.
Draw all paths to a window.
Do animation fill like step 2, 3, 4 in above concept.
So, what I need is:
A suitable way to create and store closed paths. Note: paths are combine of points connect by functions same with C# LineTo and QuadraticBezierTo function.
Draw and animated fill the paths to screen.
Can you please suggest one way to do above step? (outline what I have to read, then I can study about it myself). I know basic of Visual C++, Win32 GUI and a little about draw context (HDC) and GDI, but only start to learn Graphic/Drawing.
Sorry about my English! If anythings I explain dont clear, please let me know.
how many is quite lot of point ? what is the target framerate? for low enough counts you can use GDI for this otherwise you need HW acceleration like OpenGL,DirectX.
I assume 2D so You need:
store your path as list of segments
for example like this:
struct path_segment
{
int p0[2],p1[2],p2[2]; // points
int type; // line/bezier
float length; // length in pixels or whatever
};
const int MAX=1024; // max number of segments
path_segment path[MAX]; // list of segments can use any template like List<path_segment> path; instead
int paths=0; // actual number of segments;
float length=0.0; // while path length in pixels or whatever
write functions to load and render path[]
The render is just for visual check if you load is OK ... for now atlest
rewrite the render so
it take float t=<0,1> as input parameter which will render path below t with one color and the rest with other. something like this:
int i;
float l=0.0,q,l0=t*length; // separation length;
for (i=0;i<paths;i++)
{
q=l+path[i].length;
if (q>=l0)
{
// split/render path[i] to < 0,l-l0> with color1
// split/render path[i] to <l-l0,q-l0> with color2
// if you need split parameter in <0,1> then =(l-l0)/path[i].length;
i++; break;
}
else
{
//render path[i] with color1
}
l=q;
}
for (;i<paths;i++)
{
//render path[i] with color2
}
use backbuffer for speedup
so render whole path with color1 to some bitmap. On each animation step just render the newly added color1 stuff. And on each redraw just copy the bitmap to screen instead of rendering the same geometry over and over. Of coarse if you have zoom/pan/resize capabilities you need to redraw the bitmap fully on each of those changes ...
I'm trying to implement a MRT-DTI real-time fibertracking visualization tool based on VTK.
Therefore we need to read the DTI tensors/matrices per cell stored in a NIFTI Image (.nii) and I really can't figure out how to do this.
It's not a problem to retrieve a single scalar value from the NIFTI file, but I don't know how to get the tensor (3x3/4x4 matrix).
We would really appreciate any help !
Since the NIFTIImageReader is supposed to read a tensor NIFTI image as a multi-component vtkImage we tried this:
vtkSmartPointer<vtkImageExtractComponents> extractTupel1 = vtkSmartPointer<vtkImageExtractComponents>::New();
extractTupel1->SetInputConnection(reader->GetOutputPort());
extractTupel1->SetComponents(0,1,2);
extractTupel1->Update();
vtkSmartPointer<vtkImageExtractComponents> extractTupel2 = vtkSmartPointer<vtkImageExtractComponents>::New();
extractTupel2->SetInputConnection(reader->GetOutputPort());
extractTupel2->SetComponents(3, 4, 5);
extractTupel2->Update();
vtkSmartPointer<vtkImageExtractComponents> extractTupel3 = vtkSmartPointer<vtkImageExtractComponents>::New();
extractTupel3->SetInputConnection(reader->GetOutputPort());
extractTupel3->SetComponents(6, 7, 8);
extractTupel3->Update();
extractTupel1->GetOutput()->GetPoint(pointId, tupel1);
extractTupel2->GetOutput()->GetPoint(pointId, tupel2);
extractTupel3->GetOutput()->GetPoint(pointId, tupel3);
But it doesn't work. Maybe the GetPoint-Method is the wrong choice?
Please help :)
Answer by David Gobbi, really much thanks to him!:
No, the GetPoint() method will not return the tensor value. It will return the coordinates of the voxel. So vtkImageExtractComponents is not necessary here, either.
A vtkImageData always stores the voxel values as its "Scalars" array, even if the voxel values are not scalar quantities.
A simple (but inefficient way) to get the scalar values is this method:
GetScalarComponentAsDouble (int x, int y, int z, int component)
For each voxel, you would call this method 9 times with component = [0..8].
A much more efficient way of getting the tensors is to get the scalar array from the data, and then look up the tensors via the pointId:
reader->Update();
vtkDataArray *tensors = reader->GetOutput()->GetPointData()->GetScalars();
double tensor[9];
tensors->GetTuple(pointId, tensor);
This is orders of magnitude more efficient than GetScalarComponentAsDouble().
I've got a row dimensional array of values that I want to visualize in 3D and I'm using scene kit under OS X for it. I've done it in a clumsy manner by using each column as a point on the X axis, each row as a point on the Z axis, and each value as a normalized point on the Y axis -- I place a sphere at the vector defined by each data point. It works but it doesn't look too good.
I've also done this by building a mesh of lines based on #Matthew's function in Drawing a line between two points using SceneKit (the answer he posted, not the original question). For each point I use his function to draw two lines - one between my current point and the next point to the right and another between my current point and the next point towards the front (except when there is no additional column/row, of course).
Using the second method, my results look much better... however the performance is quite hideous! It takes quite a long time to complete the initial rendering, and if I use a trackpad/mouse to rotate or translate the scene, I might as well get a cup of coffee to wait until my system is usable again (and this is not much hyperbole). Using the sphere method, things render and update very quickly.
Any advice on how to improve the performance when using the lines method? (Note that I am not trying to add both lines and spheres at the same time.) Code-wise, the only difference between approach is which of the following methods gets called (and that for each point, addPixelAt... is called once, but addLineAt... is called twice for most points).
- (SCNNode *)addPixelAtRow:(CGFloat)row Column:(CGFloat)column size:(CGFloat)size color:(NSColor *)color
{
CGFloat radius = 0.5;
SCNSphere *ball = [SCNSphere sphereWithRadius:radius*1.5];
SCNMaterial *material = [SCNMaterial material];
[[material diffuse] setContents:color];
[[material specular] setContents:color];
[ball setMaterials:#[material]];
SCNNode *ballNode = [SCNNode nodeWithGeometry:ball];
[ballNode setPosition:SCNVector3Make(column, size, row)];
[_baseNode addChildNode:ballNode];
return ballNode;
}
- (SCNNode *)addLineFromRow:(CGFloat)row1 Column:(CGFloat)column1 size:(CGFloat)size1
toRow2:(CGFloat)row2 Column2:(CGFloat)column2 size2:(CGFloat)size2 color:(NSColor *)color
{
SCNVector3 positions[] = {
SCNVector3Make(column1, size1, row1),
SCNVector3Make(column2, size2, row2)
};
int indices[] = {0, 1};
SCNGeometrySource *vertexSource = [SCNGeometrySource geometrySourceWithVertices:positions count:2];
NSData *indexData = [NSData dataWithBytes:indices length:sizeof(indices)];
SCNGeometryElement *element = [SCNGeometryElement geometryElementWithData:indexData
primitiveType:SCNGeometryPrimitiveTypeLine
primitiveCount:1
bytesPerIndex:sizeof(int)];
SCNGeometry *line = [SCNGeometry geometryWithSources:#[vertexSource] elements:#[element]];
SCNMaterial *material = [SCNMaterial material];
[[material diffuse] setContents:color];
[[material specular] setContents:color];
[line setMaterials:#[material]];
SCNNode *lineNode = [SCNNode nodeWithGeometry:line];
[_baseNode addChildNode:lineNode];
return lineNode;
}
From the data that you've shown in your question I would say that your main problem is the number of draw calls. Your's is in the tens of thousands, which is way too much. It should probably be a lot closer to ~100.
The reason why you have so many draw calls is that you have so many distinct objects in your scene (each line). The better (but more advanced solution) would probably be to generate a single element for the entire mesh that consists of all the lines. If you want to achieve the same rendering with that mesh (with a color from cold to warm based on the height) then you could do that in a shader modifier.
However, in your case I would start by flattening all the lines (since that would be the smallest code change and should still have a significant performance improvement in your case).
(Optimizing performance is always an iterative process. Once you fix one thing there will be another thing which is the most expensive operation. Without your code I can only say what would help with the current performance problem)
Create an empty node (without adding it to your scene) and generate all the lines, adding them to this node. Then create a flattened copy of that node by calling flattenedClone on the node that contains all the lines
SCNNode *nodeWithAllTheLines = [SCNNode node];
// create all the lines and add them to it...
SCNNode *flattenedNode = [nodeWithAllTheLines flattenedClone];
[_baseNode addChildNode:flattenedNode];
When you do this you should see a significant drop in the number of draw calls (the number after the diamond in the statistics) and hopefully a big increase in performance.
I'm starting to go into random world generating, I have an idea on how random number generating works (Actually pseudorandom numbers), but I don't have a good idea of how to make the world look "nice", in other words not just place blocks based on a random x, y that it gives me, but make it look smooth.
This will be a 1 time generation per world. So everything is created at start.
I was thinking of an algorithm a few moments ago, but the problem is that it would just use be an endless amount of nested if loops, which would probably take a more than the necessary time. I was thinking of the following:
Choose a random location on the map and place the spawn point in that location.
Start building the street based on the spawn location, like if the spawn location is 16
spaces near the edge of the world build a house, otherwise start building a street.
Based on the previously generated street's place structures around.
Place misc.
Conceptualizing the algorithm isn't much of a problem, what I'm having difficulty with is starting the actual code from step 2 and below. Based on the above algorithm or an algorithm you think of, how would you start the code? I'm not asking for the actual code to be made, just an idea of how it would look.
I know this question isn't precise and can have multiple answers, but I've seen many questions similar to this one having a strange approach.
hmm looks like planar(or cubic) map filling. from my point of view firstly you need some databases
struct _object
{
string name,help,info; // texts for later use
int siz[3]; // grid size of object
int pos[3]; // placement pos (center or what ever)
// other stuff like: mesh-id,color,hit points,...
};
struct _dependency
{
int objid
List<int> near; // can be near this objects (can add probability)
List<int> far; // cannot be near this objects (can add probability,min distance)
};
List<_object> object; // DBS of all object types
List<_dependency> depend; // DBS of object dependency
Then you need to initialize this DBS from ini files or whatever. After that you need to create world map. For simplicity let it by only a single squared town and single layer(no sub-terrain), size and placement can be random.
List<_object> obj; // DBS of placed objects, could be lesser derivate of previous _object to conserve memory requirements
const int N=100;
int[N][N] map; // placement map, containing placed obj id, or -1 for empty space
so now you need some town generating function that fills map[N][N]:
void genere()
{
int i,j,x,y,xx,yy,objid,objix;
int _min_complexity=N/10; // this can also be random
int _max_complexity=N; // this can also be random
// clear map
for (i=0;i<N;i++)
for (j=0;j<N;j++)
map[i][j]=-1;
int complexity=_min_complexity+random(_max_complexity-_min_complexity);
for (i=0;i<complexity;)
{
// random placenet position
x=random(N);
y=random(N);
// random object, should take in mind object[].near and closest objects in map[y][x]
objid=random(object.num);
if (check if map[][] is empty enough to place object[objid] to x,y,z)
if (check if near x,y position is not bad type of object already object[].far)
{
// add new object to list
objix=obj.add(object[objid]);
// add new object to map
int *siz=obj[objix].siz
int *pos=obj[objix].pos
x+=pos[0];
y+=pos[1];
for (yy=0;yy<siz[1];yy++)
for (xx=0;xx<siz[0];xx++)
map[y+yy][x+xx]=objid;
i++;
}
}
}
also the position can be double[3] + orientation matrix and map coordinates will than be aligned to grid. There are many ways to tweak this code, its just an starting template. Hope it helps a little.
P.S.
List<type> l;
l.num - number of items in list
l[i] - i item from list
i=l.add(a) - add new item a to list and returns its index
When i am using code below to draw points over my image, each time i draw a new point, i am loosing my previous point, though i want to keep that as well.
void imageviewer :: paintEvent(QPaintEvent * e)
{
QLabel::paintEvent(e);
if(mpaintflag)
{
QPainter painter(this);
QPen paintpen(Qt::red);
paintpen.setWidth(10);
QPoint p1;
p1.setX(mFirstX);
p1.setY(mFirstY);
painter.setPen(paintpen);
painter.drawPoint(p1);
}
}
I think that i can keep my previous points using QList, tried a lot, but still no idea how to do it using QList.
I did it, i make a list (QList) to store the coordinate points, and then paint all the points in the list every time on image. That's how i did it.
Thanks