python图像处理初探——基于hough变换的直线道路识别

暑期实习的工作是基于遥感地图的道路识别工作,在前期的论文调研过程中,基于自己的水平选择了复现 hough变换的方法,也算是直线处理的经典算法。重要的是,复习了数字图像处理的各种流程
1.引库
opencv库进行图像的处理
numpy库进行多维数组的处理

import cv2
import numpy as np

2.基本图像处理
(以下的过程不一定都要用到,我只是顺便都复习了一下)

image = cv2.imread('road1.png')

图像锐化

kernel2 = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32)
dst = cv2.filter2D(image, -1, kernel=kernel2)

全局阈值(二值化)

gray = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)

重点是形态学中结构元素的选取,我直接复现论文中的4个结构元素
分别按照不同的方向进行腐蚀筛选

卷积核

F=np.array([[0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0],
           [1, 1, 0, 0, 0, 0, 0],
           [0, 0, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 0, 1, 1],
           [0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0]])
F1=np.array([[0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 1, 1],
           [0, 0, 1, 1, 1, 0, 0],
           [1, 1, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0]])
F2=np.array([[0, 0, 0, 0, 0, 1, 0],
           [0, 0, 0, 0, 1, 0, 0],
           [0, 0, 0, 0, 1, 0, 0],
           [0, 0, 0, 1, 0, 0, 0],
           [0, 0, 1, 0, 0, 0, 0],
           [0, 0, 1, 0, 0, 0, 0],
           [0, 1, 0, 0, 0, 0, 0]])
F3=np.array([[0, 1, 0, 0, 0, 0, 0],
           [0, 0, 1, 0, 0, 0, 0],
           [0, 0, 1, 0, 0, 0, 0],
           [0, 0, 0, 1, 0, 0, 0],
           [0, 0, 0, 0, 1, 0, 0],
           [0, 0, 0, 0, 1, 0, 0],
           [0, 0, 0, 0, 0, 1, 0]])

data=np.array(F, dtype='uint8')
data1=np.array(F1, dtype='uint8')
data2=np.array(F2, dtype='uint8')
data3=np.array(F3, dtype='uint8')

还有一些是opencv自带的结构元素函数 可以直接构建 也放在下面
根据需要自己选择是矩形还是椭圆形的核进行形态学优化

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
kernel1 = np.ones((2, 2), np.uint8)
kernel3 = cv2.getStructuringElement(cv2.MORPH_RECT,(2,2))

形态学运算

腐蚀,膨胀,开和闭 (腐蚀和膨胀放到后面的Hough函数里了)

closing = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel)
opening = cv2.morphologyEx(closing, cv2.MORPH_OPEN, kernel)

图像反转

cv2.bitwise_not(binary, binary)

霍夫直线检测

def houghtest(binarys, datas):
    res = cv2.dilate(binarys, datas, iterations=1)
    res = cv2.erode(res, datas, iterations=1)
    edges = cv2.Canny(res, 50, 150, apertureSize=3)
    lines = cv2.HoughLinesP(edges, 1, np.pi/360, 100, minLineLength=10, maxLineGap=100)
    for line in lines:
        x1, y1, x2, y2 = line[0]
        cv2.line(image, (x1, y1), (x2, y2), (0, 255, 0), 2)
        k = -(y2 - y1) / (x2 - x1)
    cv2.imshow('houghlines', image)
    cv2.waitKey(0)

霍夫直线检测中,先进行了形态学的调整,接着通过canny算子拿到图形的边缘信息,最后通过累计概率霍夫检测函数cv2.HoughLinesP进行运算,这个函数的参数如下

  • 第一个参数,InputArray类型的image,输入图像,即源图像,需为8位的单通道二进制图像,可以将任意的源图载入进来后由函数修改成此格式后,再填在这里。

  • 第二个参数,InputArray类型的lines,经过调用HoughLinesP函数后后存储了检测到的线条的输出矢量,每一条线由具有四个元素的矢量(x_1,y_1,
    x_2, y_2) 表示,其中,(x_1, y_1)和(x_2, y_2) 是是每个检测到的线段的结束点。

  • 第三个参数,double类型的rho,以像素为单位的距离精度。另一种形容方式是直线搜索时的进步尺寸的单位半径。

  • 第四个参数,double类型的theta,以弧度为单位的角度精度。另一种形容方式是直线搜索时的进步尺寸的单位角度。

  • 第五个参数,int类型的threshold,累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。大于阈值threshold的线段才可以被检测通过并返回到结果中。

  • 第六个参数,double类型的minLineLength,有默认值0,表示最低线段的长度,比这个设定参数短的线段就不能被显现出来。

  • 第七个参数,double类型的maxLineGap,有默认值0,允许将同一行点与点之间连接起来的最大的距离。

通过不同参数的设定,对于图像最后的筛选就有不同的结果。
结果如下图
第一个F结构元素
python图像处理初探——基于hough变换的直线道路识别_第1张图片第二个 F1结构元素
python图像处理初探——基于hough变换的直线道路识别_第2张图片
第三个 F2结构元素
python图像处理初探——基于hough变换的直线道路识别_第3张图片
第四个F3结构元素
python图像处理初探——基于hough变换的直线道路识别_第4张图片

反思

上图的问题,同时也是我的反思,在hough变换处理道路的时候其实是有很大的弊端的,重点是如下两点
1.hough变换一个大问题就是那些小的道路 累加器值小,检测不出来,但是要将检测的阈值降低,误差就大了 还有其他的干扰
2.还有就是曲率较大 弯大的 应该要设置很多个角度的卷积核去腐蚀,比较复杂,得根据特定道路进行设置

你可能感兴趣的:(python,opencv)