欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python圖像處理之Hough變換檢測(cè)直線(xiàn)

 更新時(shí)間:2023年07月27日 16:16:55   作者:菜菜的小粉豬  
霍夫變換是一種特征檢測(cè)(feature?extraction),被廣泛應(yīng)用在圖像分析,本文將利用Hough變換實(shí)現(xiàn)直線(xiàn)檢測(cè),感興趣的小伙伴可以了解一下

一、 前言

霍夫變換是一種特征檢測(cè)(feature extraction),被廣泛應(yīng)用在圖像分析(image analysis)、計(jì)算機(jī)視覺(jué)(computer vision)以及數(shù)位影像處理(digital image processing)。由RichardDuda和PeterHart在公元1972年發(fā)明,并稱(chēng)之為廣義霍夫變換(generalizedHoughtransform),廣義霍夫變換和更早前1962年的PaulHough的專(zhuān)利有關(guān)。經(jīng)典的霍夫變換是偵測(cè)圖片中的直線(xiàn),之后,霍夫變換不僅能識(shí)別直線(xiàn),也能夠識(shí)別任何形狀,常見(jiàn)的有圓形、橢圓形。1981年,因?yàn)镈anaH.Ballard的一篇期刊論文"Generalizing the Hough transform to detect arbitrary shapes",讓霍夫變換開(kāi)始流行于計(jì)算機(jī)視覺(jué)界。霍夫變換是用來(lái)辨別找出物件中的特征,例如:線(xiàn)條。他的算法流程大致如下,給定一個(gè)物件、要辨別的形狀的種類(lèi),算法會(huì)在參數(shù)空間(parameter space)中執(zhí)行投票來(lái)決定物體的形狀,而這是由累加空間(accumulator space)里的局部最大值(local maximum)來(lái)決定。

二、Hough 變換

一條直線(xiàn)可由兩個(gè)點(diǎn)A=(x1?,y1?)和B=(x2?,y2?)確定(笛卡爾坐標(biāo))

另一方面,y=kx+b也可以寫(xiě)成關(guān)于(k,q)的函數(shù)表達(dá)式(霍夫空間):

空間變換過(guò)程如下圖:

變換后的空間成為霍夫空間。即:笛卡爾坐標(biāo)系中一條直線(xiàn),對(duì)應(yīng)霍夫空間的一個(gè)點(diǎn)。

反過(guò)來(lái)同樣成立(霍夫空間的一條直線(xiàn),對(duì)應(yīng)笛卡爾坐標(biāo)系的一個(gè)點(diǎn)):

笛卡爾坐標(biāo)系中兩個(gè)點(diǎn)對(duì)應(yīng)霍夫空間兩條線(xiàn):

如果笛卡爾坐標(biāo)系三個(gè)點(diǎn)共線(xiàn),對(duì)應(yīng)的霍夫空間的三條線(xiàn)相交于一點(diǎn)

霍夫變換的后處理的基本方式:選擇由盡可能多直線(xiàn)匯成的點(diǎn)。但是,按照直角坐標(biāo)系表示的話(huà)會(huì)出現(xiàn)下圖的情況:當(dāng)圖像空間中點(diǎn)共的線(xiàn)垂直于x軸時(shí),斜率無(wú)限大,在霍夫空間無(wú)法找到交點(diǎn)。因而,人們最終引入了極坐標(biāo)的表示法。

極坐標(biāo)下的霍夫直線(xiàn)檢測(cè)原理與直角坐標(biāo)系下完全一致,唯一需要重新推導(dǎo)的是與霍夫空間的極坐標(biāo)參數(shù)函數(shù):

化簡(jiǎn)便可得到:

r=xcosθ+ysinθ

如果對(duì)于一個(gè)給定點(diǎn)(x0?,y0?),意味著每一對(duì)(r,θ)代表一條通過(guò)點(diǎn)(xθ?,yθ?)的直線(xiàn)。我們?cè)跇O坐標(biāo)對(duì)極徑極角平面繪出所有通過(guò)它的直線(xiàn), 將得到一條正弦曲線(xiàn). 例如, 對(duì)于給定點(diǎn)(x0?=8和y0?=6) 我們可以繪出下圖 (在平面):

極坐標(biāo)與笛卡爾坐標(biāo)的轉(zhuǎn)換公式,從極坐標(biāo)轉(zhuǎn)換(r,θ)在笛卡爾坐標(biāo)系(x,y):

從笛卡兒坐標(biāo)轉(zhuǎn)換 (x,y) 到極坐標(biāo)(r,θ):

在極坐標(biāo)系下,其實(shí)是一樣的:極坐標(biāo)的點(diǎn)→霍夫空間的直線(xiàn),只不過(guò)霍夫空間不再是[k,q]的參數(shù),而是(r,θ)。

三、直線(xiàn)檢測(cè)

通過(guò)上面的介紹可知,畫(huà)出x−y坐標(biāo)空間中的點(diǎn)在參數(shù)空間中對(duì)應(yīng)的曲線(xiàn),然后計(jì)算參數(shù)空間中曲線(xiàn)的交點(diǎn),就能求得待求的參數(shù)。但還有一個(gè)問(wèn)題,當(dāng)參數(shù)空間中的曲線(xiàn)存在多個(gè)交點(diǎn)時(shí),如何挑選出最有可能的解呢?

具體計(jì)算時(shí),可將參數(shù)空間劃分為所謂的累加單元A(θ,ρ)。如圖下圖所示,對(duì)于x−y平面的每一個(gè)非背景點(diǎn)(xk?,yk?),令 θ等于每個(gè)可取的細(xì)分值,根據(jù)θ=−xk?θ+yk?計(jì)算出對(duì)應(yīng)的ρ值,每計(jì)算出一組 A(θ,ρ),則令A(yù)(θ,ρ)=A(θ,ρ)+1。計(jì)算所有結(jié)果后,找到A(θ,ρ)的峰值對(duì)應(yīng)的θ和ρ,即可檢測(cè)直線(xiàn)。(θmin?,θmax?)和(ρmin?,ρmax?)是期望的參數(shù)范圍:0°≤θ≤180°和−D≤θ≤D, D是圖像對(duì)角線(xiàn)的長(zhǎng)度。 θ和ρ的細(xì)分?jǐn)?shù)量決定了檢測(cè)結(jié)果的精度。

投票過(guò)程可以觀看下面的GIF,

左邊上青色的點(diǎn)代表圖像上的像素點(diǎn),黃色的代表對(duì)各個(gè)點(diǎn)不同角度搜索。右半邊是投票盤(pán),顏色越淺代表票數(shù)越多。

四、代碼實(shí)現(xiàn)

1.hough檢測(cè)

def lines_detector_hough(img,ThetaDim=None, DistStep=None, threshold=None, halfThetaWindowSize=2,
                         halfDistWindowSize=None):
    '''
    :param img: 經(jīng)過(guò)邊緣檢測(cè)得到的二值圖
    :param ThetaDim: hough空間中theta軸的刻度數(shù)量(將[0,pi)均分為多少份),反應(yīng)theta軸的粒度,越大粒度越細(xì)
    :param DistStep: hough空間中dist軸的劃分粒度,即dist軸的最小單位長(zhǎng)度
    :param threshold: 投票表決認(rèn)定存在直線(xiàn)的起始閾值
    :return: 返回檢測(cè)出的所有直線(xiàn)的參數(shù)(theta,dist)和對(duì)應(yīng)的索引值,
    '''
    row,col= edge.shape
    if ThetaDim == None:
        ThetaDim = 90
    if DistStep == None:
        DistStep = 1
    # 計(jì)算距離分段數(shù)量
    MaxDist = np.sqrt(row ** 2 + col ** 2)
    DistDim = int(np.ceil(MaxDist / DistStep))
    if halfDistWindowSize == None:
        halfDistWindowSize = int(DistDim /50)
    # 建立投票
    accumulator = np.zeros((ThetaDim, DistDim))  # theta的范圍是[0,pi). 在這里將[0,pi)進(jìn)行了線(xiàn)性映射.類(lèi)似的,也對(duì)Dist軸進(jìn)行了線(xiàn)性映射
    #
    sinTheta = [np.sin(t * np.pi / ThetaDim) for t in range(ThetaDim)]
    cosTheta = [np.cos(t * np.pi / ThetaDim) for t in range(ThetaDim)]
    #計(jì)算距離(rho)
    for i in range(row):
        for j in range(col):
            if not edge[i, j] == 0:
                for k in range(ThetaDim):
                    accumulator[k][int(round((i * cosTheta[k] + j * sinTheta[k]) * DistDim / MaxDist))] += 1
    M = accumulator.max()
#---------------------------------------
    #非極大抑制
    if threshold == None:
        threshold = int(M * 1.369/ 10)
    result = np.array(np.where(accumulator > threshold))  # 閾值化
    #獲得對(duì)應(yīng)的索引值
    temp = [[], []]
    for i in range(result.shape[1]):
        eight_neiborhood = accumulator[
                           max(0, result[0, i] - halfThetaWindowSize + 1):min(result[0, i] + halfThetaWindowSize,
                                                                              accumulator.shape[0]),
                           max(0, result[1, i] - halfDistWindowSize + 1):min(result[1, i] + halfDistWindowSize,
                                                                             accumulator.shape[1])]
        if (accumulator[result[0, i], result[1, i]] >= eight_neiborhood).all():
            temp[0].append(result[0, i])
            temp[1].append(result[1, i])
    #記錄原圖所檢測(cè)的坐標(biāo)點(diǎn)(x,y)
    result_temp= np.array(temp)
#-------------------------------------------------------------
    result = result_temp.astype(np.float64)
    result[0] = result[0] * np.pi / ThetaDim
    result[1] = result[1] * MaxDist / DistDim
    return result,result_temp

2.畫(huà)直線(xiàn)代碼

def drawLines(lines, edge, color=(255, 0, 0), err=3):
    '''
    :param lines: 檢測(cè)后的直線(xiàn)參數(shù)
    :param edge: 原圖
    :param color: 直線(xiàn)的顏色
    :param err:檢測(cè)的可接受的誤差值
    :return: 無(wú)
    '''
    if len(edge.shape) == 2:
        result = np.dstack((edge, edge, edge))
    else:
        result = edge
    Cos = np.cos(lines[0])
    Sin = np.sin(lines[0])
    for i in range(edge.shape[0]):
        for j in range(edge.shape[1]):
            e = np.abs(lines[1] - i * Cos - j * Sin)
            if (e < err).any():
                result[i, j] = color
    plt.imshow(result, cmap='gray')
    plt.axis('off')
    plt.show()

3.畫(huà)hough空間代碼

def data_img(data):
    '''
    :param data: 直線(xiàn)上含有的點(diǎn)(x,y)
    :return: 輸出hough空間圖像
    '''
    fig = plt.figure()  # 新建畫(huà)布
    ax = axisartist.Subplot(fig, 111)  # 使用axisartist.Subplot方法創(chuàng)建一個(gè)繪圖區(qū)對(duì)象ax
    fig.add_axes(ax)
    ax.axis[:].set_visible(False)  # 隱藏原來(lái)的實(shí)線(xiàn)矩形
    ax.axis["x"] = ax.new_floating_axis(0, 0, axis_direction="bottom")  # 添加x軸
    ax.axis["y"] = ax.new_floating_axis(1, 0, axis_direction="bottom")  # 添加y軸
    ax.axis["x"].set_axisline_style("->", size=1.0)  # 給x坐標(biāo)軸加箭頭
    ax.axis["y"].set_axisline_style("->", size=1.0)  # 給y坐標(biāo)軸加箭頭
    t = np.arange(-np.pi / 2, np.pi / 2, 0.1)
    ax.annotate(text='x', xy=(2 * math.pi, 0), xytext=(2 * math.pi, 0.1))  # 標(biāo)注x軸
    ax.annotate(text='y', xy=(0, 1.0), xytext=(-0.5, 1.0))  # 標(biāo)注y軸
    for i in range(data.shape[1]):
        rho = data[0][i] * np.cos(t) + data[1][i] * np.sin(t)
        plt.plot(t, rho)
    plt.show()

4.檢測(cè)結(jié)果

以上就是Python圖像處理之Hough變換檢測(cè)直線(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于Python檢測(cè)直線(xiàn)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 淺談Keras的Sequential與PyTorch的Sequential的區(qū)別

    淺談Keras的Sequential與PyTorch的Sequential的區(qū)別

    這篇文章主要介紹了淺談Keras的Sequential與PyTorch的Sequential的區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-06-06
  • 淺析Python條件語(yǔ)句中的解密邏輯與控制流

    淺析Python條件語(yǔ)句中的解密邏輯與控制流

    這篇文章主要想來(lái)和大家一起探索一下Python條件語(yǔ)句的奇妙世界——解密邏輯與控制流,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以學(xué)習(xí)一下
    2023-07-07
  • django基礎(chǔ)之?dāng)?shù)據(jù)庫(kù)操作方法(詳解)

    django基礎(chǔ)之?dāng)?shù)據(jù)庫(kù)操作方法(詳解)

    下面小編就為大家?guī)?lái)一篇django基礎(chǔ)之?dāng)?shù)據(jù)庫(kù)操作方法(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05
  • python中input()與raw_input()的區(qū)別分析

    python中input()與raw_input()的區(qū)別分析

    這篇文章主要介紹了python中input()與raw_input()的區(qū)別,需要的朋友可以參考下
    2016-02-02
  • Python編程實(shí)戰(zhàn)之Oracle數(shù)據(jù)庫(kù)操作示例

    Python編程實(shí)戰(zhàn)之Oracle數(shù)據(jù)庫(kù)操作示例

    這篇文章主要介紹了Python編程實(shí)戰(zhàn)之Oracle數(shù)據(jù)庫(kù)操作,結(jié)合具體實(shí)例形式分析了Python的Oracle數(shù)據(jù)庫(kù)模塊cx_Oracle包安裝、Oracle連接及操作技巧,需要的朋友可以參考下
    2017-06-06
  • Python處理缺失值的8種不同方法實(shí)例

    Python處理缺失值的8種不同方法實(shí)例

    缺失值是指粗糙數(shù)據(jù)中由于缺少信息而造成的數(shù)據(jù)的聚類(lèi)、分組、刪失或截?cái)?下面這篇文章主要給大家介紹了關(guān)于Python處理缺失值的8種不同方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • Python輸出各行命令詳解

    Python輸出各行命令詳解

    本篇文章給大家詳細(xì)分析了Python輸出各行命令的解釋?zhuān)瑸槌鯇W(xué)者提供詳細(xì)的講解,有興趣的朋友參考下。
    2018-02-02
  • python Socket網(wǎng)絡(luò)編程實(shí)現(xiàn)C/S模式和P2P

    python Socket網(wǎng)絡(luò)編程實(shí)現(xiàn)C/S模式和P2P

    這篇文章主要介紹了python Socket網(wǎng)絡(luò)編程實(shí)現(xiàn)C/S模式和P2P,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • Python中實(shí)現(xiàn)定時(shí)任務(wù)常見(jiàn)的幾種方式

    Python中實(shí)現(xiàn)定時(shí)任務(wù)常見(jiàn)的幾種方式

    在Python中,實(shí)現(xiàn)定時(shí)任務(wù)是一個(gè)常見(jiàn)的需求,無(wú)論是在自動(dòng)化腳本、數(shù)據(jù)處理、系統(tǒng)監(jiān)控還是其他許多應(yīng)用場(chǎng)景中,Python提供了多種方法來(lái)實(shí)現(xiàn)定時(shí)任務(wù),包括使用標(biāo)準(zhǔn)庫(kù)、第三方庫(kù)以及系統(tǒng)級(jí)別的工具,本文將詳細(xì)介紹幾種常見(jiàn)的Python定時(shí)任務(wù)實(shí)現(xiàn)方式
    2024-08-08
  • python將MongoDB里的ObjectId轉(zhuǎn)換為時(shí)間戳的方法

    python將MongoDB里的ObjectId轉(zhuǎn)換為時(shí)間戳的方法

    這篇文章主要介紹了python將MongoDB里的ObjectId轉(zhuǎn)換為時(shí)間戳的方法,涉及Python操作MongoDB及字符串轉(zhuǎn)換的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-03-03

最新評(píng)論