9.1 传统方法求轨道画线(python效果较好)

文章介绍了使用Python和OpenCV库实现的图像处理技术,包括聚类算法对轨道点的分组和二值化方法,用于识别和区分铁路轨道。作者还展示了如何应用这些技术在实际图片中检测和标记轨道区域。
摘要由CSDN通过智能技术生成

代码如下:

import numpy
import numpy as np
import cv2
import time

colors = [(255,255,0), (0, 0, 0), (128, 0, 0), (0, 128, 0), (128, 128, 0), (0, 0, 128), (128, 0, 128), (0, 128, 128),
                            (128, 128, 128), (64, 0, 0), (192, 0, 0), (64, 128, 0), (192, 128, 0), (64, 0, 128), (192, 0, 128),
                            (64, 128, 128), (192, 128, 128), (0, 64, 0), (128, 64, 0), (0, 192, 0), (128, 192, 0), (0, 64, 128),
                            (128, 64, 12)]

#1.聚类算法
def cluster(points, radius=100,nums=200):
    """
    points: pointcloud
    radius: max cluster range
    """
    print("................", len(points))
    items = []
    while len(points)>1:
        item = np.array([points[0]])
        base = points[0]
        points = np.delete(points, 0, 0)
        distance = (points[:,0]-base[0])**2+(points[:,1]-base[1])**2#获得距离
        infected_points = np.where(distance <= radius**2)#与base距离小于radius**2的点的坐标
        item = np.append(item, points[infected_points], axis=0)
        border_points = points[infected_points]
        points = np.delete(points, infected_points, 0)
        while len(border_points) > 0:
            border_base = border_points[0]
            border_points = np.delete(border_points, 0, 0)
            border_distance = (points[:,0]-border_base[0])**2+(points[:,1]-border_base[1])**2
            border_infected_points = np.where(border_distance <= radius**2)
            #print("/",border_infected_points)
            item = np.append(item, points[border_infected_points], axis=0)
            if len(border_infected_points)>0:
                for k in border_infected_points:
                    if points[k] not in border_points:
                        border_points=np.append(border_points,points[k], axis=0)
                #border_points = points[border_infected_points]
            points = np.delete(points, border_infected_points, 0)
        if item.shape[0]>nums:
            items.append(item)
    return items


#2.图片横着的二值化
def Binarization(img,keras):

    img2 = img
    x1=keras[0]//2
    x2=keras[0]-x1

    y1 = keras[1] // 2
    y2 = keras[1] - y1
    ks=np.ones(keras)

    dst = np.zeros((img2.shape[0], img2.shape[1]), np.uint8)
    for i in range(x1,img2.shape[0]-x2):
        for j in range(y1, img2.shape[1] - y2):
            a_z=(img2[i-x1:i+x2,j-y1:j+y2]*ks).mean()
            m = abs(img2[i][j] - a_z).max()
            if m > 16:
                dst[i][j] = 255
            else:
                dst[i][j] = 0
    return dst

#3.获得两条轨道的类
def fenlei(items,x1,x2,y1):

    for item in items:
        item[:,:1]+=x1
        item[:,1:]+=y1
    ls=sorted(items,key=lambda s: len(s), reverse=True)
    ls=ls[:2]

    #每行保留两个坐标
    datas=[]
    for item in ls:
        ss=[]
        for i in range(x1,x2+1):
            #获取横坐标为i的所有坐标点,并取中间的两个值
            x_i=item[np.where(item[:,:1] == i)[0]]
            if len(x_i)>0:
                ss.append([i,int(x_i[:,1:].mean())])
        datas.append(ss)
    return datas


#
def railway_classes(img,all_class,keras,radius,nums,x1,x2,y1,y2):

    #1.截取图片
    img1 = img[x1:x2, y1:y2,:]  # [540:741, 810:1080],截取轨道画线的区域,对该区域识别轨道
    img3=img.copy()
    img2=cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)

    #2.对截取的图片二值化处理
    image = Binarization(img2, keras)
    # cv2.imshow("ss",image)
    # cv2.waitKey(0)

    #3.获得二值化图片中不为0的坐标
    ss = np.argwhere(image> 0)

    #4.聚类算法
    items = cluster(ss, radius,nums)

    all_k = []#保存初始的横坐标,下一张图片根据该坐标截取

    if len(items)>=2:
        # 5.获得两条轨道的类
        datas=fenlei(items,x1,x2,y1)

        for item in datas:
            # 画图
            item=np.array(item)
            all_k.append(item[:1,:][0][1])
            for k in item:
                img3[k[0],k[1]-6:k[1]+6,:]=(255,255,0)

        if np.array(datas[0])[:1,:][0][1]>np.array(datas[1])[:1,:][0][1]:
            all_class["1"]=np.concatenate((np.array(datas[1]),all_class["1"]))
            all_class["2"]=np.concatenate(( np.array(datas[0]),all_class["2"]))
        else:
            all_class["1"]=np.concatenate((np.array(datas[0]),all_class["1"]))
            all_class["2"]=np.concatenate((np.array(datas[1]),all_class["2"]))

    all_k=np.array(all_k)
    all_k=numpy.sort(all_k)
    # cv2.imshow("ss", img3)
    # cv2.waitKey(0)
    return all_k,all_class



if __name__ == '__main__':

    img_paths = r"imgs/000001.jpg"
    img = cv2.imread(img_paths)
    imgs=cv2.imread(img_paths)
    keras=(1,4)
    all_class={"1":np.array([[0,0]]),"2":np.array([[0,0]])}

    # keras:对图片二值化的卷积核大小
    # radius:聚类算法的半径,在该半径内的相邻点分为通一类
    # nums:聚类算法的个数,当同类点的个数大于等于nums时,算一个类,否则被认为时一些散点
    # x1,x2,y1,y2:原图片太大,这里只需要截取图片的轨道区域部分进行识别,这4个值是要截取图片的坐标

    starts=time.time()
    all_datas,all_class=railway_classes(img,all_class, keras,radius=3,nums=30,x1=660, x2=730, y1=835, y2=1045)
    #print(all_class["1"].shape)
    ends=time.time()
    print("time1   ",ends-starts)
    # #
    starts = time.time()
    all_datas,all_class= railway_classes(img, all_class,keras, radius=4, nums=10, x1=620, x2=660, y1=all_datas[0]-6, y2=all_datas[1]+6)
    ends = time.time()
    print("time1   ", ends - starts)

    for item in all_class:
        for items in all_class[item]:
            print(items)
            #imgs[items[0]][items[1]]=[255,255,0]
            imgs[items[0], items[1] - 6:items[1] + 6, :] = (255, 255, 0)
    cv2.imshow("ss",imgs)
    cv2.waitKey(0)

效果如下:

        

这个效果明显比第9节的效果好很多。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值