如何根据二值视频帧中轮廓的近似形状对其进行过滤

问题描述

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

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

除非场景中存在与目标具有相同颜色分布的目标红色车辆以外的其他对象(请参见我的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)
但是,当我处理视频时,这在某些帧中不能很好地工作,因为有时它会检测到满足以下条件的形状

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

所以我的问题是:

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

相关文章