同學用肉體一頓飯讓我幫他做下這個DDL
樣圖是一張非常扭曲的三虛線圖他甚至想OCR識別x軸y軸坐標單位
- 上谷歌查了查,對於曲線圖提取數據基本上是手動在曲線上取幾個點,然后由這個幾個點開始遍歷領域點,判斷領域點是否是黑色,然后再遍歷這個黑色點的領域,最終找出一條最長的線便是曲線,一種類似曲線擬合的做法?
- 知乎專欄提供了一種思路,先把曲線圖上無關信息去掉,然后提取最大的連通區域,就是所需要的實線,只可惜樣例圖要做的是虛線。
第一種方法是同學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相除,再乘上單位,即可得到數據。