如何根据二进制视频帧中的近似形状过滤轮廓

How to filter contours based on their approximate shape in a Binary video frames

我正在做一个项目,我必须检测红色车辆(请参见下图)。

因为我相信这可以在不使用深度学习的情况下实现(在这种情况下过度杀伤),我根据对象颜色(红色)使用了直方图反投影。结果令人满意

除非场景中有与目标具有相同颜色分​​布的目标红色车辆以外的物体(见下面我的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],0,(255,255,255),1)
       # draw rectangle on input
       cv2.drawContours(result2,[box],0,(255,255,255),1)
       print(area, aspect)

但是,当我处理视频时,这在某些帧中效果不佳,因为有时它会检测到满足以下情况的形状

正如您在上面的二值图像中看到的,检测到不相关的对象(下面的轮廓)。

所以我的问题是:

如你所见,要检测的红色车辆始终具有相同的形状(几乎是矩形,但肯定是凸形)。 那么我如何使用形状 属性 过滤属于红色车辆的轮廓?(当然我的意思是 属性 除了比例和面积因为我的一些短片落入了红色车辆的相同区域和配给边界。

换句话说,如何根据车辆的确切形状过滤目标对象?

提前致谢

您可以获得形状描述符并使用某种规则(或机器学习)来确定这是否是您要搜索的正确对象:

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)

输出:

Width = 42  
Height = 18 
area = 632.5  
aspect ratio = 2.3333333333333335  
extent  = 0.8366402116402116  
solidity = 0.9412202380952381   
equi_diameter = 28.37823130579125   
orientation = 89.93299865722656

您可以使用 approxPolyDp 并计算形状的近似面积,并为可以称为您要查找的形状的范围设置阈值。