任务是识别出图片中的障碍物,就是水坑。原图像在最下面。
作为新手,我首先想到通过颜色来识别,但是水坑的颜色和天空很相似,而且图中元素太多了,颜色很容易混淆,恐怕效果不好。
那么就是轮廓检测的方法了
import cv2
import numpy as np
road_1_0= cv2.imread('road1.jpg',1)
road_2_0 = cv2.imread('road2.jpg',1)
#road1的处理,使用轮廓检测,通过轮廓大小筛选到目标区域
road_1_1 = cv2.Canny(road_1_0,100,200)
road_1_4 = cv2.dilate(road_1_1,kernel=np.ones((3,3)),iterations=3)
road_1_5 = cv2.erode(road_1_4,kernel=np.ones((3,3)),iterations=1)
road_1_2 = np.ones(road_1_0.shape)
contours,hierarchy = cv2.findContours(road_1_5,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
#对轮廓面积进行降序处理,方便筛选
contours_2 = sorted(contours, key=lambda contour: cv2.contourArea(contour), reverse=True)
for c in contours_2:
area = cv2.contourArea(c)
if 1200>area >1100:
cv2.fillPoly(road_1_0,[c],(0,0,255))
elif 3150>area>3000:
cv2.fillPoly(road_1_0,[c],(0,0,255))
elif 100000>area>4000:
cv2.fillPoly(road_1_0,[c],(0,0,255))
cv2.imwrite('result_1.png',road_1_0)
这里来分析一下代码,找到轮廓线,因为这的水坑和公路的颜色相近,轮廓没有闭合,所以使用了膨胀(cv2.dilate),然后用腐蚀(cv2.erode)减少无关元素
road_1_1 = cv2.Canny(road_1_0,100,200)
road_1_4 = cv2.dilate(road_1_1,kernel=np.ones((3,3)),iterations=3)
road_1_5 = cv2.erode(road_1_4,kernel=np.ones((3,3)),iterations=1)
road_1_2 = np.ones(road_1_0.shape)
contours,hierarchy = cv2.findContours(road_1_5,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
第三部分就是把轮廓按照面积降序处理,再根据大小来筛选目标区域
#根据面积降序
contours_2 = sorted(contours, key=lambda contour: cv2.contourArea(contour), reverse=True)
#筛选
for c in contours_2:
area = cv2.contourArea(c)
if 1200>area >1100:
cv2.fillPoly(road_1_0,[c],(0,0,255))
elif 3150>area>3000:
cv2.fillPoly(road_1_0,[c],(0,0,255))
elif 100000>area>4000:
cv2.fillPoly(road_1_0,[c],(0,0,255))
cv2.imwrite('result_1.png',road_1_0)
这部分没啥好说的,这是我不断调参后的结果,正常流程为设置一个原图大小的空白图像,用np.ones(img.shape)就好,在循环里打印大小、观察轮廓,最终得到想要的轮廓大小,这部分其实花不了多长时间,比筛选颜色快多了。下面给出我调参时的代码
for c in contours_2:
area = cv2.contourArea(c)
if area >1100:
cv2.drawContours(ones_copy,[c],-1,(255,0,0))
print(area)
最终效果就是这样