基于深度图的物块检测 (OpenCV)

这几天接触了小车移动物块的项目,其中的视觉算法基于opencv,方法虽然简单效果却很nice,今天对团队的算法做个记录,

方法原理:帧差检测,将带有检测目标的深度图与无目标的背景图做差,得到感兴趣目标的位置。具体步骤如下,

1、图片读取

import cv2
import numpy as np


ref_path = 'C:\Users/15989\Desktop\imgs/1.png'
cur_path = 'C:\Users/15989\Desktop\imgs/201.png'

cur_img = cv2.imread(cur_path, -1)
ref_img = cv2.imread(ref_path, -1)

由于图片是16位的深度图,为了方便查看就对图片进行了归一化,操作如下:

def norm(img):
    img = (img - img.min()) / (img.max() - img.min())
    img *= 255
    return img

读取图片如下 (背景图/目标图): 

基于深度图的物块检测 (OpenCV)_第1张图片

基于深度图的物块检测 (OpenCV)_第2张图片2、做帧差

diff_frame = cv2.absdiff(cur_img, ref_img)

3、选取感兴趣区域

diff_frame_roi = diff_frame[200:, 200:540]

4、将图片转成二值图

frame_bin = cv2.inRange(diff_frame_roi, 20, 100)

5、闭运算 (先膨胀,后腐蚀),消除小型的黑洞

kernel = np.ones((3, 3), dtype=np.uint8)
closing = cv2.morphologyEx(frame_bin, cv2.MORPH_CLOSE, kernel)

6、寻找目标轮廓

contours, _ = cv2.findContours(closing, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

7、找到包含轮廓的最小外接圆并求出对应半径,对轮廓半径进行过滤,计算符合要求的轮廓的最小外接矩形,对外接矩形的宽高及它们的比例进行过滤,选取合适大小的目标 (调参主要集中在这一环节)

x_obj, y_obj = 0, 0
w, h = 0, 0
xl, yl = [], []
wl, hl = [], []
for cont in contours:
    (x, y), radius = cv2.minEnclosingCircle(cont)
    if radius > 13 and radius < 28:
        rect = cv2.minAreaRect(cont)
        x_obj, y_obj = rect[0]
        w, h = rect[1]
        if w/h > 1.5 or w/h < 0.5 or w*h < 500:
            continue
        else:
            xl.append(x_obj)
            yl.append(y_obj)
            wl.append(w)
            hl.append(h)

8、 得到目标最终位置,由于第3步中对图片进行了裁剪,因此需要将上一步得到的坐标进行转换,转换成原图坐标并在图片中框出目标所在位置

x_final = [xi + 200 for xi in xl]
y_final = [yi + 200 for yi in yl]
for x_f, y_f, w_f, h_f in zip(x_final, y_final, wl, hl):
      cv2.rectangle(cur_img, (int(x_f - w_f / 2), int(y_f - h_f / 2)), (int(x_f + w_f / 2), int(y_f + h_f / 2)), (0, 0, 0), thickness=2)

基于深度图的物块检测 (OpenCV)_第3张图片

你可能感兴趣的:(目标检测,计算机视觉,opencv,人工智能)