I'm working on a project where i have to detect a red vehicle (please see image below).
As i believe that this can be achieved with out using Deep learning (overkill in this case), i used histogram Back projection depending on the object color(red). The results were satisfying
except when there are objects other than the target red-vehicle having the same color distribution as the target (see example below my T-shirt) are in the scene, the algorithm thinks it is also an object of interest and thus detect both the object of interest and the irrelevant object (my T-shirt).
The result are
In this case, it's easy to only choose the contour that belongs to the car based on ratio and area,since the contour that belongs to the T-shirt is lager and has different ratio
I applied the follwoing example code
contours = cv2.findContours(clean, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
area_thresh1 = 500
area_thresh2 = 1000
aspect_thresh1 = 2
aspect_thresh2 = 4
result1 = image.copy()
result2 = image.copy()
for c in contours:
# get rotated rectangle from contour
# get its dimensions
# get angle relative to horizontal from rotated rectangle
rotrect = cv2.minAreaRect(c)
box = cv2.boxPoints(rotrect)
box = np.int0(box)
(center), (dim1,dim2), angle = rotrect
maxdim = max(dim1,dim2)
mindim = min(dim1,dim2)
area = dim1 * dim2
if area > 0:
aspect = maxdim / mindim
#print(area, aspect)
if area > area_thresh1 and area < area_thresh2 and aspect > aspect_thresh1 and aspect <
aspect_thresh2:
# draw contour on input
cv2.drawContours(result1,[c],0,(255,255,255),1)
# draw rectangle on input
cv2.drawContours(result2,[box],0,(255,255,255),1)
print(area, aspect)
However, as I'm working on a video, this doesn't work well in some frames since sometimes it detects shapes that fulfill the conditions like the case below
As you can see in the above binary image, an irrelevant object is detected (the below contour).
So my question is:
As you see the red vehicle to be detected always has the same shape (almost rectangle but for sure a convex shape). So how can i filter only the contour that belongs to the red vehicle using a the shape property ?(of course I mean a property other than ratio and area since some sopts of my short falls into the same area and ration boundaries of the red vehicle).
In other words, How can i filter the target object based on the exact shape of the vehicle??
Thanks in Advance
You can get shape descriptors and use some kind of rules (or machine learning) to decide if that's the right object you're searching for :
import numpy as np
import argparse
import cv2
import sys
target = cv2.imread('YourPath\\target.jpg' ,
cv2.IMREAD_COLOR)
mask = cv2.imread('YourPath\\mask.jpg',cv2.IMREAD_GRAYSCALE)
SearchImage = cv2.bitwise_and(target,target,mask = mask)
cv2.imshow("Search Region" , SearchImage)
cv2.waitKey()
#convert RGBto Lab
LabImage = cv2.cvtColor(SearchImage,cv2.COLOR_BGR2LAB)
cv2.imshow("Lab(b)" , LabImage[:, :, 1])
cv2.waitKey()
ret,Binary = cv2.threshold(LabImage[:, :, 1], 0, 255, cv2.THRESH_OTSU)
cv2.imshow('win1', Binary)
cv2.waitKey(0)
#find contours
contours, hierarchy = cv2.findContours(Binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
#create an empty image for contours
img_contours = np.zeros(target.shape)
# draw the contours on the empty image
cv2.drawContours(img_contours, contours, -1, (0,255,0), 3)
for cnt in contours:
x, y, w, h = cv2.boundingRect(cnt)
aspect_ratio = float(w) / h
area = cv2.contourArea(cnt)
x, y, w, h = cv2.boundingRect(cnt)
rect_area = w * h
extent = float(area) / rect_area
hull = cv2.convexHull(cnt)
hull_area = cv2.contourArea(hull)
solidity = float(area) / hull_area
equi_diameter = np.sqrt(4 * area / np.pi)
(x, y), (MA, ma), Orientation = cv2.fitEllipse(cnt)
print(" Width = {} Height = {} area = {} aspect ration = {} extent = {}
solidity = {} equi_diameter = {} orientation = {}".format( w , h , area ,
aspect_ratio , extent , solidity , equi_diameter , Orientation))
cv2.imshow('win1', img_contours)
cv2.waitKey(0)
OUTPUT:
Width = 42
Height = 18
area = 632.5
aspect ratio = 2.3333333333333335
extent = 0.8366402116402116
solidity = 0.9412202380952381
equi_diameter = 28.37823130579125
orientation = 89.93299865722656