平安城市-轨道线识别-步骤原理实现记录

首先一张图的识别为例:

第一步:读取图像并查看验证

        代码:

import cv2
import numpy as np
# 读取图片路径
image = cv2.imread("P1_No005.jpg")
# 设置窗口大小自适应比例
cv2.namedWindow("image",cv2.WINDOW_KEEPRATIO)
# 在窗口中显示图像
cv2.imshow("image", image)
# 等待一个键盘的输入(按任意键继续程序)
cv2.waitKey(0)

        运行结果:

第二步:对图像进行灰度转换并进行高斯滤波(用来降噪,即模糊图像,减少图像的细节)后续我们需要使用cv2.findContours()进行轮廓检测,因此我们需要获取图像的二值图(黑白图)(cv2.findContours()函数接受的参数为二值图(不是灰度图))

        代码:

# 对灰度图进行高斯滤波
image = cv2.resize(image, (600, 600))  # 改变图像尺寸
gs_frame = cv2.GaussianBlur(image, (11, 11), 0)  # 高斯滤波获取轮廓

# 将图像转换成灰度图像
gray = cv2.cvtColor(gs_frame, cv2.COLOR_BGR2GRAY)  # 原彩色图片转换成灰度图

ret, binary = cv2.threshold(gray, 145, 255, cv2.THRESH_BINARY_INV)  # 二值化
# 设置窗口大小自适应比例
cv2.namedWindow("binary", cv2.WINDOW_KEEPRATIO)
# 在窗口中显示图像
cv2.imshow("binary", binary)
# 等待一个键盘的输入(按任意键继续程序)
cv2.waitKey(0)

        运行结果:

第三、四步进行闭运算(先膨胀后腐蚀,将图像相连为一个无突起的连通域)

 第三步:对图像进行膨胀并进行迭代(自定义执行多次膨胀操作,扩大图像主要特征)

        代码:

kernel = np.ones((40, 40), dtype=np.uint8)  # 膨胀图像
dilate = cv2.dilate(binary, kernel, 1)  # 迭代膨胀操作
# 设置窗口大小自适应比例
cv2.namedWindow("dilate", cv2.WINDOW_KEEPRATIO)
# 在窗口中显示图像
cv2.imshow("dilate", dilate)
# 等待一个键盘的输入(按任意键继续程序)
cv2.waitKey(0)

        运行结果(可以看到主要特征被放大了):

  第四步:对图像进行腐蚀(通过更改np.ones的第一个参数即shape来变动腐蚀程度)

        代码:

# 进行腐蚀
kernel = np.ones((40, 40), dtype=np.uint8)  # 腐蚀图像
# kernel = np.ones((20, 20), dtype=np.uint8)  # 腐蚀图像
erosion = cv2.erode(dilate, kernel, iterations=1)
# 设置窗口大小自适应比例
cv2.namedWindow("erosion", cv2.WINDOW_KEEPRATIO)
# 在窗口中显示图像
cv2.imshow("erosion", erosion)
# 等待一个键盘的输入(按任意键继续程序)
cv2.waitKey(0)

        运行结果(可以对比40与20的区别,左40,右20):

  第五步:绘制矩形

        代码:

# 注意:cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),所以读取的图像要先转成灰度的,再转成二值图。
contours, hierarchy = cv2.findContours(erosion, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)  # 轮廓检测,寻找边框
x = []  # 存储横坐标
y = []  # 存储纵坐标
for i in range(600):
    for j in range(600):
        if erosion[i, j] != 0:  # 如果该像素点不等于0(为白,不为黑),存储下来
            # print(f"{i} {j}")
            x.append(i)
            y.append(j)
area = []
area_num = []
for i in range(len(contours)):
    a = cv2.contourArea(contours[i], True)
    area.append(abs(a))

if len(area) > 1:
    for i in range(len(area)):
        area_num.append(i)
    area_num.remove(area.index(max(area)))
    for i in range(len(area_num)):
        erosion = cv2.drawContours(erosion, contours, area_num[i], 0, cv2.FILLED)

# print(erosion[599,263])  # 为255
# print(erosion[0,   0])   # 为0
c1 = min(x)
c2 = max(x)
c3 = min(y)
c4 = max(y)
if erosion[c1, c3] == 255 and erosion[c2, c3] == 0:  
# 若左上到右下为路径(左上顶点为白,右上顶点为黑),则为左
    print('left')
if erosion[c1, c4] == 255 and erosion[c2, c4] == 0:  
# 若左下到右上为路径(左下顶点为白,右上顶点为黑),则为右
    print('right')
if erosion[c1, c3] == 255 and erosion[c1, c4] == 255:   # 均为白,则为直
    print('Go straight')
# 绘制图框
cv2.rectangle(image, (c3, c1), (c4, c2), (0, 255, 0), 2)  # 图像上绘制矩形
cv2.imshow("result", image)
cv2.waitKey(0)

        运行结果:

​​​​​​​

即可

完整代码:

import cv2
import numpy as np

# 读取图片路径
image = cv2.imread("P1_No005.jpg")

# 对灰度图进行高斯滤波
image = cv2.resize(image, (600, 600))  # 改变图像尺寸
gs_frame = cv2.GaussianBlur(image, (11, 11), 0)  # 高斯滤波获取轮廓

# 将图像转换成灰度图像
gray = cv2.cvtColor(gs_frame, cv2.COLOR_BGR2GRAY)  # 原彩色图片转换成灰度图

ret, binary = cv2.threshold(gray, 145, 255, cv2.THRESH_BINARY_INV)  # 二值化

kernel = np.ones((40, 40), dtype=np.uint8)  # 膨胀图像
dilate = cv2.dilate(binary, kernel, 1)  # 迭代膨胀操作

# 进行腐蚀
kernel = np.ones((20, 20), dtype=np.uint8)  # 腐蚀图像
erosion = cv2.erode(dilate, kernel, iterations=1)

# 注意:cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),所以读取的图像要先转成灰度的,再转成二值图。
contours, hierarchy = cv2.findContours(erosion, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)  
# 查询角点
x = []  # 存储横坐标
y = []  # 存储纵坐标
for i in range(600):
    for j in range(600):
        if erosion[i, j] != 0:  # 如果该像素点不等于0(为白,不为黑),存储下来
            # print(f"{i} {j}")
            x.append(i)
            y.append(j)

c1 = min(x)
c2 = max(x)
c3 = min(y)
c4 = max(y)
if erosion[c1, c3] == 255 and erosion[c2, c3] == 0:  # 若左上到右下为路径(左上顶点为白,右上顶点为黑),则为左
    print('left')
if erosion[c1, c4] == 255 and erosion[c2, c4] == 0:  # 若左下到右上为路径(左下顶点为白,右上顶点为黑),则为右
    print('right')
if erosion[c1, c3] == 255 and erosion[c1, c4] == 255:   # 均为白,则为直
    print('Go straight')
# 绘制图框
cv2.rectangle(image, (c3, c1), (c4, c2), (0, 255, 0), 2)  # 图像上绘制矩形
cv2.imshow("result", image)
cv2.waitKey(0)

将代码加入循环即可进行多次检测:

import cv2
import numpy as np
import os

for filename in os.listdir('mydata/test'):  # 遍历路径下所有图片
    print(filename)
    image = cv2.imread('mydata/test' + '/' + filename)
    # 读取图片路径
    # # 设置窗口大小自适应比例
    # cv2.namedWindow("image", cv2.WINDOW_KEEPRATIO)
    # # 在窗口中显示图像
    # cv2.imshow("image", image)
    # # 等待一个键盘的输入(按任意键继续程序)
    # cv2.waitKey(0)

    # 对灰度图进行高斯滤波
    image = cv2.resize(image, (600, 600))  # 改变图像尺寸
    gs_frame = cv2.GaussianBlur(image, (11, 11), 0)  # 高斯滤波获取轮廓

    # 将图像转换成灰度图像
    gray = cv2.cvtColor(gs_frame, cv2.COLOR_BGR2GRAY)  # 原彩色图片转换成灰度图

    ret, binary = cv2.threshold(gray, 145, 255, cv2.THRESH_BINARY_INV)  # 二值化
    # # 设置窗口大小自适应比例
    # cv2.namedWindow("binary", cv2.WINDOW_KEEPRATIO)
    # # 在窗口中显示图像
    # cv2.imshow("binary", binary)
    # # 等待一个键盘的输入(按任意键继续程序)
    # cv2.waitKey(0)

    kernel = np.ones((40, 40), dtype=np.uint8)  # 膨胀图像
    dilate = cv2.dilate(binary, kernel, 1)  # 迭代膨胀操作
    # # 设置窗口大小自适应比例
    # cv2.namedWindow("dilate", cv2.WINDOW_KEEPRATIO)
    # # 在窗口中显示图像
    # cv2.imshow("dilate", dilate)
    # # 等待一个键盘的输入(按任意键继续程序)
    # cv2.waitKey(0)

    # 进行腐蚀
    kernel = np.ones((40, 40), dtype=np.uint8)  # 腐蚀图像
    erosion = cv2.erode(dilate, kernel, iterations=1)
    # # 设置窗口大小自适应比例
    # cv2.namedWindow("erosion", cv2.WINDOW_KEEPRATIO)
    # # 在窗口中显示图像
    # cv2.imshow("erosion", erosion)
    # # 等待一个键盘的输入(按任意键继续程序)
    # cv2.waitKey(0)

    # 注意:cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),所以读取的图像要先转成灰度的,再转成二值图。
    contours, hierarchy = cv2.findContours(erosion, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)  # 轮廓检测,寻找边框
    # print(contours)
    # print(hierarchy)
    area = []
    area_num = []
    for i in range(len(contours)):
        a = cv2.contourArea(contours[i], True)
        area.append(abs(a))

    if len(area) > 1:
        for i in range(len(area)):
            area_num.append(i)
        area_num.remove(area.index(max(area)))
        for i in range(len(area_num)):
            erosion = cv2.drawContours(erosion, contours, area_num[i], 0, cv2.FILLED)
    # 查询角点
    x = []  # 存储横坐标
    y = []  # 存储纵坐标
    for i in range(600):
        for j in range(600):
            if erosion[i, j] != 0:  # 如果该像素点不等于0(为白,不为黑),存储下来
                # print(f"{i} {j}")
                x.append(i)
                y.append(j)

    # print(erosion[599,263])  # 为255
    # print(erosion[0,   0])   # 为0
    c1 = min(x)
    c2 = max(x)
    c3 = min(y)
    c4 = max(y)
    if erosion[c2, c4] == 255 and erosion[c2, c3] == 0:  # 若左上到右下为路径(左上顶点为白,右上顶点为黑),则为左
        print('left')
    if erosion[c1, c4] == 255 and erosion[c1, c3] == 0:  # 若左下到右上为路径(左下顶点为白,右上顶点为黑),则为右
        print('right')
    if erosion[c1, c3] == 0 and erosion[c1, c4] == 0:   # 均为白,则为直
        print('Go straight')
    print(f"{erosion[c1, c3]} {erosion[c2, c3]}")
    print(f"{erosion[c1, c4]} {erosion[c2, c4]}")
    print(f"{erosion[c1, c3]} {erosion[c1, c4]}")
    # 绘制图框
    cv2.rectangle(image, (c3, c1), (c4, c2), (0, 255, 0), 2)  # 图像上绘制矩形
    cv2.imshow("result", image)
    cv2.waitKey(0)

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
ZPW-2000A轨道电路是一种常用的列车自动控制系统,由于其拥有可靠性高、安全性好、运行稳定等特点,在铁路交通中被广泛应用。 ZPW-2000A轨道电路的原理是利用电磁感应原理,通过铁轨上设置的电路设备,与列车上的传感器进行相互作用。当列车经过轨道电路时,电路中传感器和设备相互感应,产生电信号,将信号传送到中央控制系统。通过对传感器信号的检测和分析,中央控制系统能够判断列车的运行状态,以及是否需要进行车辆的自动控制。中央控制系统会根据收到的信号,对轨道上的信号灯进行控制,指挥列车的行驶、停车、换轨等操作,从而实现列车的自动控制。 ZPW-2000A轨道电路的应用主要集中在铁路运输领域。一方面,它可以实现列车的自动控制,提高了列车的运行效率和安全性。在列车接近信号灯时,轨道电路能够及时发出信号,控制信号灯的亮灭,以便通知司机执行相应的操作。同时,它还能够监测列车的运行速度和位置,保证列车按照规定的路径行进,杜绝列车的异常行为,保证列车行驶的安全性。 另一方面,ZPW-2000A轨道电路还能够实现列车的运营管理。通过对轨道电路的数据收集和处理,可以实时监测列车运行的情况,包括运行状态、停车时间、换乘情况等。通过这些数据的分析,铁路管理部门可以制定合理的运行计划,调整列车的运行频率和线路安排,提高运输线路的利用率,为旅客提供更加方便、快捷的出行体验。 总之,ZPW-2000A轨道电路的原理是基于电磁感应,在铁路交通领域有着广泛的应用。它通过自动控制和运营管理,提高了列车运行的效率和安全性,为铁路交通的发展做出了重要贡献。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值