Search code examples
pythonopencvcontour

Measuring width of contour at given angle in OpenCv


Given a contour in OpenCV, I can extract the width and height by using cv2.boundingRect(contour). This returns the width and height of a bounding rectangle, as illustrated by the left figure.

Given an angle, is it possible to extract the width/height of a rotated bounding rectangle, as illustrated in the right figure?

Contour illustration

I am trying to measure the length of moving objects, but I need to measure the length in the movement direction, which may sometimes be up to 45 degrees from the horizontal line.

I know there is a way of getting a rotated bounding rectangle, using cv2.minAreaRect and cv2.boxPoints, but the rotation I need will not always match the minimum area rectangle, so I need to be able to specify the angle somehow.

I only need the rotated width and height values, I don't really need the rotated contour, if that makes it easier.


Solution

  • As my comment: Why not. Support you have an angle, then you can make two orthogonality lines. Calculate the distance between pts and each line, then calc max_dist - min_dict, you will get width and height.

    My mother language is Chinese, and not I'm good at English writing. So I just turn it into code:

    #!/usr/bin/python3
    # 2017.12.13 22:50:16 CST
    # 2017.12.14 00:13:41 CST
    import numpy as np
    
    def calcPointsWH(pts, theta=0):
        # 计算离散点在特定角度的长宽
        # Measuring width of points at given angle
        th = theta * np.pi /180
        e = np.array([[np.cos(th), np.sin(th)]]).T
        es = np.array([
        [np.cos(th), np.sin(th)],
        [np.sin(th), np.cos(th)],
        ]).T
        dists = np.dot(pts,es)
        wh = dists.max(axis=0) - dists.min(axis=0)
        print("==> theta: {}\n{}".format(theta, wh))
    

    Give this diamond for testing:

    enter image description here

    pts = np.array([[100, 200],[200,  26],[300, 200],[200, 373]], np.int32)
    for theta in range(0,91, 30):
        calcPointsWH(pts, theta)
    
    
    ==> theta: 0
    [ 200.  347.]
    ==> theta: 30
    [ 173.60254038  300.51081511]
    ==> theta: 60
    [ 300.51081511  173.60254038]
    ==> theta: 90
    [ 347.  200.]
    

    Now it's 2017.12.14 00:20:55 CST, goodnight.