Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with contours and bounding rectangle in OpenCV 2.4 - python 2.7

Tags:

I am working with openCv and python and I am dealing with Structural Analysis and Shape Descriptors. I have found this blog: http://opencvpython.blogspot.it/2012/06/contours-2-brotherhood.html that's very helpful and I have tried with a black and white image to drawing a bounding rectangle and it works. But now from an image i extract, for example, the yellow color and on that i would like to draw a bounding rectangle. The problem is that the black and white image is not uniform it has some noise and like that the code doesn't recognize the whole shape.

origianl image

black and white image

final image

And this is the code:

import numpy as np import cv2  im = cv2.imread('shot.bmp') hsv_img = cv2.cvtColor(im, cv2.COLOR_BGR2HSV) COLOR_MIN = np.array([20, 80, 80],np.uint8) COLOR_MAX = np.array([40, 255, 255],np.uint8) frame_threshed = cv2.inRange(hsv_img, COLOR_MIN, COLOR_MAX) imgray = frame_threshed ret,thresh = cv2.threshold(frame_threshed,127,255,0) contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) cnt=contours[0] x,y,w,h = cv2.boundingRect(cnt) cv2.rectangle(im,(x,y),(x+w,y+h),(0,255,0),2) cv2.imshow("Show",im) cv2.waitKey() cv2.destroyAllWindows() 
like image 255
Gianfra Avatar asked May 14 '13 08:05

Gianfra


People also ask

How do you draw a bounding box in OpenCV Python?

We use the rectangle() function to draw the bounding box around the shapes; we use the rectangle() function, which draws a rectangle around each shape. The first argument of the rectangle() function is the image on which we want to draw the bounding box.

How do I create a bounding box in OpenCV?

Working of selectROI() Function in OpenCV The bounding box is an imaginary rectangle drawn around a given object and it serves as the region of interest. To draw a bounding box around an object in the given image, we make use of a function called selectROI() function in OpenCV.

How do you connect contours in OpenCV?

go through the first contour as it is listed until you hit the closest point. Then switch to the other list, starting from the closest point you go clockwise through the other contour until it is used up. switch back to the first contour and append the rest of their points. force them into cv2 contour format.


1 Answers

Since your original image is fairly noisy, a simple fix is to remove some of the noise using cv2.medianBlur() This will remove small noise areas in your original image, and leave you with only one contour. The first few lines of your code would look like this:

im = cv2.imread('shot.bmp') im = cv2.medianBlur(im,5)    # 5 is a fairly small kernel size hsv_img = cv2.cvtColor(im, cv2.COLOR_BGR2HSV) 

However, this method is not the most robust because you must manually specify a kernel size, and the line cnt=contours[0] in your code assumes that the contour of interest is the firs in the list of contours, which is only true if there is only one contour. A more robust method is to assume that you are interested in the largest contour, which will allow you to compensate for even moderate noise.

To do this, add the lines:

# Find the index of the largest contour areas = [cv2.contourArea(c) for c in contours] max_index = np.argmax(areas) cnt=contours[max_index] 

after the line:

contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) 

Resulting in this code:

import numpy as np import cv2  im = cv2.imread('shot.bmp') hsv_img = cv2.cvtColor(im, cv2.COLOR_BGR2HSV) COLOR_MIN = np.array([20, 80, 80],np.uint8) COLOR_MAX = np.array([40, 255, 255],np.uint8) frame_threshed = cv2.inRange(hsv_img, COLOR_MIN, COLOR_MAX) imgray = frame_threshed ret,thresh = cv2.threshold(frame_threshed,127,255,0) contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)  # Find the index of the largest contour areas = [cv2.contourArea(c) for c in contours] max_index = np.argmax(areas) cnt=contours[max_index]  x,y,w,h = cv2.boundingRect(cnt) cv2.rectangle(im,(x,y),(x+w,y+h),(0,255,0),2) cv2.imshow("Show",im) cv2.waitKey() cv2.destroyAllWindows() 

Both of these methods give a result with a correct bounding box:

Bounding Box Result

N.B.
As of OpenCV 3.x the findContours() method returns 3 results (as can be seen here), so the additional return value should be caught like:

_, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPL‌​E) 
like image 190
Aurelius Avatar answered Oct 23 '22 07:10

Aurelius