python实现霍夫线检测,识别线路及角度

原理就不解释了,就是利用的opencv里的霍夫变换,程序也有注释。

import cv2 as cv
import numpy as np
import random
import sys
import math
from scipy.special import comb, perm  ##计算排列组合的
from pandas import Series,DataFrame    #提取误差较小多个数据的包

def round_up(value):
    # 替换内置round函数,实现保留2位小数的精确四舍五入
    return round(value * 10) / 10.0
img = cv.imread('./data/2.jpg')
#gray = cv.cvtColor(img,cv.COLOR_RGB2GRAY) ##转换为灰度
#blur = cv.GaussianBlur(img, (7, 7), 0)
#cv.imshow('blur',blur)
edges = cv.Canny(img,200,255)   ##canny边缘检测算法  250,300为高低阈值
#canny = cv.Canny(img,250,300)
minlineLength=30
maxLineGap=5   ###HoughLinesP函数所用的,最短线长和最大线间距
#lines=cv.HoughLinesP(edges,0.8,np.pi/180.0,180,minlineLength,maxLineGap)
lines=(cv.HoughLines(edges,1,np.pi/180.0,180) )#霍夫线检测,极坐标下半径和角度,阈值
print(lines)

i = 1
index = 1
j = 1

def threshold_cluster(Data_set,threshold):   ###找出误差不大的数据,误差为threshold  我
    #统一格式化数据为一维数组
    stand_array=np.asarray(Data_set).ravel('C')
    stand_Data=Series(stand_array)
    index_list,class_k=[],[]
    while stand_Data.any():
        if len(stand_Data)==1:
            index_list.append(list(stand_Data.index))
            class_k.append(list(stand_Data))
            stand_Data=stand_Data.drop(stand_Data.index)
        else:
            class_data_index=stand_Data.index[0]
            class_data=stand_Data[class_data_index]
            stand_Data=stand_Data.drop(class_data_index)
            if (abs(stand_Data-class_data)<=threshold).any():
                args_data=stand_Data[abs(stand_Data-class_data)<=threshold]
                stand_Data=stand_Data.drop(args_data.index)
                index_list.append([class_data_index]+list(args_data.index))
                class_k.append([class_data]+list(args_data))
            else:
                index_list.append([class_data_index])
                class_k.append([class_data])
    return index_list,class_k    #输出的list表示的是相似数据的位置,class_k将相似数据放到了一起

    N = len(lines)  # lines的长度    ###这块有缩进,自己调一下,复制的时候搞坏了
    M = lines.ndim  # lines的列数
    data = [0 for x in range(0, N + 1)]
    # data = np.array(data, dtype='uint8')
    data[0] = N
    num = int(comb(N, 2))  ##计算组合数
    select = [0 for x in range(0, N)]
    data_send = [0 for x in range(0, 5)]
    # data_send = np.array(data_send, dtype='uint8')
    data_send[0] = hex(0x34)
    data_send[1] = hex(0x4d)
    for line in lines:    #找出两点,画出直线
        rho, theta = line[0]
        a = np.cos(theta)
        b = np.sin(theta)
        x0 = a * rho
        y0 = b * rho
        x2 = int(x0 + 1000 * (-b))
        y2 = int(y0 + 1000 * (a))
        x1 = int(x0 - 1000* (-b))
        y1 = int(y0 - 1000 * (a))
        if x2 - x1 == 0:
            coner = 90  ##计算线的偏角
        elif y2 - y1 == 0:
            coner = 0
        else :
            tanconner = ((y2 - y1) / (x2 - x1))
            coner = np.arctan(tanconner) * -57.29577951  ##计算线的偏角..1弧度 = 180/pai 度 = 57.29577951
        cv.line(img, (x1, y1), (x2, y2), (0, 0, 255),2)  ##划线,并涂成红色
        if i<=N:
            data[i]=coner    ##将偏航角存储下来
            select[i-1]=coner
            i=i+1
        print(f"第{i-1}条线的偏转角度为:")
        print((coner))
        print("线路第一个点x坐标:%f" % ((x1)))
        print("线路第一个点y坐标:%f" % (y1))
        print("线路第二个点x坐标:%f" % (x2))
        print("线路第二个点y坐标:%f" % (y2))
    cv.imshow("edges",edges)
    cv.imshow("Lines",img)
    k = (cv.waitKey(10) & 0xFF)
    index_list, class_k = threshold_cluster(select, 4)   ##调用函数
    res = max(class_k, key=len, default='')    ##找出class_k中最长的字符串,并赋值给res
    length_res=len(res)     #计算res长度
    if length_res>=2:
        yaw = (round_up(np.mean(res)))
    elif length_res==0:
        yaw=255
    elif length_res==1:
        yaw = (round_up(np.mean(class_k)))   ##对res长度的三种情况的判断。0 、1 和大于等于2
    yaw_send=int(yaw)
    data_send[2]=hex(N)
    data_send[3]=hex(yaw_send)
    data_send[4]=hex(0x00)  #定义传输数据格式
    if k == ord('q'):
       sys.exit()
    elif k==ord('s'):
        cv.imwrite('./data/'+ str(index) + '.jpg', img)
        cv.imwrite('./data/' + str(index) + '.jpg', edges)  #保存照片
        index=index+1
    print("检测的线路总数为:%d" %(N))
    print("线路偏航角为:")
    print(data)
    print("线路偏航角为:")
    print((yaw))
    print("传输数据列表:")
    print((data_send))
    cv.waitKey(0)
    cv.destroyAllWindows()

你可能感兴趣的:(视觉,霍夫变换,线路检测,python)