Measuring width of contour at given angle in OpenCv

Question:

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.

Asked By: Erlend D.

||

Answers:

use

cv2.minAreaRect(cnt)

Here you can find here complete example and explanation.

Edit: minAreaRect is actually what you need, what’s the problem in taking width and height from an oriented rectangle?

Answered By: Moia

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.

Answered By: Kinght 金
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.