I have implemented realtime ray tracer with MetalFramework for iOS and it is implemented for following optical prisms like dodecahedron, icosahedron, octahedron, cube, etc. All my figures are composed from triangles, for example cube - 12 triangles, octahedron - 4 triangles. I trace rays and search intersection with figure, then I search how ray moves in prism. Then ray leaves figure and I search intersection with skybox. The problem is in complicated figures. When I test cube fps is 60, but when I test dodecahedron fps is 6. In my algorithm intersection with figure is the same as intersection with any triangle. It means that when I check intersection with ray and figure I have to check intersection with all triangles. I need some idea how to do not check intersections for all triangles. Thanks.
let say you have world bounded by some bounding box
create grid (dividing this box to cubes or whatever)
each voxel/cell
Is a list of triangles that intersects or are in it so before rendering for each cell process all triangles and store index of all triangles inside or crossing
rewrite ray-tracer to trace through this voxel map
So just increment the ray through neighboring voxels it is the same as line rasterization on pixels. This way you have partially Z-sort done. So take first voxel hit by ray and test only triangles contained in it. If any hit on voxel was found then stop (no need to test other voxels because they are farer).
further optimizations
You can add flag if triangle has been tested so test only those which where not already tested because many triangles will be multiple times tested otherwise
[notes]
Number of voxels per axis greatly affect performance so you need to play with it a bit to achieve best performance. If you have dynamic objects then the voxel map lists computations must be done once in a while or even per each frame. For static scene there is sufficient to do this just once.
To trace efficiently you'll need to use an acceleration structure, for example a KD-tree or a bounding volume hierarchy(BVH). This is similar to using a binary search tree to find a matching element.
I would suggest using a BVH because it is easier to construct and traverse than a KD-tree. And I would suggest against using a uniform voxel grid structure. A voxel grid can easily have very poor performance when triangles are unevenly distributed through the scene or heavily concentrated in a few voxels.
The BVH is just a tree of bounding volumes, such as an axis aligned bounding box (AABB) which encompass the primitives within it. This way if your a ray misses the bounding volume you know that it does not hit any primitives contained with it.
To construct a BVH:
Put all the triangle in one bounding volume. This will be the root of the tree.
Divide the triangles into two sets where the bounding volume of each set of triangles is minimized. More properly you'd want to follow the surface area heuristic (SAH), where you want to create set of triangles where you minimize the sum of the (surface area of the BVH)/(# triangles) for both sets of triangles.
Repeat step 2 for each node recursively until you the number of triangles you have left hits some threshold (4 is a good number to try).
To traverse
Check if the ray hits the root bounding box, if it does then proceed to step 2 otherwise no hit.
Check if it hits the child bounding boxes. If it does then repeat this step for its children bounding boxes. Otherwise no hit.
When you get the a bounding box which only contains triangles you'll need to test each triangle to see if it is hit just like normal.
This is a basic idea of a BVH. There much more detail that I haven't gone into about the BVH that you'll have to search for, since there are so many variations in the details.
In Short Implement a bounding volume hierarchy to trace.
Related
I am working on a program that can essentially determine the electrostatic field of some arbitrarily shaped mesh with some surface charge. To test my program I make use of a cube whose left and right faces are oppositely charged.
I use a finite element method (FEM) that discretizes the object's surface into triangles and gives to each triangle 3 integration points (see below figure, bottom-left and -right). To obtain the field I then simply sum over all these points, whilst taking into account some weight factor (because not all triangles have the same size).
In principle this works all fine, until I get too close to a triangle. Since three individual points are not the same as a triangular surface, the program breaks and gives these weird dots. (block spots precisely between two integration points).
Below you see a figure showing the simulation of the field (top left), the discretized surface mesh (bottom left). The picture in the middle depicts what you see when you zoom in on the surface of the cube. The right-most picture shows qualitatively how the integration points are distributed on a triangle.
Because the electric field of one integration point always points away from that point, two neighbouring points will cancel each other out since their vectors aim in the exact opposite direction. Of course what I need instead is that both vectors point away from the surface instead.
I have tried many solutions, mostly around the following points:
Patching the regions near an integration point with a theoretically correct uniform field pointing away from the surface.
Reorienting the vectors only nearby the integration point to manually put them in the right direction.
Apply a sigmoid or other decay function to make the above look more smooth.
Though, none of the methods above allow me to properly connect the nearby and faraway regions.
I guess what might work is some method to extrapolate the correct value from the surroundings. Though, because of the large number of computations, I moved the simulation the my GPU, which means that I have to be careful allowing two pixels to write to each other.
Either way, my question here is as follows:
What would be a good way to smooth out my results? That is, I need a more accurate description of my model when I get closer to a triangle.
As a final note I want to add that it is not my goal to simply obtain a smooth image. Later in the program I need this data to determine the response of a conducting material, which is where these black dots internally become a real pain...
Thank you for your help !!!
I'm looking for a way to detect if a set of points/coordinates have any intersecting lines.
A little setup, I'm drawing a polygon using UIBezierPath on an overlay to a map. This all works. I'm able to reduce the map points down using a point reducing algorithm, and I'm left with a simple looking polygon that renders on my map just fine. FWIW, I'm using Google Maps SDK.
My problem is that it is possible for the user to draw a polygon with self intersecting lines (which is a problem for what I am doing). I need to be able to do one of 3 things.
Remove the intersecting points in the array. (Clip off the bow tie pieces)
Detect if my points have this bow tie (I'll just tell them to redraw a new polygon)
If possible (which I don't think it is), prevent the path from drawing the bow tie in the first place.
I mostly see the bow tie when the polygon self closes and the end point is slightly underlapping the start point. So when the polygon closes and renders into map coordinates on the map, I get a tiny bow tie that messes with an internal API.
Is there anything out there that will work using map coordinates? I've seen some fixes for regular CGPoints, but nothing that will take map coordinates. I would prefer to do this check on my polygon after it has gone through my reducer as it leaves many less points to check. Performance is an issue, and would prefer not to iterate over hundreds of points directly coming off the UIBezierPath. Any help would be appreciated.
I don't know about the Google Maps SDK or the UIBezierPath. I assume that you are given a polygon in the 2D plane and you would like to automatically detect where the polygon intersects itself (if it does).
Perhaps the easiest way to do this is checking all pairs of edges whether they intersect or not. You can check this in O(n2) time where n is the number of edges, as there are n*(n-1)/2 pairs of edges. For a given pair of edges, here are the details how to do it:
How to check if two given line segments intersect?
Nothing extraordinary but the details do require attention.
A more sophisticated algorithm is the plane sweep algorithm:
Line segment intersection, starting at slide 25
Line Segment Intersection Using a Sweep Line Algorithm
Could you suggest an approach for color-based segmentation for square or triangular shapes? I'm working on an iOS app for recognizing road signs and have implemented it for round signs but that approach doesn't seem to work with other forms. For the circles we do the following:
Detect the colors we need, e.g. red and white, through HSV/B.
Detect circle through the method called Fast Circle Detection Using Gradient Pair Vectors based on analysis of gradient direction vectors (description and code: http://rnd.azoft.com/applied-use-of-m2m-tchnology-in-ios-apps/)
Triangles and squares demand differed approach and we've stuck a bit.
Assuming you're looking for red lines...
Threshold just the red component of the image
Compute hough lines and look for line segments of an estimated length (if you know the length of the sides of the triangle/square you're looking for).
Once you have this list, find combinations of lines that form triangles and squares.
Verify each candidate triangle/square by checking that their areas are within expected ranges.
If you follow this method, it is likely that you will find multiple shapes within close proximity of each other i.e. the same triangle/square in the real world will be found multiple times by the algorithm depending on the thickness of the lines. In this case, cluster them by distance and only retain one shape per cluster.
Another option is
Threshold the red component of the image.
Find contours.
Check for closed contours.
For every close contour, check if the shape resembles an equilateral triangle or a square by plotting histograms of slopes of individual points on the contour. The histogram for a square will have two highly populated bins, while that of a triangle will have three highly populated bins.
I have studied on a school project for road sign detection and for our segmentation part, we really benefited from this paper.
http://vc.cs.nthu.edu.tw/home/paper/codfiles/cmwang/201201100409/110104%20Goal%20evaluation%20of%20segmentation%20algorithms%20for%20traffic%20sign%20recognition.pdf
It compares performance of many color based segmentation techniques and some non-color based approaches. Tests compared with different signs.
Unlike some survey paper in this area it explains threshold values for different methods.
Good luck.
Using GPUImage, I am able to detect corners of a book/page in an image. But sometimes, it will pass more than 4 points, in which case I will need to process and figure out the best rectangle out of these points. Here's an example:
What's the most efficient way to figure out the best rectangle in this case?
Thanks
If you're using a corner detection algorithm, then you can filter results based on the relative strength of the detected corner. The contrast at the book corners relative to your current background appears to be much stronger than the contrast at the point found in the wood grain. Are there relative magnitudes associated with each point, or do you just get the points? Setting thresholds for edge strengths can mean a lot of fiddling unless the intensities of the foreground and background are relatively constant.
Your sample image could be blurred or morphed. For example, the right morphological "close" on light pixels could eliminate the texture in the wood grain without having an effect on the size and shape of the book. (http://en.wikipedia.org/wiki/Mathematical_morphology)
Another possibility is to shrink the image to a much smaller size and then perform detection on that. Resizing the image will tend to wipe out tiny details such as whatever wood grain pattern is currently being detected.
Picking the right lens and lighting can make the image easier to process. Try to simplify the image as much as possible before processing it. As mentioned above, "dark field" lighting that would illuminate just the book edges would present a much simpler image for processing. Writing down the constraints can make it more obvious which solution will be most robust and simplest to implement. Finding any rectangle anywhere in an image is very difficult; it's much easier to find a light rectangle on a dark background if the rectangle is at least 100 x 100 pixels in size, rotated no more than 15 degrees from square to the image edges, etc.
More involved solutions can be split into two approaches:
Solving the problem using given only 4 or more (x,y) points.
Using a different image processing technique altogether for the sample image.
1. Solving the program given only the points
If you generally only have 5 or 6 points, and if you are confident that 4 of those points will belong to the corners of the rectangles that you want, then you can try this:
Find the convex hull of all points. The convex hull is the N-gon that completely encompasses all points. If the points were pegs sticking up, and if you stretched a rubber band around them and let it snap into place, then the final shape of the rubber band is a convex hull. Algorithms that find convex hulls typically return a list of points that ordered counterclockwise from the bottom leftmost point.
Make a copy of your point list and remove points from the copy until only four points remain. These four remaining points will still be ordered counterclockwise.
Calculate the angle formed by each set of three successive points: points 1, 2, 3, then 2, 3, 4, then 3, 4, 1, and so on.
If an angle is outside a reasonable tolerance--less than 70 degrees or greater than 110 degrees--skip back to step 2 and remove the next point (or set of points).
Store the min and max angles for each set of 4 points.
Repeat steps 2 - 6, removing a different point (or points) each time.
Track the set of points for which the min and max angles are closest to 90 degrees.
http://en.wikipedia.org/wiki/Convex_hull
There are a number of other checks and constraints that could be introduced. For example, if the point-to-point distances for 3 successive points in the convex hull (pts N to N+1, and N+1 to N+2) are close to the expected width and height of the book, then you might mark these as known good points and only test the remaining points to see which is the fourth point.
The technique above can get unwieldy if you get quite a few points, but it may work if two or three of the book corner points are expected to be found on the convex hull.
For any geometric problem, I always recommend checking out GeometricTools.com, which has a lot of great, optimized source code for all sorts of problems. It's very handy to have the book as well, especially if you can find a cheap copy using AddAll.com.
http://www.geometrictools.com/
2. Other image processing techniques for your sample image
Although I could be wrong, it appears that GPUImage doesn't have many general-purpose image processing algorithms. Some other image processing algorithms could make this problem much simpler to solve.
Though there isn't space to go into it here, one of the keys to successful image processing is appropriate lighting. Make sure you're lighting is consistent. A diffuse light that evenly illuminates the book and the background would work well. You can simplify the problem using funkier lighting: if you have four lights (or a special ring light), you can provide horizontal illumination from the top, bottom, left, and right that will cause the edges of the book to appear bright and other surfaces to appear dark.
http://www.benderassoc.com/mic/lighting/nerlite/Darkfield.htm
If you can use some other GPU libraries to do image processing, then one of the following techniques could work nicely:
Connected component labeling (a.k.a. finding blobs). It shouldn't be too hard to use either binary thresholding or a watershed algorithm to separate the white blob that is the book from the rest of the background. Once the blob for the book is identified, finding the corners is easier. (http://en.wikipedia.org/wiki/Connected-component_labeling) In OpenCV you can find the "contours."
Generate an list of edge points, then have four separate line-fitting tools search from top to bottom, right to left, bottom to top, and left to right to find the four strong (and mostly straight) edges associated with the book. In your sample image, though, either the book cover is slightly warped or the camera lens has introduced barrel distortion.
Use a corner detector designed to find light corners on a dark background. If you will always be looking for a white book on a wood grain background, you can create a detector to find white corners on a brown background.
Use a Hough technique to find the four strongest lines in the image. (http://en.wikipedia.org/wiki/Hough_transform)
The algorithmic technique that works best will depend on your constraints: are you looking for rectangles only of a certain size? is the contrast between foreground and background consistent? can you introduce lighting to simplify the appearance of the image? and so on.
I need to match a given point (lat, lon) against several polygons to decide if there is a match.
The easiest way would be to iterate over each polygon and apply the point-in-polygon check algorithm, but that is prohibitively expensive.
The next optimization that I did was to define a bounding rectangle for each polygon (upper bound, lower bound) and iteratively check the point against each bounding box (fewer comparisons as against checking all the points in the polygon).
Is there any other optimizations possible? Would a spatial index on the bound rectangle points or a geohash help?
Further optimizations:
The bounding box idea is good. Checking if a point is in a bounding box is extremely fast.
If you still need more speed, you can do more pre-calculation like this:
For each polgon create a bounding box.
Define equally sized "tiles" that cover your map.
For each tile, create a list of polygons that overlap. You can do that by first checking if the bounding box overlaps with the tile. If they do, you check if the polygon overlaps with the tile.
When searching, do this:
Determine the tile that you're in. That's a fast operation.
Now you have the list of potential polygons.
For each polygon, check if the point is in the bounding box.
if it is, check if the point is in the polygon using the more expensive algorithm that you've mentioned.
I've used this algorithm several times and it's very fast. By changing the tile size you can choose the right balance between memory footprint and performance:
Think of the extreme cases:
One huge tile that covers the entire map:
You'll get one list of all elements in your map, you'll have to check all of the bounding boxes.
Very tiny tiles (1x1 m for a map that only has a polygon per country):
You'll get a huge amount of tiles. All polygons will be split over many tiles, and each tile will only have one polygon. But, once you've figured out in which tile the point is (fast), it's almost 100% sure that there's just one polygon that needs to be checked.
You need to be somewhere in between. If you only need this once and a while, you might want to choose a low memory footprint over performance. The optimal tilesize can also depends on the homogeneity of the polygon sizes. So, there is no automatic way to calculate an optimal tile-size, and you'll just have to tweak a bit until you get it right.