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


i working opencv , python , dealing structural analysis , shape descriptors. have found blog: http://opencvpython.blogspot.it/2012/06/contours-2-brotherhood.html that's helpful , have tried black , white image drawing bounding rectangle , works. image extract, example, yellow color , on draw bounding rectangle. problem black , white image not uniform has noise , code doesn't recognize whole shape.

origianl image

black , white image

final image

and code:

import numpy 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() 

since original image noisy, simple fix remove of noise using cv2.medianblur() remove small noise areas in original image, , leave 1 contour. first few lines of code this:

im = cv2.imread('shot.bmp') im = cv2.medianblur(im,5)    # 5 small kernel size hsv_img = cv2.cvtcolor(im, cv2.color_bgr2hsv) 

however, method not robust because must manually specify kernel size, , line cnt=contours[0] in code assumes contour of interest firs in list of contours, true if there 1 contour. more robust method assume interested in largest contour, allow compensate moderate noise.

to this, add lines:

# find index of largest contour areas = [cv2.contourarea(c) c in contours] max_index = np.argmax(areas) cnt=contours[max_index] 

after line:

contours, hierarchy = cv2.findcontours(thresh,cv2.retr_tree,cv2.chain_approx_simple) 

resulting in code:

import numpy 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 index of largest contour areas = [cv2.contourarea(c) 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 result correct bounding box:

bounding box result

n.b.
of opencv 3.x findcontours() method returns 3 results (as can seen here), additional return value should caught like:

_, contours, hierarchy = cv2.findcontours(thresh,cv2.retr_tree,cv2.chain_approx_simpl‌​e) 

Comments