Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extract all bounding boxes using OpenCV Python

Tags:

I have an image that contains more than one bounding box.
Books in Bounding Boxes

I need to extract everything that has bounding boxes in them. So far, from this site I've gotten this answer:

y = img[by:by+bh, bx:bx+bw]
cv2.imwrite(string + '.png', y)

It works, however, it only gets one. How should I modify the code? I tried putting it in the loop for contours but it still spews out one image instead of multiple ones.

Thank you so much in advance.

like image 741
xandra12791 Avatar asked Jan 14 '14 01:01

xandra12791


2 Answers

there you go:

import cv2

im = cv2.imread('c:/data/ph.jpg')
gray=cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
contours, hierarchy = cv2.findContours(gray,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)[-2:]
idx =0 
for cnt in contours:
    idx += 1
    x,y,w,h = cv2.boundingRect(cnt)
    roi=im[y:y+h,x:x+w]
    cv2.imwrite(str(idx) + '.jpg', roi)
    #cv2.rectangle(im,(x,y),(x+w,y+h),(200,0,0),2)
cv2.imshow('img',im)
cv2.waitKey(0)    
like image 69
Zaw Lin Avatar answered Sep 27 '22 20:09

Zaw Lin


A simple approach is to find contours, obtain the bounding rectangle coordinates using cv2.boundingRect() then extract the ROI using Numpy slicing. We can keep a counter to save each ROI then save it with cv2.imwrite(). Here's a working example:

Input image:

enter image description here

Detected ROIs to extract highlighted in green

enter image description here

Saved ROIs

enter image description here

Code

import cv2
import numpy as np

# Load image, grayscale, Otsu's threshold 
image = cv2.imread('1.png')
original = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Find contours, obtain bounding box, extract and save ROI
ROI_number = 0
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 2)
    ROI = original[y:y+h, x:x+w]
    cv2.imwrite('ROI_{}.png'.format(ROI_number), ROI)
    ROI_number += 1

cv2.imshow('image', image)
cv2.waitKey()
like image 44
nathancy Avatar answered Sep 27 '22 19:09

nathancy