Compute the centroid of a rectangle in python - python

I want to compute the centroid of rectangle, The coordinates of rectangle are as follows:
co_ord = (601, 1006,604, 1009) ## (xmin,ymin,xmax,ymax)
Can someone point to an easy way.
Thanks

The centroid of a rectangle with opposite corners (x1, y1) and (x2, y2) lies at the center of that rectangle ((x1+x2)/2, (y1+y2)/2)

First, I am assuming that by saying centroid, you mean center. Next, I assume that the coord tuple is in the format: (x, y, width, height). In that case, it would be done this way:
coord = (601, 1006, 604, 1009)
centerCoord = (coord[0]+(coord[2]/2), coord[1]+(coord[3]/2))
where centerCoord would be the coordinates of the center in the format (x, y).

If you have the right coord of the rectangle, you can easily compute the centroid point coordinates with a formula:
If you have the 2 opposite points of the rectangle, you can use this:
Point A: X1; Y1
Point B: X2; Y2
Computed centroid points:
Coord X: (x1+x2)/2
Coord Y: (y1+y2)/2
Just a suggestion:
You can write a checking part in your program. You should check the parameters which your program get. It's not required for the basic running but it would be better if the program checks the rectangle is a real rectangle.

I think this should brighten things up for you. I will use the openCV library to make the example more understandable.
To find a center you need to coordinates: x and y.
# Draw a rectangle on the image. pt1 = left upper corner, pt2 = right bottom corner
cv2.rectangle(img=your_image, pt1=(px1_width, px2_height), pt2=(px3_width, px4_height), color=(0, 255, 0), thickness=3)
# Calculate the center point of rectangle
x, y = (px1_width + px3_width) // 2, (px2_height + px4_height) // 2
# Draw a circle in the center of rectangle
cv2.circle(img=your_image, center=(x, y), radius=3, color=(0, 255, 0), thickness=3)

Related

What is the easy way to crop a part of image using Python OpenCV

I have below code to crop a part of image:
import cv2
def on_mouse(event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONDOWN:
print("X: {} | Y: {}".format(x, y))
win_name = "Image"
cv2.namedWindow(win_name)
cv2.setMouseCallback(win_name, on_mouse)
img = cv2.imread('park.jpg')
cropImg = img[179:470, 511:645]
cv2.imshow(win_name, img)
cv2.imshow("Crop", cropImg)
cv2.waitKey(0)
cv2.destroyAllWindows()
In the above code, you can see that I have defined a function call on_mouse which basically gives us the coordinates (x, y) wherever the mouse clicks on the image. This helps in getting the x1, y1 and x2, y2 coordinates of the area we want to crop. In below image, I am trying to crop the area of giraffe. So I clicked on top left corner near giraffe which gave me the coordinates as X: 470 | Y: 179 and then I clicked bottom right corner of the giraffe which gave me the coordinates of X: 645 | Y: 511. When using them in above code, it gives below output
Below is the original image
Can anyone please help me understand how can I crop it and what does these x1, y1 and x2, y2 denotes? Thanks
The logic they designed that different than you think. It looks like:
cropImg = img[rowStart:rowEnd, colsStart:colsEnd]
It means first 2 couple you need to define row start and end coordinates which means Y axis coordinates and then column start and end coordinates which means X axis coordinates. So the line need to be changed in your code as:
cropImg = img[170:511,470:645]
Your result will change like :
(x1, y1) are the coordinates of starting point, while (x2, y2) are the end points in the image. In a rectange you can think of them as top-left corner is (x1, y1) while (x2, y2) is bottom-right corner - or just like width and height.
But while cropping they have a little reverse format
cropImage = image[ y1: y2 , x1: x2]
# or
cropImage = image[ Y: H, X: W ]

Finding rotation of an object that has contours

I have this image of rectangular objects:
I want to be able to find the angle of rotation of each object (the circle facing up being 180 degrees).
My Idea: I will first locate each part and draw a contour around each rectangular object, then I will identify each circle within that object and draw a contour. I will draw a straight line that will act as a constant in the center of the image then I will draw a straight line on each part with the 'North' side of the line going towards the small circle. Then using the constant and that line find the angle between the two lines.
So how would I go about doing this? I'm open to other ideas, but this is the simplest I could come up with and I'm not sure how to go about doing it.
This is what I have. I need to index each contour and add numbers to identify each one once its drawn. AreaMin & AreaMax are trackbars for area.
if areaMin < area < areaMax:
cv2.drawContours(imgContour, cnt, -1, (255, 0, 0), 7)
peri = cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, 0.02 * peri, True)
x , y , w, h = cv2.boundingRect(approx)
cv2.rectangle(imgContour, (x , y ), (x + w , y + h ), (255, 0, 0), 5)
I think you could calculate the length of two sides of the rectangle and their ratio, and then use math.atan() method to get the angle

Convert child location to parent location coordinates

I have a bigger area where there are smaller parts inside. Like in this image I have point inside smaller and coordinates are 2.5, 2.5. How I calculate its location in parent coordinates? Is there a pythonic way?
#GoodDeeds "And when you mean parent coordinates, do you mean scaled up by the ratio the parent is to the child?" Yes
Assuming the coordinate system is fixed, and the image dimensions are parallel to the axes:
1. Normalize the coordinates to [0, 1]:
This tells you the fraction of the image covered by the coordinate along each dimension. This fraction remains constant when you scale up the image.
Given a coordinate (x, y), and an image of dimensions (w, h), the normalized coordinates are given by (x/w, y/h). If the origin is not at (0, 0), but at some (x0, y0), it is given by ((x-x0)/w, (y-y0)/h).
2. Scale up the coordinates
Given a normalized coordinate (x, y), for a parent image with dimensions (W, H), the scaled coordinate will be (x*W, y*H). If the origin is not at (0, 0), but at some (x0, y0), it is given by (x*W+x0, y*H+y0).
Combining the two steps, since the origin for both images is the same at (0, 0), and substituting w = h = 5, W = H = 50, for a coordinate (x, y), the transformed coordinate (x', y') is given by:
(x', y') = (50*x / 5, 50*y / 5) = (10*x, 10*y).
So, in your case, (2.5, 2.5) will be mapped to (25, 25).

Does anybody know how to get the X and Y of a drawn circle?

I can't figure out how to get the X and Y coordinates of a drawn circle
(example: pygame.draw.circle(Surface, color, pos(x,y), radius, width=0))
How could I get the X and y and use it in possibly making another circle go towards those codinates? if anybody knows how it would help a lot...
I am a bit baffled tbh.
import pygame
x, y = 100, 100
r = 50
black = (0, 0, 0)
red = (255, 0, 0)
(... screen stuff ...)
pygame.draw.circle(screen, black, (x,y), r)
pygame.draw.circle(screen, red, (x,y), r / 2)
You should already have the coordinates somewhere in your program. If you want to re-use them, you're going to have to store the coordinates into variables, then you can mess around with the coordinates. So just store the coordinates and draw a second one from there. Hope this helps.

Python PIL: How to draw an ellipse in the middle of an image?

I seem to be having some trouble getting this code to work:
import Image, ImageDraw
im = Image.open("1.jpg")
draw = ImageDraw.Draw(im)
draw.ellipse((60, 60, 40, 40), fill=128)
del draw
im.save('output.png')
im.show()
This should draw an ellipse at (60,60) which is 40 by 40 pixels. The image returns nothing.
This code works fine however:
draw.ellipse ((0,0,40,40), fill=128)
It just seems that when i change the first 2 co-ords (for where the ellipse should be placed) it won't work if they are larger than the size of the ellipse to be drawn. For example:
draw.ellipse ((5,5,15,15), fill=128)
Works, but only shows part of the rect. Whereas
draw.ellipse ((5,5,3,3), fill=128)
shows nothing at all.
This happens when drawing a rectangle too.
The bounding box is a 4-tuple (x0, y0, x1, y1) where (x0, y0) is the top-left bound of the box and (x1, y1) is the lower-right bound of the box.
To draw an ellipse to the center of the image, you need to define how large you want your ellipse's bounding box to be (variables eX and eY in my code snippet below).
With that said, below is a code snippet that draws an ellipse to the center of an image:
from PIL import Image, ImageDraw
im = Image.open("1.jpg")
x, y = im.size
eX, eY = 30, 60 #Size of Bounding Box for ellipse
bbox = (x/2 - eX/2, y/2 - eY/2, x/2 + eX/2, y/2 + eY/2)
draw = ImageDraw.Draw(im)
draw.ellipse(bbox, fill=128)
del draw
im.save("output.png")
im.show()
This yields the following result (1.jpg on left, output.png on right):
The ellipse function draws an ellipse within a bounding box. So you need to use draw.ellipse((40,40,60,60)) or other coordinates where the top left is smaller than the bottom right.

Categories