Skip to content

Instantly share code, notes, and snippets.

@bigsnarfdude
Last active May 19, 2022 12:18
Show Gist options
  • Save bigsnarfdude/d811e31ee17495f82f10db12651ae82d to your computer and use it in GitHub Desktop.
Save bigsnarfdude/d811e31ee17495f82f10db12651ae82d to your computer and use it in GitHub Desktop.
[boundingBox] opencv example python - Contours – bounding box, minimum area rectangle, and minimum enclosing circle
import cv2
import numpy as np
# read and scale down image
# wget https://bigsnarf.files.wordpress.com/2017/05/hammer.png #black and white
# wget https://i1.wp.com/images.hgmsites.net/hug/2011-volvo-s60_100323431_h.jpg
img = cv2.pyrDown(cv2.imread('2011-volvo-s60_100323431_h.jpg', cv2.IMREAD_UNCHANGED))
# threshold image
ret, threshed_img = cv2.threshold(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY),
127, 255, cv2.THRESH_BINARY)
# find contours and get the external one
contours, hier = cv2.findContours(threshed_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
#image, contours, hier = cv2.findContours(threshed_img, cv2.RETR_TREE,
# cv2.CHAIN_APPROX_SIMPLE)
# with each contour, draw boundingRect in green
# a minAreaRect in red and
# a minEnclosingCircle in blue
for c in contours:
# get the bounding rect
x, y, w, h = cv2.boundingRect(c)
# draw a green rectangle to visualize the bounding rect
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
# get the min area rect
rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)
# convert all coordinates floating point values to int
box = np.int0(box)
# draw a red 'nghien' rectangle
cv2.drawContours(img, [box], 0, (0, 0, 255))
# finally, get the min enclosing circle
(x, y), radius = cv2.minEnclosingCircle(c)
# convert all values to int
center = (int(x), int(y))
radius = int(radius)
# and draw the circle in blue
img = cv2.circle(img, center, radius, (255, 0, 0), 2)
print(len(contours))
cv2.drawContours(img, contours, -1, (255, 255, 0), 1)
cv2.imshow("contours", img)
cv2.imshow("contours", img)
while True:
key = cv2.waitKey(1)
if key == 27: #ESC key to break
break
cv2.destroyAllWindows()
@crowledj
Copy link

nice ! just working on a project with python's openCV right now

@RonKG
Copy link

RonKG commented Nov 10, 2017

Very clean to read code. Thanks!

@JoshuaLelon
Copy link

It doesn't work right out of the box for me.

I did download the file beforehand, but python (I'm using 3.6) doesn't like line 49.

Just to see if it worked otherwise, I commented it out, and it runs but nothing shows up (i.e. the screen is black). I can press esc and exit, though.

Something curious:

print(len(contours)) prints 0

That's all I've investigated so far.

@Midun-S
Copy link

Midun-S commented Mar 1, 2018

Even i got the same error. Just erase line number 46 to 51 and replace it with
cv2.waitKey(0) // here the window waits until user manually closes

else try
if cv2.waitKey(0) & 0xFF == ord('q'):
break //here the window closes when the letter q is pressed

@abunesh
Copy link

abunesh commented Mar 26, 2018

hi i was using the code to get a bounding box over shaded objects in a picture.for eg, in the pic included, the car is shaded in red and i'd just like the bounding box to be over the car. however with this code the bounding box is generated over everything. how do i tweak it to get what i want, which is just a bounding box over the objects in the pic that is shaded?.
bboxwrong

@25b3nk
Copy link

25b3nk commented Mar 27, 2018

Clean code! Thanks!

@MoeinMDN
Copy link

verrrrrrrrrrrrrry good man !

@DigiPeters
Copy link

How could i make this work when i use a program that retrieves multiple images from google and can pass them through the process?
Cheers

@hoai97nam
Copy link

thank you very muchhhh

@hasnainmamdani
Copy link

I get the following error when using the provided hammer.png image:
`---------------------------------------------------------------------------
error Traceback (most recent call last)
in
3
4 # threshold image
----> 5 ret, threshed_img = cv2.threshold(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)
6 # find contours and get the external one
7 image, contours, hier = cv2.findContours(threshed_img, cv2.RETR_TREE,

error: OpenCV(3.4.2) /Users/travis/build/skvark/opencv-python/opencv/modules/imgproc/src/color.hpp:253: error: (-215:Assertion failed) VScn::contains(scn) && VDcn::contains(dcn) && VDepth::contains(depth) in function 'CvtHelper'
`

Which version of opencv are you using?

@mali30
Copy link

mali30 commented Jun 5, 2019

I am having an issue with line 49. Has anyone resolved this?

@bigsnarfdude
Copy link
Author

latest revision - works/tested with python 3.7.1 and open CV 4.1.0

@Mythili-pixel
Copy link

import cv2
import numpy as np
image = cv2.imread('d.jpg',-1)
paper = cv2.resize(image,(500,500))
ret, thresh_gray = cv2.threshold(cv2.cvtColor(paper, cv2.COLOR_BGR2GRAY),
200, 255, cv2.THRESH_BINARY)
image, contours, hier = cv2.findContours(thresh_gray, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
for c in contours:
rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)
# convert all coordinates floating point values to int
box = np.int0(box)
# draw a green 'nghien' rectangle
cv2.drawContours(paper, [box], 0, (0, 255, 0),1)

cv2.imshow('paper', paper)
cv2.imwrite('paper.jpg',paper)

I tried the above code for zebra line detection in an image.It shows output like this.
output.By I need to detect the entire block of zebra crossing .how is to be done?

@Hungprovp
Copy link

Hungprovp commented Jul 14, 2021

hi i was using the code to get a bounding box over shaded objects in a picture.for eg, in the pic included, the car is shaded in red and i'd just like the bounding box to be over the car. however with this code the bounding box is generated over everything. how do i tweak it to get what i want, which is just a bounding box over the objects in the pic that is shaded?.
bboxwrong

Tôi nghĩ rằng bạn thử so sánh các diện tích các đường bao đã thu được trên ảnh:
Đây là mã của tôi:
def get_contours(img_read_img, area_min_thresh=AREA):
img_gray = cv2.cvtColor(img_read_img, cv2.COLOR_BGR2GRAY)
invert_img = cv2.bitwise_not(img_gray)
retval, im_bw = cv2.threshold(invert_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
contours, hier = cv2.findContours(im_bw, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
contours = list(filter(lambda x: cv2.contourArea(x) > area_min_thresh, contours))
# img_contours = np.zeros(img_read_img.shape)
# cv2.drawContours(img_contours, contours, -1, (0, 255, 0), 3)
max_area = cv2.contourArea(contours[0])
max_id = 0
for i, c in enumerate(contours):
area = cv2.contourArea(c)
if area > max_area:
max_area = area
max_id = i
max_contours = contours[max_id]
cv2.drawContours(img_read_img, [max_contours], -1, (0, 0, 255), 2)
# cv2.imshow("contour", img_read_img)
# cv2.waitKey(0)
return img_read_img

@anamtaamin
Copy link

Can it work for 2 page PDF?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment