0

I found out that the .size.height and .size.width operators of OpenCV's RotatedRect class don't work in Python whereas they work in C++. Let me elaborate with a simplified code snippet:

cap = cv2.VideoCapture('video1.mp4')
filter = RandomClass(20)

while(cap.isOpened()):
    ret, frame = cap.read()              # Read a frame
    res = filter.classMain(frame)        # Process the frame
    if (res == 0):
        print('Success')                 # If processing completed, print Success
cap.release()

where the class definition is as follows:

import cv2
import numpy as np

class RandomClass:
    def __inti__(self):
        self.set_skip_first(True)
    def get_skip_first(self):
        return self.skip_first
    def set_skip_first(self, value):
        self.skip_first = value
    def classMain(self, frame):
        if not get_skip_first():
            self.expand_minRect(100)        # expand the minRect by 100 pixels
            # use the expanded rectangle for some other processing here
        else:
            self.set_skip_first(False)
        # create a mask with cv2.inRange
        contour = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE, offset=(0,0))[1]
        # iterate over each contour and find the index of the largest contour
        self.minRect = cv2.minAreaRect(np.array(self.contours[self.largest_contour_index]))
        # execute some other processing here
        return 0
    def expand_minRect(self, value):
        self.minRect.size.height = self.minRect.size.height + value
        self.minRect.size.width = self.minRect.size.width + value

The error I'm receiving is as follows. The exact lines work perfectly fine in the C++ version of the above code.

File "filename", line 106, in expand_minRect

self.minRect.size.height = self.minRect.size.height + value

AttributeError: 'tuple' object has no attribute 'size'

I tried the following. I was expecting the second printed value (of variable width2) to be greater than the first printed value (of variable width1) by value.

def expand_minRect(self, value):
    _,(width1, height1),_ = self.minRect
    print(width)
    self.minRect[1][0] = self.minRect[1][0] + value
    _,(width2,height2),_ = self.minRect
    print(w)

However it didn't work as the variable type of self.minRect[1][0] is Tuple and Tuples cannot be modified.

File "filename", line 111, in expand_minRect

self.minRect1[0] = self.minRect1[0] + value

TypeError: 'tuple' object does not support item assignment

I did some research, I couldn't find a Python documentation for RotatedRect but I found a stackoverflow answer stating that

Python still lacks of RotatedRect class

So all things to a side, assuming that the RotatedRect support in Python3 is incomplete, how can I work around this and expand the width and height of my minRect variable?

Community
  • 1
  • 1
csg
  • 8,096
  • 3
  • 14
  • 38
  • 2
    Does [this](https://docs.opencv.org/3.4/de/d62/tutorial_bounding_rotated_ellipses.html) help? – beaker Mar 03 '20 at 16:54
  • @breaker Unfortunately, no. I had seen this website before. The code extracts the corners of the RotatedRect and then draws lines connecting those corners. I, on the other hand, need to expand these corners by 100 pixels. I tried finding the equations of two lines passing through diagonal corners and find 4 new expanded corners on these two lines but that didn't work as good as the C++ code where I can simply use `minRect.size.height += value`. Is it possible to find the source-code of RotatedRect class to determine how this operation is executed under the hood? – csg Mar 03 '20 at 17:05

1 Answers1

2

According to this tutorial, minAreaRect returns a rectangle with ((center_x,center_y),(width,height),angle). Thus, if you modify your expand_minRect to recreate it with the correct components, it should work.

def expand_minRect(self, value):
    self.minRect = (self.minRect[0],                                          # keep the center
                    (self.minRect[1][0] + value, self.minRect[1][1] + value), # update the size
                    self.minRect[2])                                          # keep the angle

Note: The problem emerges from the fact that OpenCV python has a less object-oriented implementation than OpenCV c++. It does not return a struct which enables accessing each attribute by name (like ".size"). You need to know the tuple order and assumptions for each element.

ilke444
  • 2,641
  • 1
  • 17
  • 31
  • 2
    Thanks! (Tesekkurler.). That's a good idea! It solved my problem. My solution was too close. – csg Mar 03 '20 at 20:27