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

问题描述

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

Main image

由于我认为无需使用深度学习即可实现(在这种情况下过度杀伤),因此我根据对象的颜色(红色)使用了直方图反向投影。结果令人满意

result

场景中除了目标红色车辆以外的其他对象具有与目标相同的颜色分布(请参见我的T恤下面的示例)时,算法认为该对象也是感兴趣的对象,因此可以检测到既是感兴趣的对象又是无关的对象(我的T恤)。

second case

结果是

enter image description here

在这种情况下,因为属于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)

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

result2

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

所以我的问题是:

如您所见,要检测的红色车辆始终具有相同的形状(几乎是矩形,但肯定是凸形)。 那么,我该如何使用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

definition

,

您可以使用近似值PolyplyDp来计算形状的近似面积,并为可被称为所需形状的范围设置阈值。