How to calculate Angle of a square object with respect to image in 2D plane using camera?

喜你入骨 提交于 2021-01-29 07:46:37

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!