matlab從曲線圖提取資料
同學用
一頓飯讓我幫他做下這個DDL

樣圖是一張非常扭曲的三虛線圖

- 上谷歌查了查,對於曲線圖提取資料基本上是手動在曲線上取幾個點,然後由這個幾個點開始遍歷領域點,判斷領域點是否是黑色,然後再遍歷這個黑色點的領域,最終找出一條最長的線便是曲線,一種類似曲線擬合的做法?
- 知乎專欄 提供了一種思路,先把曲線圖上無關資訊去掉,然後提取最大的連通區域,就是所需要的 實線 ,只可惜樣例圖要做的是 虛線 。
第一種方法是同學AA想要的,不過英國人嘛,只告訴他要這樣做,並沒有告訴他基本思想,所以我們基於第二種方法拓展嘗試一下。
清洗影象
所給的影象是RGB影象,且有噪聲點,先將影象灰度化,計算影象閾值,通過閾值將影象二值化。

提取真實區域
想要的真實區域就是下圖中使用紅框標出的區域
法1
一開始的想法是先在圖片的(end*0.8:end-10,)區域中霍夫變換識別出下邊框,然後取下邊框的(,1:10)部分識別左邊框,取左邊框的最上端座標和下邊框的最右端座標,作為分割影象的基準,真實區域就分割出來了。
- 提取下邊框很順利
- 提取左邊框不是很順利
- 提取右邊框也不是很順利
- 提取上邊框很順利
雖然和計劃的有所偏差,但通過上邊框的最左端座標和下邊框的最右段座標,作為分割影象的基準,得到的真實影象理論上是相同的。
法2
對於樣例圖,真實區域是封閉的,是圖中的最大連通區域,那找最大聯通區域也可以提取出樣例圖的真實區域。

再取得該區域最左上端白點座標和最右下端白點座標,作為分割影象的基準,得到真實影象。
真實影象如圖所示

再次清洗影象
為了方便起見,下文中“圖”、“影象”指的是上一步中得到的真實影象,而不是原始影象。
對於得到的影象,仍然存在邊框、刻度線、右下角標識區域等無關資訊。
- 邊框可以直接通過上一步法1中得到的邊框座標陣列去掉。
- 刻度線以左邊框的刻度線為例,遍歷影象(,1:5)範圍內,若該點是黑點,則從該點開始,向右尋找最大的直線區域,去除。
樣例圖中存在曲線與刻度線相交的情況,我採用的方法是對於該點,如果24領域中的黑點總數大於一個閾值,則認為該點是曲線上的點,保留。 - 右下角標識區域直接找取聯通區域,如果該連通區域的大小大於閾值,認為是標識區域,去除。
得到的結果影象,邊界存在問題,有待改進:
分離曲線
三條曲線都不是實線,沒法通過找最大聯通區域的方法逐個分離,但因為不同曲線中實線部分的長度是不一樣的,所以可以貪心一下,從第1列開始,以某個閾值add_len為步長,找最大連通區域,再進行拼接,以圖中最上面一條曲線為例:
- 首先取影象(:,1:10)區域中的最大聯通區域,或者取3個聯通區域,認為聯通區域在列上的座標極小值為其高度值,高度值越小則越高,最高者則為想要取得最上面一條曲線。
- 然後取得該聯通區域中最右端的點n1(x,y),再取(:,y+1:y+add_len)中的n個聯通區域,對於每個聯通區域,找出其最左端的點n2(x1,y1),求n1與n2之間的歐式距離,認為歐式距離最短的就是該曲線在(:,y+1:y+add_len)的部分,然後重複該步,直到y值無限接近於影象最右端。
- 對於上一步也有不同的做法,取得該聯通區域中最右端的點n1(x,y),在從i=1開始迴圈,取(:,y+1:y+add_len)中的i個最大聯通區域,對於第i個區域,他的面積總是第i大的,找出其最左端的點n2(x1,y1),求n1與n2之間的歐式距離,若歐式距離小於某個閾值,則認為該聯通區域是該曲線在(:,y+1:y+add_len)的部分,然後重複該步,直到y值無限接近於影象最右端。
過程如圖:
兩種做法進行比較,得出的曲線基本相同。
取得最上端曲線a如圖所示:
然後將該曲線在圖中去除,再重複之前的做法,取得第二條曲線b。對於第二條曲線,add_len需要改小,歐式距離的閾值需要改大。
將第二條曲線去除,得到第三條曲線c
可以看出第三條曲線的影象存在噪點,可以用一個區域對噪點清洗,得到第三條曲線c
匯出資料
將a,b,c的座標值與影象的size相除,再乘上單位,即可得到資料。