項目思路記錄

1 目標切割
假設:沒有目標模板(不能運用模板匹配)
要求:精確切割出目標
思路:傳統圖像處理技術(因爲神經網絡或級聯分類器不能精確切割)
處理思想:畫出像素分佈圖,觀察分佈,確定特徵


具體步驟:
(1)閾值處理
閾值處理的方法這裏選擇了取圖像85%的分位數的值np.percentile(blur, 85) 這樣選取的好處是自適應性比較好,相比於大津法也有更多的自由選擇閾值的空間。
(2)計算每一行的像素均值,得到一個以圖像高爲長度的向量。理想情況是根據背景區域與目標區域的灰度差,可以比較容易地確定目標區域的y方向的位置。同樣地,計算每一列的像素均值,從而得到目標區域的x方向的位置。
得到的y方向上的像素均值圖像實際上是這樣的:

難以確定一個自適應的閾值來確定邊緣的位置。於是想到計算一階導,但由於臨近像素點之間的像素差不大,因此計算一階導數
的效果很差。結合之前學習深度學習中,池化的概念,我想到了對每十個像素點計算一個均值或者最大值,來代替這十個像素點的值,從而減小這些細節的影響,提取出比較明顯的像素變化趨勢,得到圖像如下。根據這個圖形,我們再計算一階導數,就可以得到比較好的結果。

一階導數的結果:

如此,我們只需要確定前半部分的最大值,以及後半部分的最小值,就可以得到圖像的左右邊緣了。計算上下邊緣同理。

總結:採用傳統方法對目標區域進行切割,首先自適應是一個問題。採用圖像數據的分位數是一個不錯的選擇。其次,畫出圖像直方圖、像素分佈等信息進行觀察和嘗試,尋找目標區域的特徵,如顏色,灰度等。最後,多嘗試,多思考。

2 角度修正
角度修正的方法我沒有找到一個較好地方法,只能說根據網上的一些方法進行了嘗試,不具有通用性。
(1)根據霍夫變換找直線
霍夫變換的原理比較簡單。他將二維空間裏的一條直線,映射成爲用(theta,h)表示。其中theta是該直線的垂線與x軸的夾角,h是原點到該直線的垂直距離。空間裏的每個點其實可以位於無數條直線上,因此一個點可以對應無數個(theta,h)。位於同一條直線上的這些點的{(theta,h)}集和存在一個交集,這個交集就是他們所在的同一條直線。從而霍夫變換通過確定空間裏的這些點所對應的{(theta,h)},就可以確定空間裏的直線。通過霍夫變換找到直線後,我們就可以通過直線的角度判斷圖像的傾角。
lines = cv.HoughLines(img_canny, 1, np.pi / 10, 10) if lines is None: arc = 0 else: # 提取爲爲二維 arc = lines[:, 0, :] arc = arc[0][1]
M = cv.getRotationMatrix2D((img.shape[0] / 2, img.shape[1] / 2), -arc, 1)

不過在實踐中發現,霍夫變換的效果經常是比較差的。
(2)考慮到我們的圖像中有兩行字符,因此我們可以通過計算字符的傾角確定圖像的傾角。
首先是確定出字符大概位置,通過計算字符的最小外接矩形得到字符的傾角。
coords = np.column_stack(np.where(img_to_calculate_angle > 0)) angle = cv.minAreaRect(coords)[-1] if angle < -45: angle = 90 + angle else: angle = -angle


3 尋找連通區域

確定連通區域有一個現成的函數:
label_img = measure.label(blurm)
props = measure.regionprops(label_img)
得到的props就是連通區域集和,我們可以計算每個聯通區域的像素點個數,像素比例,周長,凸集面積等等。
prop.area:區域像素個數
prop.extent:區域與背景像素比

4 鏈接斷開劃痕
由於在閾值處理的過程中,一部分劃痕被斷開了。爲了更精準地計算劃痕的長度,需要將斷開的劃痕連接起來。這裏查閱了一篇論文,‘’基於Prim最小生成樹的路面裂縫連接算法‘’,採用了其中的算法實現斷開劃痕的鏈接。
算法思路:
(1)計算距離矩陣。計算每一條劃痕的左右頂點與其他劃痕左右頂點的距離。初始化空列表:linked,初始化列表:unlinked,儲存所有的劃痕。
(2)確定最長劃痕,從unlinked中刪除,添加進linked,在unlinked中尋找距離這個最長劃痕最近的劃痕,添加進linked
(3)在unlinked中尋找與linked中的劃痕距離最近的劃痕,添加進linked。循環該步驟,直至unlinked爲空。
(4)判斷某鏈接是否正確:(1)兩劃痕中心點的距離<=65,兩劃痕的角度差不超過30度(2)兩劃痕的連接點的橫縱方向最大距離<=5或者兩劃痕連線的斜率與兩劃痕的斜率均值之差<30度,則計算兩條劃痕的長度和及連線的長度,代替原劃痕的長度;

5 判斷平行劃痕
由於對方要求,當有多條臨近的平行劃痕,計算他們寬度的和作爲平行劃痕的寬度。因此需要判斷平行劃痕。
首先需要判斷是否平行,即通過計算斜率來判斷。第二需要判斷是否這些劃痕距離比較近,通過判斷相鄰的兩條劃痕的距離是否在一定範圍內來判斷。

6 判斷字符識別是否受到劃痕影響
分爲貫穿和未貫穿但影響識別兩種情況處理。

在查閱資料的過程中,發現了一個有用的函數,順便記錄一下(如果早能夠發現,也許能省掉一些麻煩)。
頂帽變換和底帽變化:用於矯正不均勻光照的影響。
頂帽變換用於暗背景上的亮物體,而底帽變換則用於相反的情況。由於這一原因,當談到這兩個變換時,常常分別稱爲白頂帽變換和黑底帽變換。
下面,我們通過一個實例來說明此方法,對於圖1(a),可以看到光照明顯不均勻,左邊光照更強,直接進行otsu法全局閾值得到圖1(b),可以看到左邊的硬幣分割出錯。
  由於原圖是背景亮,前景暗,對原圖進行底帽變換以解決光照不均勻的問題,這裏先給出處理結果,如圖1(c)和(d),可以看到底帽變換後的圖像刪除了大部分非均勻背景,最後閾值處理後,左邊的硬幣被分割出來,有少量殘缺,但是影響不大,後續可以通過形態學的其他處理將殘缺補齊。
下面是一個底帽變換的例子。

再來一個頂帽變換的例子
原圖:

閾值處理:發現右下角效果不好
頂帽變換:
再進行閾值處理,發現效果變好了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章