尝试改进我在 OpenCV 中的道路分割程序
Trying to improve my road segmentation program in OpenCV
我正在尝试制作一个能够识别场景中道路的程序,并继续使用形态学过滤和分水岭算法。但是,该程序会产生平庸或糟糕的结果。如果道路占据了大部分场景,它似乎还可以(不够好)。然而在其他图片中,事实证明天空被分割了(云的分水岭)。
我尝试查看是否可以执行更多图像处理以改进结果,但这是我迄今为止最好的,不知道如何继续改进我的程序。
如何改进我的程序?
代码:
import numpy as np
import cv2
from matplotlib import pyplot as plt
import imutils
def invert_img(img):
img = (255-img)
return img
#img = cv2.imread('images/coins_clustered.jpg')
img = cv2.imread('images/road_4.jpg')
img = imutils.resize(img, height = 300)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
thresh = invert_img(thresh)
# noise removal
kernel = np.ones((3,3), np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 4)
# sure background area
sure_bg = cv2.dilate(opening,kernel,iterations=3)
#sure_bg = cv2.morphologyEx(sure_bg, cv2.MORPH_TOPHAT, kernel)
# Finding sure foreground area
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
ret, sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0)
# Finding unknown region
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg,sure_fg)
# Marker labelling
ret, markers = cv2.connectedComponents(sure_fg)
# Add one to all labels so that sure background is not 0, but 1
markers = markers+1
# Now, mark the region of unknown with zero
markers[unknown==255] = 0
'''
imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
imgray = cv2.GaussianBlur(imgray, (5, 5), 0)
img = cv2.Canny(imgray,200,500)
'''
markers = cv2.watershed(img,markers)
img[markers == -1] = [255,0,0]
cv2.imshow('background',sure_bg)
cv2.imshow('foreground',sure_fg)
cv2.imshow('threshold',thresh)
cv2.imshow('result',img)
cv2.waitKey(0)
利用一些领域知识;换句话说,做一些简化的假设。即使是像 "the camera's not upside down" 和 "the pavement has a uniform hue" 这样的基本东西也会改善常见情况。
如果你能把十字路口当作一个特例,那么找到道路的边缘可能比找到道路本身更简单、更有用。
首先,分割问题很难。您希望解决方案越通用,它就越难。道路分割是一个 well-known 问题,我相信您可以找到许多从不同方向解决这个问题的论文。
帮助我获得计算机视觉问题想法的是尝试思考是什么让我很容易检测到它,而对计算机来说却如此困难。
例如,让我们看看您的图像上的道路。是什么让它从背景中脱颖而出?
- 明显的灰色。
- 总是有两条白色的肩线
- 始终位于图像的底部
- 中间总是有一条分隔线(yellow/white)
- 相当流畅
- 底部变宽并逐渐消失 horizon。
现在,在我们找到一些独特的特征之后,我们需要找到量化它们的方法,所以它对算法来说是显而易见的,因为它对我们来说是显而易见的。
- 处理 RGB(或更好 - HSV)图像,不要在开始时将其转换为灰色并丢失所有颜色数据。寻找灰色地带!
- 再次,让我们找到白色区域(在灰色区域中)。您可以尝试在肩线的特定方向上进行边缘检测。您正在寻找大约占图像高度一半的线。等...
- 让我们删除图像的上半部分。你几乎没有路,你会从算法中摆脱很多噪音。
- 见 2...
- 让我们检查局部标准偏差,或其他一些平滑度特征。
- 如果我们找到某种形状,让我们检查它是否符合我们的预期。
我知道这些只是想法,我并不认为它们很容易实现,但如果你想改进你的算法,你必须给它更多"knowledge",就像你所做的那样。
我正在尝试制作一个能够识别场景中道路的程序,并继续使用形态学过滤和分水岭算法。但是,该程序会产生平庸或糟糕的结果。如果道路占据了大部分场景,它似乎还可以(不够好)。然而在其他图片中,事实证明天空被分割了(云的分水岭)。
我尝试查看是否可以执行更多图像处理以改进结果,但这是我迄今为止最好的,不知道如何继续改进我的程序。
如何改进我的程序?
代码:
import numpy as np
import cv2
from matplotlib import pyplot as plt
import imutils
def invert_img(img):
img = (255-img)
return img
#img = cv2.imread('images/coins_clustered.jpg')
img = cv2.imread('images/road_4.jpg')
img = imutils.resize(img, height = 300)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
thresh = invert_img(thresh)
# noise removal
kernel = np.ones((3,3), np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 4)
# sure background area
sure_bg = cv2.dilate(opening,kernel,iterations=3)
#sure_bg = cv2.morphologyEx(sure_bg, cv2.MORPH_TOPHAT, kernel)
# Finding sure foreground area
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
ret, sure_fg = cv2.threshold(dist_transform,0.7*dist_transform.max(),255,0)
# Finding unknown region
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg,sure_fg)
# Marker labelling
ret, markers = cv2.connectedComponents(sure_fg)
# Add one to all labels so that sure background is not 0, but 1
markers = markers+1
# Now, mark the region of unknown with zero
markers[unknown==255] = 0
'''
imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
imgray = cv2.GaussianBlur(imgray, (5, 5), 0)
img = cv2.Canny(imgray,200,500)
'''
markers = cv2.watershed(img,markers)
img[markers == -1] = [255,0,0]
cv2.imshow('background',sure_bg)
cv2.imshow('foreground',sure_fg)
cv2.imshow('threshold',thresh)
cv2.imshow('result',img)
cv2.waitKey(0)
利用一些领域知识;换句话说,做一些简化的假设。即使是像 "the camera's not upside down" 和 "the pavement has a uniform hue" 这样的基本东西也会改善常见情况。
如果你能把十字路口当作一个特例,那么找到道路的边缘可能比找到道路本身更简单、更有用。
首先,分割问题很难。您希望解决方案越通用,它就越难。道路分割是一个 well-known 问题,我相信您可以找到许多从不同方向解决这个问题的论文。
帮助我获得计算机视觉问题想法的是尝试思考是什么让我很容易检测到它,而对计算机来说却如此困难。
例如,让我们看看您的图像上的道路。是什么让它从背景中脱颖而出?
- 明显的灰色。
- 总是有两条白色的肩线
- 始终位于图像的底部
- 中间总是有一条分隔线(yellow/white)
- 相当流畅
- 底部变宽并逐渐消失 horizon。
现在,在我们找到一些独特的特征之后,我们需要找到量化它们的方法,所以它对算法来说是显而易见的,因为它对我们来说是显而易见的。
- 处理 RGB(或更好 - HSV)图像,不要在开始时将其转换为灰色并丢失所有颜色数据。寻找灰色地带!
- 再次,让我们找到白色区域(在灰色区域中)。您可以尝试在肩线的特定方向上进行边缘检测。您正在寻找大约占图像高度一半的线。等...
- 让我们删除图像的上半部分。你几乎没有路,你会从算法中摆脱很多噪音。
- 见 2...
- 让我们检查局部标准偏差,或其他一些平滑度特征。
- 如果我们找到某种形状,让我们检查它是否符合我们的预期。
我知道这些只是想法,我并不认为它们很容易实现,但如果你想改进你的算法,你必须给它更多"knowledge",就像你所做的那样。