问题
I have captured an image using a webcam, attached upside-down above a table horizontally. On the table, I have a square object or piece of card. I have successfully detected the object and found its center coordinates (centroid). Now I want to find the rotation angle of the object with respect to the image. Considering everything in the 2D image plane. How can I calculate the angle? This image represents what I trying to achieve:
回答1:
I got the Solution. I write the code to perform the required operation as I said in my Question above. I am using OpenCV 4 + Python 3.8.3 + Spyder IDE
This is my working code:
# This code is used to Find the Origin and Rotation Angle of a Rectangle
#First of all place a blue colored rectangle card on the table below the camera
# Then execute the code. The code will detect the Rectangle in Blue color then find the origin and rotation values.
#[Resources]
# https://stackoverflow.com/questions/34237253/detect-centre-and-angle-of-rectangles-in-an-image-using-opencv
# https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_contours/py_contours_begin/py_contours_begin.html#how-to-draw-the-contours
# https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_contours/py_contour_features/py_contour_features.html#b-rotated-rectangle
# https://stackoverflow.com/questions/52247821/find-width-and-height-of-rotatedrect
import numpy as np
import cv2
import sys
import yaml
import os
import warnings
warnings.filterwarnings("ignore")
#Global Variables
cx = 0.0 #x locaton of Rectangle
cy = 0.0 #y location of Rectangle
angle = 0.0 #Angle of rotation of Rectangle
if __name__ == "__main__":
while(1):
try:
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
while(1):
_,frame = cap.read()
k = cv2.waitKey(5)
if k == 27: #exit by pressing Esc key
cv2.destroyAllWindows()
sys.exit()
if k == 13: #Save the centroid and angle values of the rectangle in a file
result_file = r'rectangle_position.yaml'
try:
os.remove(result_file) #Delete old file first
except:
pass
print("Saving Rectangle Position Matrix in: ",result_file)
data={"rect_position": [cx,cy,angle]}
with open(result_file, "w") as f:
yaml.dump(data, f, default_flow_style=False)
#Detecting Blue Color
red = np.matrix(frame[:,:,2]) #extracting red layer (layer No 2) from RGB
green = np.matrix(frame[:,:,1]) #extracting green layer (layer No 1) from RGB
blue = np.matrix(frame[:,:,0]) #extracting blue layer (layer No 0) from RGB
#it will display only the Blue colored objects bright with black background
blue_only = np.int16(blue)-np.int16(red)-np.int16(green)
blue_only[blue_only<0] =0
blue_only[blue_only>255] =255
blue_only = np.uint8(blue_only)
# cv2.namedWindow('blue_only', cv2.WINDOW_AUTOSIZE)
# cv2.imshow("blue_only",blue_only)
# cv2.waitKey(1)
#https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_thresholding/py_thresholding.html#otsus-binarization
#Gaussian filtering
blur = cv2.GaussianBlur(blue_only,(5,5),cv2.BORDER_DEFAULT)
#Otsu's thresholding
ret3,thresh = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cv2.namedWindow('Threshold', cv2.WINDOW_AUTOSIZE)
cv2.imshow("Threshold",thresh)
cv2.waitKey(1)
#Finding Conture of detected Rectangle
contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
for contour in contours:
area = cv2.contourArea(contour)
if area>100000:
contours.remove(contour)
cnt = contours[0] #Conture of our rectangle
#https://stackoverflow.com/a/34285205/3661547
#fit bounding rectangle around contour
rotatedRect = cv2.minAreaRect(cnt)
#getting centroid, width, height and angle of the rectangle conture
(cx, cy), (width, height), angle = rotatedRect
#centetoid of the rectangle conture
cx=int(cx)
cy=int(cy)
print (cx,cy) #centroid of conture of rectangle
# we want to choose the Shorter edge of the rotated rect to compute the angle between Vertical
#https://stackoverflow.com/a/21427814/3661547
if(width > height):
angle = angle+180
else:
angle = angle+90
print("Angle b/w shorter side with Image Vertical: \n", angle)
#Draw rectangle around the detected object
#https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_contours/py_contours_begin/py_contours_begin.html#how-to-draw-the-contours
im = cv2.drawContours(frame,[cnt],0,(0,0,255),2)
cv2.circle(im, (cx,cy), 2,(200, 255, 0),2) #draw center
cv2.putText(im, str("Angle: "+str(int(angle))), (int(cx)-40, int(cy)+60), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,255), 1, cv2.LINE_AA)
cv2.putText(im, str("Center: "+str(cx)+","+str(cy)), (int(cx)-40, int(cy)-50), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,255), 1, cv2.LINE_AA)
cv2.namedWindow('Detected Rect', cv2.WINDOW_AUTOSIZE)
cv2.imshow('Detected Rect',im)
cv2.waitKey(1)
except Exception as e:
print("Error in Main Loop\n",e)
cv2.destroyAllWindows()
sys.exit()
cv2.destroyAllWindows()
The code is working well and calculation the origin of the Rectangle as well as its rotation angle with respect to Image Vertical.
The Result:
I got help from these links:
- Detect centre and angle of rectangles in an image using Opencv
- https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_contours/py_contours_begin/py_contours_begin.html#how-to-draw-the-contours
- https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_contours/py_contour_features/py_contour_features.html#b-rotated-rectangle
- Find width and height of RotatedRect
来源:https://stackoverflow.com/questions/64621016/how-to-calculate-angle-of-a-square-object-with-respect-to-image-in-2d-plane-usin