Eliminating rectangles enclosed within other rectangles in OpenCV - c

I'm in the process of writing a C program using OpenCV to detect some rectangles made with tape, which are hollow on the inside. Problem is, each physical rectangle gives two digital rectangles: one for the inner perimeter, one for the outer perimeter. The outer rectangle in all cases completely encloses the inner rectangle.
I need some way to remove the inner rectangles, and in a reasonably efficient manner, as this is being run on a video feed and must not drop framerate considerably (approx. 15fps, on a BeagleBoard xM, which is not terribly powerful).
There are always four physical rectangles, and somewhere between four to eight digital rectangles depending on the cleanliness of the processing operations. The outer rectangle is detected reliably; the inner rectangle is not. The image is thresholded, eroded, and dilated such that the image is clean and detection is reliable in general.
I feel that this problem is separate from OpenCV and is really just working with rectangles and could probably be solved by me with some time, but the project is on a crunch deadline, so I'm also throwing this question in. Thanks in advance, guys.

there is a function called grouprectangle in opencv.
The function can remove multiple rectangles...
Have a happy coding.

Since you only have at most 8 digital rectangles, I think it would be fine to use the natural, brute force, algorithm to figure out which rectangles are inside other rectanges. It's OK to do O(N^2) algorithms when N is small, and 8 is small.
Here is the pseudo code:
for each rectangle i {
for each rectangle j {
if i != j and rectangle i is inside rectangle j {
disregard rectangle i
}
}
}

Solved - the speedy solution is to take the distance to one of the corners from the center point of the rectangle, and compare that distance between rectangles whose centers are very close together. The one with the shorter distance must be the inner rectangle.
Code-wise you'd want to calculate the center, then find, say, the bottom right point, which is just the point with both min x and min y. Calculate the distance between them and store it somehow. For each rectangle, iterate over the other ones and check if their centers are very close (a constant of ~30px works fine for this in my case). Compare the distances calculated earlier; the rectangle with the shorter distance should be deleted from the list of rectangles.

Related

Most efficient way to determine circle coordinates?

I am making a function for drawing a circle in 2d space.
For this, I have identified 2 approaches:
go through all the possible pixels and run them through a formula that will return a value that shows whether the pixel coordinates are inside the circle, outside (bonus: or intersecting it)
get all the circle pixels (basically draw the circle)
I tried to look at some math sources, but I have met with some problems:
in the second approach, the resolution at which I am incrementing the angle matters, so if it is too little, or radius is too small, there will be unnecessary duplication. On the other hand, if the angle gets incremented by more, or radius is too large, there will be gaps.
The formula I was using is:
struct vec2{int x; int y;};
void get_circle(int x, int y, int r, int angle, struct vec2 *coordinates) {
coordiantes->x = x + r * cos(angle);
coordinates->y = y + r * sin(angle);
}
This is obviously a bit much to run a lot of times.
I also want to make some kind of primitive anti-aliasing, so if I can get a value where a pixel only intersects the circle line by a half, it would be drawn as a half-pixel.
My final goal is to draw a nice circle with a line that can be thick. The thickness can be achieved with the area approach where I fill all pixels in a circle area, and then I remove pixels in the inner circle. Or it can be several iterations of the circle. I didn't write the array part of the computation, but yes, I would like each pixel identified. If we take a pixel as a rectangle, then I would like no pixel to be drawn if the theoretical circle goes through <33% of the surface, half-pixel 33-66, and full if >66%.
Please advise. I need some approach that will be computationally efficient.
First, "most efficient" depends on quite a few things. For most modern OpenGL systems you can usually get away with just computing points around the circumference using sine and cosine (and an appropriate aspect scale) with the native floating-point type, then plotting the points using any decent polyline algorithm.
Once you have things working, profile.
If profiling shows your algorithm to be holding things up (and compared to other normal and common computations, it shouldn't be), only then should you spend time and effort on trickier (read: more complicated) stuff, like the Midpoint Circle Algorithm to generate points to send to your polyline.
Also, don't forget to memoize into a sprite or texture or pixmap or whatever is appropriate for your hardware/software IFF profiling shows a worthwhile improvement.

Making Width and Height of a character in console equal in terms of pixels (C)

I'm making a program in C (simple snake game).
I'm using window.h and came across an inconvenience.
I'm using COORD's and SetConsoleCursorPosition to move about the cursor.
However, moving one y coordinate is almost the same as moving two x coordinates in terms of how many pixels each represents.
For example, this square window has a width of 80 and height of 40 in terms of the cursor position coordinates.
Also, you can clearly see the contraction (and therefore reduction of apparent speed of the snake) when moving sidewards in the images below.
Is there any efficient solution to this so that the pixel size of one move in the x direction is the same as one move in the y direction.
Many thanks.
[
The SetCurrentConsoleFontEx function lets you specify the console font size in the lpConsoleCurrentFontEx's dwFontSize member. There you can set the font width and height be the same.

algorithm to find how many circles there are in 2d array

I'm given a 2d binary array. Some of the dots are on, some are off (1 for on, 0 for off).
I know that the "on" dots were created before by putting circles on the 2d array.
The circles are of the same radius, and each time a circle was put, the dots inside it changed to 1 instead of 0.
All the circles are within the edges of the array and dot touching the edge of the circle is lit.
An illustration can be seen below. The circles are ordered randomly and may touch.
Notice that the dots inside the circles are 1 and all other are 0.
Can you find how many circles were there just by looking at the 2d array without the circles after I had put them? Is this problem solvable?
My attempt at solving this problem was:
First, I assumed that my circles can contain dots as in the figure (radius big enough to contain 4 to 7 dots.
Then I tried to categorize what possible orientation can the circles have, however there are just a lot.
I would like to find these two circles. Notice that they can cannot overlap but can be just one near the other.
If your circles don't overlap, you can use connected component labeling algorithm and get number of circles:
NCircles = (NComponents - 1) / 2
(if inner empty regions of circles and outer empty place form separate components)
Edit: with these dots it is worth to select only connected conponents with size in some range to exclude dots and other false regions.
Simple kind of CCL suitable for this picture:
scan image until black pixel is met
do flood fill while possible, keep bounding box of scanned black pixels
if box corresponds to circle size, count it
scan further from any unmarked pixel
One more possible approach: you can try Hough algorithm for circles of predefined radius.
For example, OpenCV library contains labeling function that works with images and arrays (and Hough transform too)
Why not just generate randomly generate circles and count them?
When you insert a new circle, just check if they do not overlap.
And stop inserting new circles after you tried a certain times and failed to insert a new circle. With this last value you probably need to play a bit.
You can probably repeat this a couple of times and average the result like that.

How to display the tiny triangles or recognize them quickly?

What I am doing is a pick program. There are many triangles and I want select the front and visible ones by a rectangular region. The main method is described below.
there are a lot of triangles and each triangle has its own color.
draw all the triangles to a frame buffer.
read the color of pixel in frame buffer and based on the color, we know which triangles are selected.
The problem is that there are some tiny triangles can not be displayed in the final frame buffer. Just like the green triangle in the picture. I think the triangle is too tiny and ignored by the graphic card.
My question is how to display the tiny triangles in the final frame buffer? or how to know which triangles are ignored by the graphic card?
Triangles are not skipped based on their size, but if a pixel center does not fall inside or lie on the top or left edge (this is referred to as coverage testing) they do not generate any fragments during rasterization.
That does mean that certain really small triangles are never rasterized, but it is not entirely because of their size, just that their position is such that they do not satisfy pixel coverage.
Take a moment to examine the following diagram from the DirectX API documentation. Because of the size and position of the the triangle I have circled in red, this triangle does not satisfy coverage for any pixels (I have illustrated the left edge of the triangle in green) and thus never shows up on screen despite having a tangible surface area.
If the triangle highlighted were moved about a half-pixel in any direction it would cover at least one pixel. You still would not know it was a triangle, because it would show up as a single pixel, but it would at least be pickable.
Solving this problem will require you to ditch color picking altogether. Multisample rasterization can fix the coverage issue for small triangles, but it will compute pixel colors as the average of all samples and that will break color picking.
Your only viable solution is to do point inside triangle testing instead of relying on rasterization. In fact, the typical alternative to color picking is to cast a ray from your eye position through the far clipping plane and test for intersection against all objects in the scene.
The usability aspect of what you seem to be doing seems somewhat questionable to me. I doubt that most users would expect a triangle to be pickable if it's so small that they can't even see it. The most obvious solution is that you let the user zoom in if they really need to selectively pick such small details.
On the part that can actually be answered on a technical level: To find out if triangles produced any visible pixels/fragments/samples, you can use queries. If you want to count the pixels for n "objects" (which can be triangles), you would first generate the necessary query object names:
GLuint queryIds[n]; // probably dynamically allocated in real code
glGenQueries(n, queryIds);
Then bracket the rendering of each object with glBeginQuery()/glEndQuery():
loop over objects
glBeginQuery(GL_SAMPLES_PASSED, queryIds[i]);
// draw object
glEndQuery(GL_SAMPLES_PASSED);
Then at the end, you can get all the results:
loop over objects
GLint pixelCount = 0;
glGetQueryObjectiv(queryIds[i], GL_QUERY_RESULT, &pixelCount);
if (pixelCount > 0) {
// object produced visible pixels
}
A couple more points to be aware of:
If you only want to know if any pixels were rendered, but don't care how many, you can use GL_ANY_SAMPLES_PASSED instead of GL_SAMPLES_PASSED.
The query counts samples that pass the depth test, as the rendering happens. So there is an order dependency. A triangle could have visible samples when it is rendered, but they could later be hidden by another triangle that is drawn in front of it. If you only want to count the pixels that are actually visible at the end of the rendering, you'll need a two-pass approach.

Measuring the area of an arbitrary shape from an edge map

I'm trying to write an algorithm that will give me the (approximate) area of a shape.
My algorithm is provided with an image, which in then performs a Sobel edge-detection on. Using the edge-detected image, I'd like to find the area of an enclosed space, given a co-ordinate within the area. The co-ordinate is likely to be close to the centre of the shape, but not exactly centred..
If I wanted to be thorough, I'd do it recursively. However, I'm running this code on an embedded platform, so I'm memory-limited. I'd also prefer speedier algorithms.
The algorithm doesn't need to produce the exact area of the shape - something close (an order of magnitude at most) would be OK.
So far, I've considered approximating the shape as both a rectangle and an ellipse, by measuring up, down, left and right from the co-ordinate until an edge is found.
Here's an example of said methods:
- example image:
- ellipse and rectangle-marked:
The green fill is a partial-run of recursively filling the area.
If anyone has some better methods, I'd appreciate it!

Resources