Say we have a photo frame like the one above.
Starting from center, how would u find a rectangle with maximum area that can be used to draw (all pixels in the rectangle must be rgb(255,255,255)?
I need to find the x and y coordinate of point A and B shown in the picture.
One of my approach is to do this:
starting from the center, and expand the boundary like the graph above.
But I am not sure how you could write loop(s) like that.
You should use the flood fill algorithm: link.
I suggest you to use sets to store the pixels to be altered in a set; that way the number of recursions to be done can be reduced.
Edit: I obviously didn't read the question well. Still, the flood fill could be used, if you used it it on a circle that is expanded.
Start with a single pixel, that is the center of your circle.
set the radius lager by 1 unit.
Find the pixels within your circle, get their colours using flood fill.
If they are the same color, goto 2. If not, you have the radius finding the rectangle is next.
This algorithm may give you a possible solution, but there may be more than one, depending on your frame - you should start developing using some simple frame where the correctness of the solution can be judged easily.
Edit: based on the comment, the problem is to find the largest area axis-parallel rectangle in a polygon - and luckily there is a paper on this: here. Doesn't look as an easy task though.
I would use brute force here. Choose a y_bottom and y_top, determine the corresponding x_left and x_right and loop both y_bottom and y_top over the width of the picture. In pseudocode:
for y_bottom in range (0, H):
for y_top in range (y_bottom, H):
# Assume that x = W/2 is part of the rectangle
x_left = maximum X such that all pixels in box (x_left, y_top, W/2, y_bottom) are white
x_right = minimum X such that all pixels in box (W/2, y_top, x_right, y_bottom) are white
determine Area of box (x_left, y_top, x_right, y_bottom)
store this box if Area is larger than max found so far
Related
So after I've done object detection, I have a few overlapping 2d rectangles, and I want to find size of the area outside of all the rectangles I've created, which has (xyxy) coordinates on each one. How do I find size of area outside that boxes in python?
enter image description here
I have tried to calculate the area by adding the sizes of all the bounding boxes then the sum will be used to subtract the size from the input image. However, it is still constrained by overlapping square lengths so that the measurement is not accurate.
from bbox import BBox2D
box1 = BBox2D([0.20212765957446807, 0.145625, 0.24822695035460993, 0.10875])
box2 = BBox2D([0.6693262411347518, 0.146875, 0.31382978723404253, 0.06875])
print(box2.height * box2.width)
print(box1.height * box1.width)
Try this one.
or simply u can
def _getArea(box):
return (box[2] - box[0]) * (box[3] - box[1])
This should do the trick. Structure of Box: [xmin,ymin,xmax,ymax]
To find the area outside all of the boxes, you will need to do the following things.
Find the area of the entire image
Find the area of all of the rectangles (including overlapping area)
Find the total overlapping area
Subtract the total overlapping area from the total area of the rectangles
Subtract the rectangle area without overlap from the area of the entire image
To find the total overlapping area, you will need to loop through every rectangle on the screen and check if it is overlapping. If it is overlapping another rectangle you will need to find the corners that are overlapping each other. For example in your image, the top left and middle rectangles are overlapping. The two corners you need would be the bottom right corner of the top left rectangle and the top left corner of the middle rectangle. You can then find the area of the rectangle that is made by the overlap.
If you add a little more information in your question, I could type out a simple function that could do this but right now I don't know all the specifications.
I have a list of (x,y) points that constitue several circles with different centers, they all have the same diameter (which is known).
I need to detect the number of circles in total (not necessary to define their parameters). Is there a simple way to do that in python? (preferably without openCV)
If all circles have the same size and they do not intersect, you can just scan the picture line-by-line, pixel-by-pixel.
When you meet a pixel of circle color, apply flood-fill algorithm from this point and mark all connected pixels of the same color with the same integer value (1 for the first circle and so on).
After all the last value is number of objects.
Aslo you can use connected-component labelling algorithm
I'm looking for a way to split a number of images into proper rectangles. These rectangles are ideally shaped such that each of them take on the largest possible size without containing a lot of white.
So let's say that we have the following image
I would like to get an output such as this:
Note the overlapping rectangles, the hole and the non axis aligned rectangle, all of these are likely scenario's I have to deal with.
I'm aiming to get the coordinates describing the corner pieces of the rectangles so something like
[[(73,13),(269,13),(269,47)(73,47)],
[(73,13),(73,210),(109,210),(109,13)]
...]
In order to do this I have already looked at the cv2.findContours but I couldn't get it to work with overlapping rectangles (though I could use the hierarchy model to deal with holes as that causes the contours to be merged into one.
Note that although not shown holes can be nested.
A algorithm that works roughly as follow should be able to give you the result you seek.
Get all the corner points in the image.
Randomly select 3 points to create a rectangle
Count the ratio of yellow pixels within the rectangle, accept if the ratio satisfy a threshold.
Repeat 2 to 4 until :
a) every single combination of point is complete or
b) all yellow pixel are accounted for or
c) after n number of iteration
The difficult part of this algorithm lies in step 2, creating rectangle from 3 points.
If all the rectangles were right angle, you can simply find the minimum x and y to correspond for topLeft corner and maximum x and y to correspond for bottomRight corner of your new rectangle.
But since you have off axis rectangle, you will need to check if the two vector created from the 3 points have a 90 degree angle between them before generating the rectangle.
I want to place N circles with given, common radius in the rectangle of given size, such that circles are not overlapping in Python. My current solutions are:
1) to create a set of every point in the space and remove from it points that will cause overlapping before generating next circle (but it's slow when the rectangle is big).
2) to draw the center of balls from the set of not-overlapping points (e.g. every 2r + const) (but the positions are not random enough here).
Do you have other, more efficient ideas?
so the most efficient packing in 2D is hexagonal packing and you can just hard code your program to give that packing for circles
read more about it here : https://en.wikipedia.org/wiki/Circle_packing
Let's say I have a contour which is meant to represent the shape of the hand. The issue is, the contour also contains other parts of the arm (i.e. wrist, forearm, upper arm, etc.) To find the position of the hand's center, I'm looking at the combinations (size 3) of the defect points of the convex hull, finding the center of circle which is tangent to these 3 points, and averaging the most reasonable ones together to gain a rough understanding of where the hand's center is.
With this averaged center, I'd like to be able to remove points on my given contour which don't fall inside some radius that's likely to determine the width of the hand - in other words, cutoff points that don't fall inside this circle. I could simply iterate through each contour point and remove these points, but that would be horribly inefficient because of Python loops' speed. Is there a faster or more efficient way of doing this, perhaps using some inbuilt OpenCV functions or otherwise?
Thanks!
Interesting follow-up to your other question.
You can remove the unwanted points by boolean indexing:
import numpy as np
hand_contour = np.random.rand(60,2) # you can use np.squeeze on the data from opencv to get rid of that annoying singleton axis (60,1,2)->(60,2)
# You have found the center of the palm and a possible radius
center = np.array([.3, .1])
radius = .3
mask = (hand_contour[:,0] - center[0])**2 + (hand_contour[:,1] - center[1])**2 < radius**2
within_palm = hand_contour[mask,:] # Only selects those values within that circle.
You could also mask the unwanted values, with a masked_array, but if you're not interested in keeping the original data, the above method is the way to go.