Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python extract multiple objects from image opencv

I am trying to extract object from an image using the color using OpenCV, I have tried by inverse thresholding and grayscale combined with cv2.findContours() but I am unable to use it recursively. Furthermore I can't figure out how to "cut out" the match from the original image and save it to a single file.

enter image here

EDIT

~
import cv2
import numpy as np

# load the images
empty = cv2.imread("empty.jpg")
full = cv2.imread("test.jpg")

# save color copy for visualization
full_c = full.copy()

# convert to grayscale
empty_g = cv2.cvtColor(empty, cv2.COLOR_BGR2GRAY)
full_g = cv2.cvtColor(full, cv2.COLOR_BGR2GRAY)

empty_g = cv2.GaussianBlur(empty_g, (51, 51), 0)
full_g = cv2.GaussianBlur(full_g, (51, 51), 0)
diff = full_g - empty_g

#  thresholding

diff_th = 
cv2.adaptiveThreshold(full_g,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 
cv2.THRESH_BINARY,11,2)

# combine the difference image and the inverse threshold
zone = cv2.bitwise_and(diff, diff_th, None)

# threshold to get the mask instead of gray pixels
_, zone = cv2.threshold(bag, 100, 255, 0)

# dilate to account for the blurring in the beginning
kernel = np.ones((15, 15), np.uint8)
bag = cv2.dilate(bag, kernel, iterations=1)

# find contours, sort and draw the biggest one
contours, _ = cv2.findContours(bag, cv2.RETR_TREE,
                              cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
i = 0
while i < len(contours):
    x, y, width, height = cv2.boundingRect(contours[i])
    roi = full_c[y:y+height, x:x+width]
    cv2.imwrite("piece"+str(i)+".png", roi)
    i += 1

Where empty is just a white image size 1500 * 1000 as the one above and test is the one above.

This is what I came up with, only downside, I have a third image instead of only the 2 expected showing a shadow zone now...

like image 597
user3491125 Avatar asked Jun 14 '19 19:06

user3491125


People also ask

How do you track multiple objects?

Tracking multiple objects requires detection, prediction, and data association. Detection: Detect objects of interest in a video frame. Prediction: Predict the object locations in the next frame. Data association: Use the predicted locations to associate detections across frames to form tracks.


1 Answers

Here's a simple approach:

  1. Obtain binary image. Load the image, grayscale, Gaussian blur, Otsu's threshold, then dilate to obtain a binary black/white image.

  2. Extract ROI. Find contours, obtain bounding boxes, extract ROI using Numpy slicing, and save each ROI


Binary image (Otsu's thresholding + dilation)

enter image description here

Detected ROIs highlighted in green

enter image description here

To extract each ROI, you can find the bounding box coordinates using cv2.boundingRect(), crop the desired region, then save the image

x,y,w,h = cv2.boundingRect(c)
ROI = original[y:y+h, x:x+w]

First object

Second object

import cv2

# Load image, grayscale, Gaussian blur, Otsu's threshold, dilate
image = cv2.imread('1.jpg')
original = image.copy()
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5,5), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,7))
dilate = cv2.dilate(thresh, kernel, iterations=1)

# Find contours, obtain bounding box coordinates, and extract ROI
cnts = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
image_number = 0
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(image_number), ROI)
    image_number += 1

cv2.imshow('image', image)
cv2.imshow('thresh', thresh)
cv2.imshow('dilate', dilate)
cv2.waitKey()
like image 107
nathancy Avatar answered Sep 22 '22 12:09

nathancy