如何改进我的OpenCV程序以仅检测人行横道?

3
我希望能够在下面的图像中检测出人行道并将其用红色填充,但程序也会检测到其他物体。这是我的代码:
import cv2
import numpy as np

img = cv2.imread("zebra_lane.jpg")
cv2.imshow("kep" ,img)
imgContour=img.copy()

def getContours(img, imgContour):
    contours, hierarchy = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)

    for cnt in contours:
        area=cv2.contourArea(cnt)
        if area>500:
            cv2.drawContours(imgContour, contours, -1, (0, 0, 255), 2)

            # peri=cv2.arcLength(cnt,True)
            # approx = cv2.approxPolyDP(cnt,0.02*peri,True)
            # # print(len(approx))
            # if len(approx)==4:
            #     x,y,w,h =cv2.boundingRect(approx)
            #     cv2.rectangle(imgContour,(x,y),(x+w,y+h), (0,0,255),1)


imgblur=cv2.GaussianBlur(img,(7,7),1)
imggray=cv2.cvtColor(imgblur,cv2.COLOR_BGR2GRAY)


imgcanny=cv2.Canny(imggray,150,90)
cv2.imshow("kep" ,imgcanny)

kernel=np.ones((1,1))
imgDil = cv2.dilate(imgcanny,kernel,iterations=1)
cv2.imshow("kep" ,imgDil)


getContours(imgDil,imgContour)
cv2.imshow("contour",imgContour)

预期的输出是什么?你想隔离出行人步行区吗? - rayryeng
预期输出是将白色交叉口填充为红色,但仅限于交叉口。 - user14618331
2
在白色/灰色步态上设置阈值。然后仅获取这些轮廓并根据轮廓的大小进行过滤以排除小的轮廓。然后,如果您想要完整的范围,可以获取凸包来组合这些区域。 - fmw42
使用人工智能技术,进行语义分割。传统方法无法胜任,这需要AI。 - Christoph Rackwitz
遵循@fmw42的方法。这是一个非常明智的选择。 - rayryeng
1个回答

3

以下是在Python/OpenCV中实现此过程的一种方法:

  • 读取输入
  • 对白色/灰色人行道条纹进行阈值处理
  • 应用形态学开闭操作
  • 获取外部轮廓
  • 按面积筛选轮廓并保留好的轮廓
  • 在输入上绘制好的轮廓
  • 合并轮廓
  • 计算合并轮廓的凸包
  • 在输入上绘制凸包
  • 保存结果

输入:

enter image description here

import cv2
import numpy as np

# read image
img = cv2.imread('walkway.jpg')

# threshold on white/gray sidewalk stripes
lower = (100,130,130)
upper = (180,200,200)
thresh = cv2.inRange(img, lower, upper)


# apply morphology close to fill interior regions in mask
kernel = np.ones((3,3), np.uint8)
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = np.ones((5,5), np.uint8)
morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel)

# get contours
cntrs = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cntrs = cntrs[0] if len(cntrs) == 2 else cntrs[1]

# filter on area
contours = img.copy()
good_contours = []
for c in cntrs:
    area = cv2.contourArea(c)
    if area > 200:
        cv2.drawContours(contours, [c], -1, (0,0,255), 1)
        good_contours.append(c)

# combine good contours
contours_combined = np.vstack(good_contours)

# get convex hull
result = img.copy()
hull = cv2.convexHull(contours_combined)
cv2.polylines(result, [hull], True, (0,0,255), 2)

# write result to disk
cv2.imwrite("walkway_thresh.jpg", thresh)
cv2.imwrite("walkway_morph.jpg", morph)
cv2.imwrite("walkway_contours.jpg", contours)
cv2.imwrite("walkway_result.jpg", result)

# display it
cv2.imshow("THRESH", thresh)
cv2.imshow("MORPH", morph)
cv2.imshow("CONTOURS", contours)
cv2.imshow("RESULT", result)
cv2.waitKey(0)

阈值图像:

输入图片描述

形态学图像:

输入图片描述

轮廓图像:

输入图片描述

结果:

输入图片描述


哇塞非常感谢!“轮廓图像”就是我想要的。矩形只需要填充红色,然后完成。 - user14618331
1
由于这是课堂作业,你从我的帖子中学到了什么新知识? - fmw42
许多有用的东西。 - user14618331

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接