代码如下:
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节的效果好很多。