Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drawing angled rectangles in OpenCV

I am using OpenCV and python to work on a project that involves body tracking, and I am using HSV values to find a skin tone then draw a box around it.

However although I can find the tracked object and draw a box around it the rectangles are always vertical, and I would like to know if there is anyway angle the rectangles so they better show the detected object, somewhat like the minEnclosingCircle function, but using a rectangle

The images probably explain what I am looking for better. The boxes that I am getting are green, and what I'm looking for I have drawn on in yellow. As you can see the mask shows and angled rectangle would also better encompass the selected area. I have also included the original image.

My code is:

import numpy as np
import cv2

# Input image
image = cv2.imread('TestIn.png')

# Converts to grey for better reulsts
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# Converts to HSV
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

# HSV values
lower_skin = np.array([5,36,53])
upper_skin = np.array([19,120,125])

mask = cv2.inRange(hsv, lower_skin, upper_skin)

mask = cv2.erode(mask, None, iterations=2)
mask = cv2.dilate(mask, None, iterations=2)

# Finds contours
im2, cnts, hierarchy = cv2.findContours(mask.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# Draws contours
for c in cnts:
    if cv2.contourArea(c) < 3000:
        continue

    (x, y, w, h) = cv2.boundingRect(c)
    cv2.rectangle(image, (x,y), (x+w,y+h), (0, 255, 0), 2)

cv2.imshow('mask', mask)
cv2.imshow('image', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

Input image:

Input Image

Output image (output boxes in green, desired boxes in yellow):

output image. output boxes in green, desired boxes in yellow

like image 643
Stump Avatar asked Apr 28 '16 17:04

Stump


People also ask

What is cv2 boundingRect?

The cv2. boundingRect() function of OpenCV is used to draw an approximate rectangle around the binary image. This function is used mainly to highlight the region of interest after obtaining contours from an image. As per the documentation there are two types of bounding rectangles: Straight Bounding Rectangle.


1 Answers

You need to use cv2.minAreaRect(...) and then cv2.boxPoints(...) to obtain a sequence of points representing the polygon in a format that can be used by other OpenCV drawing functions, such as cv2.drawContours(...) or cv2.polylines(...).


Based on the example in OpenCV documentation I added few statements to your code to achieve the desired result:

import numpy as np
import cv2

# Input image
image = cv2.imread('oaHUs.jpg')

# Converts to grey for better reulsts
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# Converts to HSV
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

# HSV values
lower_skin = np.array([5,36,53])
upper_skin = np.array([19,120,125])

mask = cv2.inRange(hsv, lower_skin, upper_skin)

mask = cv2.erode(mask, None, iterations=2)
mask = cv2.dilate(mask, None, iterations=2)

# Finds contours
im2, cnts, hierarchy = cv2.findContours(mask.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# Draws contours
for c in cnts:
    if cv2.contourArea(c) < 3000:
        continue

    (x, y, w, h) = cv2.boundingRect(c)
    cv2.rectangle(image, (x,y), (x+w,y+h), (0, 255, 0), 2)

    ## BEGIN - draw rotated rectangle
    rect = cv2.minAreaRect(c)
    box = cv2.boxPoints(rect)
    box = np.int0(box)
    cv2.drawContours(image,[box],0,(0,191,255),2)
    ## END - draw rotated rectangle

cv2.imwrite('out.png', image)

Output:

like image 136
Dan Mašek Avatar answered Sep 22 '22 14:09

Dan Mašek