Rigid transformation of two shapes with OpenCV in Java - java

As the title says, I'm trying to find a way to generate a transformation matrix to best best align two images (the solution with the smallest error value computed with an arbitrary metric - for example the SAD of all distances between corresponding points). Example provided below:
This is just an example in the sense that the outer contour can be any shape, the "holes" can be any shape, any size and any number.
The "from" image was drawn by hand in order to show that the shape is not perfect, but rather a contour extracted from a camera acquired image.
The API function that seems to be what I need is Video.estimateRigidTransform but I ran into a couple of issues and I'm stuck:
The transformation must be rigid in the strongest sense, meaning it must not do any kind of scaling, only translation and rotation.
Since the shapes in the "from" image are not perfect, the number of points in the contour are not the same as the ones in the "To" image, and the function above need two sets of corresponding points. In order to bypass this I have tried another approach: I have calculated the centroids of the holes and outer contour and tried aligning those. There are two issues here:
I need alignment even if one of the holes is missing in the "from" image.
The points must be in the same order in both lists passed to Video.estimateRigidTransform and there is no guarantee that function findContours will provide them in the same order in both shapes.
I have yet to try to run a feature extractor and matcher to obtain some corresponding points but I'm not very confident in this method, especially since the "From" image is a natural image with irregularities.
Any ideas would be greatly appreciated.

Related

Contour and perimeter recognition in binary image

I need to detect contour (object) and find the perimeter of a detected object.
For example, I have the following image:
All images are binary, so they consist of only 0 and 1.
I need to firstly detect objects, and then find the perimeter of the object contour, the area will be known I guess because this is just the sum of all object pixels.
I am using 4-pixel coherence while finding objects.
I have found some algorithms, but cannot figure out how they work and how to implement them if I have an array of 1 and 0.
Please, can someone provide explanation or code example of the easiest to understand the algorithm.
I need to do this without using OpenCV or any other library.
Here is what you can do:
Small opening in order to erase all the small patterns.
Connected component labeling in order to detect, label and separate your objects. See here for java codes.
Perimeter extraction (each non null pixel with at least one black neighbor).

Path2D.intersect() Similar to Area.intersect()

I have played around with Area.intersect() and was wondering if there is a way to create a method much like this one using Path2D because I noticed a performance jump when using Path2D as a shape. In other words take a portion of a large Path2D and create a smaller Path2D from that portion.
Map Drawing
In-Game View
Note: Using the below hashmap a I render tiled shapes to the viewing area according to each "Object" which in this case would be the different image types : Ocean, Grass, Obsidian, Rock, Sand, & Dirt...
LinkedHashMap<Point, LinkedHashMap<Object, Path2D.Double>>
EDIT : Each image type has an entire map area of its own that is 10000px by 100000px my tiles that intersect are 100px by 100px which are shoved into the linked hash map by point as its given type as a Path2D.Double and rendered onto the screen by the points in the current viewing area.
It's not clear what SDK you're working with which offers Area.intersect(). Depanding on what you intend to intersect your path with, however, it may be a complex problem - notice that a path2D intersected with a polygon may turn into several paths!
However, there are some known algorithm for intersecting a path with a polygon, such as Cyrus-Beck or Sutherland-Cohen.
I found this piece of code for Cohen-Sutherland in Java:
http://worldofenggcodes.blogspot.co.il/2013/10/cohen-sutherland-line-clipping-algorithm.html
Which seems OK, although you might need to extract the code into a more usable function. Cyrus-Beck would probably be a better option, though I could only find pseudo-code:
http://www.moreprocess.com/computer-graphics/cyrus-beck-line-clipping-algorithm
Once you've implemented either, you need to apply it to every line in your path, to get a new list of lines which intersect with the square.

Selecting points randomly in regions corresponding with neighbors, avoiding infinite recursion

Pardon the wall of text. I'll add images later. I need to generate a somewhat realistic map of cubic meter voxels, with water, sand, grasses, trees, minerals, deserts, beaches, islands, etc, without any sort of voronoi cop-out(i.e. be smart about relating these factors to each other). Yes, this is a game.
I figured I'd generate critical points randomly and interpolate them for elevation and humidity readings, but I'm at a loss with random generation. Basically I need a somewhat even distribution of points without having to make the full list at once. I need to generate roughly 20x20x20 at a time, and probably work with approximately 1000x1000x1000 cells of critical points, but I'd expect strange things to happen at the edges of the large cells. Does anyone know of any way to select points in this way? The real trouble is that points should prefer to be in proximity to others in "mountain-range" style chains.
The problem here is that this is happening across these 1-km cells.
I can simply pick points this way within a cell, but since a cell and its neighbor need to be dependent on each other, my trivial algorithm would have encountered the need to head to infinity for one of these cells, or see a grid-like pattern of broken chains. The chains should not break more frequently on cell boundaries. If they do a somewhat problematic wafer-like pattern shows in generation and makes for a poor generation that is unusable for design/gameplay reasons.
n.b. For the purposes of these, the system-level random generator can be seeded and is practically uniform. As far as within a cell, I can select chains just fine.
I also considered having a cell spill over into any ungenerated cells so its chains start connected to existing ones, but that would break the determinism of generation simply based on location and seed, adding order of generation as a factor.
Again, for the purposes of realism and design I'm trying to stay away from using Perlin. Or should I post on gamedev.SE?
The key concept is to create the interfaces between a cell and all six of its neighbors before filling in the cell. Picture creating your entire world as a grid of hollow boxes, but before you do that, create it as a wire-frame outline, but before you do that, create the grid of wire-frame intersections.
Here's a simplistic approach -- you'll have to improve this. First, consider this method of generating the entire world at once:
(1) select all the vertex voxels -- perhaps the upper north west voxel in each cell -- and set its world attributes to reasonable values based entirely on location and seed.
(2) select the lines of voxels connecting the vertices, and fill in all their world attributes, based on location and seed, but constrained to match up with the existing vertex voxel values at each end.
(3) select the planes of voxels describing the faces bounded by the existing lines, and fill in in all their world attributes, based on location and seed, but constrained to match up with the existing line voxel values along the edges.
(4) fill in the cell, based on location and seed, but constrained to match up with the existing bounding six faces.
Now, consider that this method doesn't need to be done all at once. All that is necessary is that you create all six faces of a cell before filling it in, and that you create all four bounding lines of a face before you fill that in, and that you create the two end points of a line before filling that in. After the first cell, some of these will already exist.
The reason I said that you'll have to improve this idea is that it produces noticeable gradient boundaries at the cell boundaries. I'm afraid that each interface voxel will not only need to contain world attributes, but the rate of change of each attribute across the interface at that point. This implies that each line voxel will have to contain two rates of change for each attribute, and each vertex, three.
I'm not going to describe how you would constrain the gradient of a world attribute as it approaches a voxel with a predefined gradient because I'm sure you can handle it, my answer is already too long, and I don't know how.

Creating interactive contour plots on Android

I have data in the form of a 2D array of intensities that should be plotted in a contour plot. In the end it should look like a topographic map with contour lines like the following image:
The idea is that the typical multitouch gestures (pinch for zooming, dragging for moving around) can be used to navigate the contour plot. The maximum size of the data should be around 4k*4k points, each 4 bytes big.
Is there some plotting library that I can use, or do I have to start from scratch? Is there an easily implemented algorithm for that?
I don't know of any plotting libraries for Android (or Java for that matter), but I do know a thing or two about plotting in general:
An easy algorithm for creating contours would be Marching Squares. Marching squares creates polygons from your array of data. There should be plenty of examples of this algorithm in Java (try Google Code Search, but read licenses before you use).
If you want to zoom in far you probably want to create bezier curves from these polygons to smooth them out, an example algorithm (with code that should be easily ported to Java) can be found here.
Note: If you want to fill the contours with a color you should consider using a fragment shader instead of creating polygons. Send the data to the shader as a texture and use the intensity to assign a color to each pixel. For this you should know some OpenGL.
As #Markus Johnsson said, one way to visualize your two-dimensional array of data is to use the Marching Squares algorithm. But in your case, it seems you need its implementation based on isolines instead of isobands (which use polygons Markus mentioned about).
Implementation based on isolines is easier to write it from scratch. It is mainly due to the fact, that you have to check only whether a given value is under, or above specific isovalue (vs below-within-above specific range in isoband implementation). This results only in 16 possible configurations of lines drawn in a single isocell (vs 80 polygon configurations in isobands implementation).
It is often desirable to interpolate your data before using it in the creation of the contour map. One way to do so, is to use Bicubic Interpolation.
I've written recently a simple implementation of the filled two-dimensional contour plot based on the Marching Squares algorithm and its isoband variant. This implementation also use mentioned Bicubic Interpolation for smoothening the data. You can find this simple package here. It is written under GNU GPLv3 license (or later). In order to use it in your project you have to copy and paste org.contour2dplot.* to the project's location.
All you need to do in order to draw a contour map with the use of the aforementioned package is to prepare a double[][] data and create a Contour2DMap object. Example use can look like this:
// Specify in the constructor width and height of the contour map.
Contour2DMap contour2DMap = new Contour2DMap(600, 600);
// Specify size for the contour map container.
contour2DMap.setPrefSize(600, 600);
// Set data.
contour2DMap.setData(data);
// Set iso factor, which is a step between subsequent iso values.
contour2DMap.setIsoFactor(1.0);
// Set interpolation factor.
contour2DMap.setInterpolationFactor(10);
// Set contour map color scale - "Color" or "Monochromatic".
contour2DMap.setMapColorScale("Color");
// Draw all elements on the contour map.
contour2DMap.draw();
Contour2DMap object inherits from javafx.scene.layout.Pane, so you can nest it in other javafx.scene.layout.* objects, such as BorderPane.
In order to make contour map interactive you may consider overwriting the javafx.scene.chart.Chart object and nesting Contour2DMap in it.
You may also consider rewriting org.contour2dplot.* for the isolines variant of the Marching Squares algorithm.
Below are two screenshots of Contour2DMap for setMapColorScale("Color") and setMapColorScale("Monochromatic") respectively.

Getting boundary information from a 3d array

Hey, I'm currently trying to extract information from a 3d array, where each entry represents a coordinate in order to draw something out of it. The problem is that the array is ridiculously large (and there are several of them) meaning I can't actually draw all of it.
What I'm trying to accomplish then, is just to draw a representation of the outside coordinates, a shell of the array if you'd like. This array is not full, can have large empty spaces with only a few pixels set, or have large clusters of pixel data grouped together. I do not know what kind of shape to expect (could be a simple cube, or a complex concave mesh), and am struggling to come up with an algorithm to effectively extract the border. This array effectively stores a set of points in a 3d space.
I thought of creating 6 2d meshes (one for each side of the 3d array), and getting the shallowest point they can find for each position, and then drawing them separetly. As I said however, this 3d shape could be concave, which creates problems with this approach. Imagine a cone with a circle on top (said circle bigger than the cone's base). While the top and side meshes would get the correct depth info out of the shape, the bottom mesh would connect the base to the circle through vertical lines, making me effectivelly loose the conical shape.
Then I thought of annalysing the array slice by slice, and creating 2 meshes from the slice data. I believe this should work for any type of shape, however I'm struggling to find an algorithm which accuratly gives me the border info for each slice. Once again, if you just try to create height maps from the slices, you will run into problems if they have any concavities. I also throught of some sort of edge tracking algorithm, but the array does not provide continuous data, and there is almost certainly not a continuous edge along each slice.
I tried looking into volume rendering, as used in medical imaging and such, as it deals with similar problems to the one I have, but couldn't really find anything that I could use.
If anyone has any experience with this sort of problem, or any valuable input, could you please point me in the right direction.
P.S. I would prefer to get a closed representation of the shell, thus my earlier 2d mesh approach. However, an approach that simply gives me the shell points, without any connection between them, that would still be extremely helpful.
Thank you,
Ze
I would start by reviewing your data structure. As you observed, the array does not maintain any obvious spatial relationships between points. An octree is a pretty good representation for data like you described. Depending upon the complexity of you point set, you may be able to find the crust using just the octree - assuming you have some connectivity between near points.
Alternatively, you may then turn to more rigorous algorithms like raycasting or marching cubes.
Guess, it's a bit late by now to be truly useful to you, but for reference I'd say this is a perfect scenario for volumetric modeling (as you guessed yourself). As long as you know the bounding box of your point cloud, you can map these coordinates to a voxel space and increase the density (value) of each voxel for each data point. Once you have your volume fully defined, you can then use the Marching cubes algorithm to produce a 3D surface mesh for a given threshold value (iso value). That resulting surface doesn't need to be continuous, but will wrap all voxels with values > isovalue inside. The 2D equivalent are heatmaps... You can refine the surface quality by adjusting the iso threshold (higher means tighter) and voxel resolution.
Since you're using Java, you might like to take a look at my toxiclibs volumeutils library, which also comes with sevaral examples (for Processing) showing the general approach...
Imagine a cone with a circle on top
(said circle bigger than the cone's
base). While the top and side meshes
would get the correct depth info out
of the shape, the bottom mesh would
connect the base to the circle through
vertical lines, making me effectivelly
loose the conical shape.
Even an example as simple as this would be impossible to reconstruct manually, let alone algorithmically. The possibility of your data representing a cylinder with a cone shaped hole is as likely as the vertices representing a cone with a disk attached to the top.
I do not know what kind of shape to
expect (could be a simple cube...
Again, without further information on how the data was generated, 8 vertices arranged in the form of a cube might as well represent 2 crossed squares. If you knew that the data was generated by, for example, a rotating 3d scanner of some sort then that would at least be a start.

Categories