北科資工二多媒體技術與應用 第三周作業-利用霍夫線分辨出磁磚邊緣

筆記說明

此筆記用途在於台北科技大學資訊工程系大二下多媒體技術與應用作業紀錄
並非所有人都適用,部分對我而言稍加容易的內容並不會寫在此內。
這是學習後心得的筆記,可能不太適用會未來的學生

由於我沒有學習過裡面的理論,因此這是資工大二學生透過網路與自身理解的筆記,學習價值並不高、且可能擁有大量錯誤。

題目如下,用圖片

此題作法

考倒我了,嗚嗚。
我對於圖學的知識過少,還需要增加自己對於多媒體的思考能力R。

由於此題已經有告訴你需要用的步驟與規則如下

  • 二值化 cv2.threshold
    給予一數值 x,圖片中大於 x 的點都變成白色,小於的則變成黑色
  • 濾波 cv2.medianBlur
    先進行濾波,讓縮小的圖片雜訊被模糊掉,進而讓邊緣線更清楚
  • 膨脹 cv2.dilate
    先給予一個矩陣,如果此矩陣裡有白色的點,那所有點都變為白色,要搭配二值化此用
  • 侵蝕 cv2.erode
    先給予一個矩陣,如果此矩陣裡有白色的點,那所有點都變為黑色,要搭配二值化此用
  • 模糊 cv2.medianBlur
    由於有大量的反光,加上磁磚並不是完整統一顏色,難免會在縮小後造成雜訊過多,此時我們用濾波讓雜訊模糊,進而讓我們的邊緣清晰。
  • 霍夫線 cv2.HoughLines
    他不需要一個完整的線,它可以將零碎的片段組成一條線。由於圖片擁有大量的反光,會使得磁磚邊緣不清晰,使用他就可以避免此問題,此函式有四個參數,建議一開始可以將極座標先預設為初始值
    • image 影像
    • rho 極座標的線長度
    • theta 極座標的角度
    • threshold 超過此長度的線,才會視為是一條線,通常建議從 100 開始慢慢調整
  • 對磁磚邊緣劃線 ````cv2.line``` 進行

現在我們有了這些資訊,就比較好寫程式了。

將資料統整後,可以得出一個結論

  • 圖片大小不可以超過 1000 像素,所以我們先 cv2.resize
  • 先進行濾波,讓縮小的圖片雜訊被模糊掉,進而讓邊緣線更清楚
  • 再來進行二值化,因為如果沒有二值化後面所有東西都不能做
    至於要在那個點做 x 化就要不斷嘗試
  • 查看圖片,發現還是有一些雜訊,因此先侵蝕
    至於要在矩陣多大就要不斷嘗試
  • 侵蝕完畢後,發現磁磚縫細有點變形,在做膨脹
    至於要在矩陣多大就要不斷嘗試
  • 中間有雜訊是正常的,只要不影響霍夫線即可。
  • 再來劃出霍夫線,這裡的輸出的直線座標系統是用極座標。
  • 由於是極座標,因此我們要在轉換成直角座標
  • 轉換完成後,使用 ````cv2.line``` 劃線
  • 輸出答案

參考連結

霍夫线变换 openCV
How to draw a desired line from HoughLines function output in OpenCV C++? by stackoverflow
OpenCV-Python教程(9、使用霍夫变换检测直线) by Daetalus
OpenCV-Python 霍夫直线检测-HoughLinesP函数参数 by -牧野-
图像平滑 by OpenCV-Python 中文教程
極座標系 by wiki

心得

原本在上課老師給的學習時間中不斷嘗試卻一直失敗,果然再不太熟的情況下想要做出一份專案是不可能的壓XD,要先透過別人的資料進行學習,從中得知能做好事的關鍵,然後我們再進行模仿,成功後再進行改良、創新。

謝謝郭梓琳、林紀緯的程式碼,讓我從中學習到這麼多的知識。

放在網路上供我知道,也讓有困難的朋友也能學習到。

程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import cv2
import numpy as np

img = cv2.imread("../pic/floor.jpg") #輸入資料
h, w, ch = img.shape #圖片高、寬、通道
w //= 5 #這樣就小於 1000
h //= 5
print(h)

img = cv2.resize(img, (w,h), interpolation = cv2.INTER_NEAREST)
#縮小圖片,記住這邊的 interpolation 選擇很重要,如果不確定建議可以都試試找最棒的
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = cv2.medianBlur(gray,1) #透過慮波來讓縮小的圖片雜訊被模糊掉,進而讓邊緣線清楚
ret, gray = cv2.threshold(gray, 110, 255, cv2.THRESH_BINARY_INV) #二值化,110 是慢慢設定的
#需要特別注意,由於 HoughLines 是判斷**白色**得線,但我們的磁磚邊緣線是黑色,
#因此我們這邊的參數要用 cv2.THRESH_BINARY_INV,這樣原本判定黑色的地方就會變白色

gray = cv2.erode(gray, np.ones((2,2)), iterations=1) #侵蝕,裡面矩陣與 iterations 細調
gray = cv2.dilate(gray, np.ones((2,2)), iterations=1) ##膨脹,裡面矩陣與 iterations 細調

#cv2.imshow("img", img)
cv2.imshow("gray", gray) #檢查一下,有雜訊是正常的,只要不影響到霍夫線劃線都沒問題
cv2.waitKey(0)

rho = 1.0 #極座標系統長度
theta = np.pi / 2 #極座標系統角度
line = cv2.HoughLines(gray, rho, theta, 200) #霍夫線

for it in line: #將每條線
for rho, theta in it: #拿出每條線裡面的極座標系統
a = np.cos(theta) #下面轉換成為直角坐標
b = np.sin(theta)
x0 = a*rho
y0 = b*rho
x1 = int(x0 + h*(-b)) #由於我們要畫的線基本上是從圖片的末端開始畫,因此我們直接將畫線
y1 = int(y0 + h*(a)) #長度設定為,我們圖片中最長的長度即可(通常是高)。
x2 = int(x0 - h*(-b)) #這樣我們就會從圖片的末端畫到另一末端
y2 = int(y0 - h*(a))
cv2.line(img, (x1,y1), (x2,y2), (0,0,255), 2) #畫線

cv2.imshow("result", img)
cv2.imwrite("result.jpg", img) #輸出圖片
cv2.waitKey(0)

題目資料

原始磁磚圖片

灰階、濾波、二值化、膨脹、侵蝕後的圖片

答案

  • 版權聲明: 本部落格所有文章除有特別聲明外,均採用 Apache License 2.0 許可協議。轉載請註明出處!
  • © 2020-2024 John Doe
  • Powered by Hexo Theme Ayer
  • PV: UV: