问题描述
我正在一个必须检测红色车辆的项目中(请参见下图)。
由于我认为无需使用深度学习即可实现(在这种情况下过度杀伤),因此我根据对象的颜色(红色)使用了直方图反向投影。结果令人满意
场景中除了目标红色车辆以外的其他对象具有与目标相同的颜色分布(请参见我的T恤下面的示例)时,算法认为该对象也是感兴趣的对象,因此可以检测到既是感兴趣的对象又是无关的对象(我的T恤)。
结果是
在这种情况下,因为属于T恤衫的轮廓较大且具有不同的比例,所以仅根据比率和面积选择属于汽车的轮廓很容易
我应用了以下示例代码
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],(255,255,255),1)
# draw rectangle on input
cv2.drawContours(result2,[Box],1)
print(area,aspect)
但是,在我处理视频时,这在某些帧中效果不佳,因为有时它会检测到满足以下情况的形状:
如您在上面的二进制图像中看到的,检测到不相关的对象(下面的轮廓)。
所以我的问题是:
如您所见,要检测的红色车辆始终具有相同的形状(几乎是矩形,但肯定是凸形)。 那么,我该如何使用shape属性仅过滤属于红色车辆的轮廓?(当然,我指的是除比率和面积之外的其他属性,因为我的短裤的一些短袜属于同一区域和红色车辆的配给边界)。
换句话说,如何根据车辆的确切形状过滤目标对象?
预先感谢
解决方法
您可以获取形状描述符并使用某种规则(或机器学习)来确定这是否是您要搜索的对象:
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],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,0),3)
for cnt in contours:
x,y,w,h = cv2.boundingRect(cnt)
aspect_ratio = float(w) / h
area = cv2.contourArea(cnt)
x,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)
输出:
Width = 42
Height = 18
area = 632.5
aspect ratio = 2.3333333333333335
extent = 0.8366402116402116
solidity = 0.9412202380952381
equi_diameter = 28.37823130579125
orientation = 89.93299865722656
,
您可以使用近似值PolyplyDp来计算形状的近似面积,并为可被称为所需形状的范围设置阈值。