# 期刊論文
系統架構圖




碰到的問題是甚麼?你要怎麼解決?方法是甚麼?
要寫你為什麼這麼做,根據是甚麼?
寫理論基礎 核心精神 根據
**鋼條底部偵測**
使用yolo抓取型鋼底部物件,輸出底部物件的座標、信心指數、類別名稱,將物件框的座標作為直線分群的基準,根據物件框位置顯示鋼條整根正在畫面中,可進行後續處理,進而觸發後續處理程序
用途:檢測區域當中,生產線在持續生產,等到整條鋼都出現以後,才能進行檢測
用途:
1. 做直線分群
1. 作為觸發後續運算的機制,減少運算量(以攝影機取像30fps計算,取像兩秒鐘,則後台系統取得的影像為60張,經實驗統計,若以觸發機制為基礎的演算法,可在僅運算15張影像的前提下完成型鋼彎曲辨識的任務,成功地將運算量降低為25%)

**鋼條底部追蹤**
使用座標追蹤鋼條底部移動的物件框,作為鋼條數量計算,直線配對的基準,根據物件的移動量,將移動的物件框歸屬到原物件框或新增一個物件框,若移動量低於預設值,則歸屬到原物件框,反之,則新增一個物件框,表示底部檢測有檢測到新的鋼條
用途:作為鋼條數量計算,直線配對的基準,避免底部檢測中途漏檢
最後的座標、數量,用以標記直鋼以及彎鋼的位置和數量
定義:
1.拍攝範圍1920*1080
2.鋼材偵測範圍866*865 運算量減少為原先的27.3%
1.2.公式ROI減少算量 比例除一下
3.每秒鐘30frame,通過範圍為13米,產品為12米
4.生產線生產速度最快為2秒鐘會通過865px(13M)(列公式)
5.每frame產生865/60=14.41的位移(列公式)
6.型鋼裁切時產生的振動以及現場因拍攝距離與光影造成拍攝物件不清晰
7.定義物件追蹤的物件移動量(motion distance) md < 40為同一個物件
要去講因為產線速度還有振動導致你定義40
1. 鋼條底部ROI 730*250
2. 運算量降低至原先的8.8%
Crop the region of interest (scene_image) using xyxy coordinates
Draw a rectangle on the region of interest
Update temporary steel count
Initialize final x-coordinate list
Update existing value
Add a new value
**鋼條矩形偵測**
在鋼條生產的過程中,每一批有一至五根鋼條,在監控區域監視的區域前,有機器負責將鋼條剪斷,鋼條被機器切斷後流至生產線上,切斷後經過品質檢測,檢查鋼條是否彎曲
我們在生產線現場截取XXXX的影像,根據樣本標示鋼條的底部,投入YOLO訓練出一個可偵測鋼條區域的模型,
該模型的用途是作為在產線生產期間,鋼條在流過生產線時,能即時偵測鋼條長度的模型,而此鋼條長度將作為後續判斷鋼條彎曲的參數
使用yolo抓取鋼條區域,輸出鋼條區域的座標、信心指數、類別名稱,將物件框的座標作為彎直辨識的基準,根據鋼條在偵測範圍的像素點,計算出筆直的鋼條在矩形框的占比(判斷鋼條彎曲的最短長度係數MinLineLength,MLL,要寫MLL的定義是=拼接的直線長度/矩形框長度),在辨識時則將物件框高度乘上彎曲係數,得到直鋼所需的像素點作為判斷的標準
用途:辨識型鋼的區域,作為彎直測的基準,用來比對直線檢測的直線是否夠長,並解決鋼條規格不同需要不同直線長度的問題
1. 有偵測到底部才觸發鋼條矩形偵測
2. 鋼材偵測範圍800px
3. 根據拼接的直線長度573計算出矩形框(782)的比例0.733 (公式)
(寫出MLL)
範例:
經過偵測以後會得到一系列影像中的物件,此時要針對目標的偵測物件進行強化,強化的方法是先初始化一個整張全黑沒有包含任何遮罩的影像表示為total_mask,針對每一個偵測到的物件,使用YOLO標示出物件的邊界框(Bounding Box,BBox) BBox,BBox框住的區域為前景(FG)加背景(BG),兩者相加代表BBox的大小,是為WPixelYOLO。隨後使用ViBe演算法進行前景背景分割(BGS),計算後產生一個前景物件的遮罩obj_mask,遮罩obj_mask的區域大小經計算後得到WPixelBGS,取得前景WPixelBGS與BBox的大小WPixelYOLO之後,計算前景WPixelBGS在BBox整體WPixelYOLO之中所佔的比例,該比例表示為RatioWPixelBGS,計算如過程如公式二,若比例太低則並非監控的物件,必須過濾掉,過濾的門檻值表示為ThrWPixelRatio,當RatioWPixelBGS小於ThrWPixelRatio時,就必須過濾掉,過濾的方式是設定該物件的整個區域為0,如公式三。
公式3
5. 以比例做為辨識彎曲的定義
6. 鋼條有不同長度 在生產過程當中,產線上移動的鋼條隨著時間推移使鋼條在影像中的大小逐漸變短
7. 嚴格定義在0.8731 標準定義在0.733
(請補充0.8731的出處,還有為什麼要定義0.8731,用意是甚麼)
**鋼條邊緣檢測**
使用邊緣檢測演算法,計算鋼條的邊緣成像,用做後續的直線檢測,根據畫面的亮度,自動調整檢測參數,亮度低表示畫面不清楚,使用sobel+canny,反之則只採用canny,以維持鋼條邊緣的成像品質與精確率
用途:為了檢測鋼條,使用直線檢測前,需要透過邊緣檢測將邊緣抓出,用作直線檢測的前處理,
畫面可能有光源不足的問題,用兩階段邊緣檢測,先將粗略的邊緣抓出,再抓出細膩的邊緣,解決光源不足
定義:
1. 若光源小於116則做兩階段邊緣檢測
2. 第一階段sobel 將灰階畫面做捲積 kernel size=3 抓出粗略的邊緣
3. 第二階段canny 從sobel畫面抓出細微的邊緣
將畫面轉換為灰階後,雙邊濾波器加強特徵,再偵測亮度和中位數,判斷目前的畫面狀況,若光源不足則執行二階段的邊緣檢測,使用Sobel作特徵強化的基礎再執行Canny邊緣檢測,於Canny邊緣檢測參數部分,若中位數足夠則使用嚴謹的參數,反之中位數不足則改用寬鬆的參數
**鋼條直線偵測**
使用霍夫曼直線檢測,根據畫面的中位數(對比度),自動調整檢測參數,以檢測鋼條上的直線,做後續直線分群的基準
直線檢測的部分,直線偵測篩選大於50個像素的直線,再過濾角度+-45度以下的直線,以達到減少運算量,並強化特徵之效果
用途:檢測鋼條的直線部分,作為辨識鋼條直度的標準,若直線夠長則代表鋼條為直,並在對比度不足時採用較寬鬆的直線檢測參數
定義:
1. 若中位數>136 則對比度足夠 則參數使用maxLineGap=20
2. 反之則參數maxLineGap=50
3. 濾除x1=x2 y1=y2的直線(直線 斜率無限大與橫線 斜率0)
4. 對左2鋼條區域開放90度直線
5. 將角度>45度 長度>20的直線加到後處理直線陣列2([num, length, angle, x1, y1, x2, y2, slope])
**鋼條直線分群**
用途:使用自定義的演算法,將鋼條兩邊的直線做分群,做後續的直線拼接
使用斜率將直線延伸到鋼條底部物件檢測結果之物件框的位置,根據直線與物件框之間的距離,將直線分配到最近的物件框,表示該直線屬於該物件框所屬之鋼條
延伸方法 直線x座標 - (紅框y - 直線y) /斜率 =直線位在紅框y的位置
減少運算量,移除距離超過50的候選紅框
計算p_x與每個紅框的左右兩邊距離 將直線分配到最近的紅框上
距離<0則代表位在紅框的左邊 反之則位在紅框的右邊

定義:
1. 直線距離依照md+10作為標準
2. 群體依照紅框數量*2做收集
流程:
1. 創建配對陣列 紅框*2([])
5. 創建後處理陣列 紅框*2([])
6. for每一根直線創建四個陣列 距離 距離絕對值 紅框id 過濾矩陣
7. 計算for每個紅框p_x 用斜率延伸直線 計算直線與紅框平行的x座標
1. 直線x座標 - (紅框y - 直線y /斜率) =直線位在紅框y的位置
2. 斜率=直線 y2-y1 /x2-x1
3. 如果直線低於紅框位置 修正值為正 反之直線高於紅框位置 修正值為負
4. 計算出直線位於紅框的座標p_x
8. 過濾 距離<50(|紅框x - p_x |) and 直線長度>50
9. 計算 距離
10. 計算 座標差距(距離保留正負)
11. 紀錄 紅框id
12. 紀錄到過濾矩陣 直線陣列 紅框x 紅框y
13. 計算最靠近的紅框index
14. 用index查找最近的紅框id,座標差距
15. 如果id 不等於0 id*2
16. 依標差距判斷直線位在紅框左邊還是右邊
17. 輸出配對結果 [直線陣列,紅框x,紅框y]

**直線拼接**
展開直線分群的直線,將最長直線視為基準線,根據2022/07/14提供之測量樣本,研究出5mm角度差在0.3,將其他線段之角度差在0.33(加上10%誤差值)的直線拼接起來
用途:將同一根鋼條的線段拼接,消除空隙造成的影響,判斷鋼條的直度
定義:
1. 角度差 其他條直線角度-基準線角度
**彎直判斷**
1. for每一邊的直線輸出單邊配對結果
2. 將配對結果(長度)做轉置
3. 找出最長直線的index以及長度
4. 輸出直線的座標角度
5. 過濾角度差超過的直線找出index
```
FOR each detected object (xyxy, conf, cls) in reverse order of output_det:
x, y, w, h = int(xyxy[0]), int(xyxy[1]), int(xyxy[2] - xyxy[0]), int(xyxy[3] - xyxy[1])
# Crop the region of interest (scene_image) using xyxy coordinates
# scene_image = crop_one_box(xyxy, imc, file='save.jpg', BGR=True)
IF 100 > w > 20 AND 20 < h < 100:
roi_y = y + h
# Draw a rectangle on the region of interest
# cv2.rectangle(roi, (x, y), (x + w, y + h), (0, 0, 255), 2)
# Update temporary steel count
temp_number_of_steels += 1
# Update x-coordinate lists
x_list.append(x + int(w / 2))
x_list_v1.append(x)
x_list_v1.append(x + w)
y_list.append(y)
IF length of x_list_final < 1:
# Initialize final x-coordinate list
x_list_final.append(x + int(w / 2))
y_list_final.append(y)
ELSE IF length of x_list_final >= 1:
exist = False
FOR i in range(length of x_list_final):
IF absolute value of ((x + int(w / 2)) - x_list_final[i]) < 40:
exist = True
FOR each index, value in enumerate(x_list_final):
IF ((x + int(w / 2)) - value) < 40 AND ((x + int(w / 2)) - value) >= 1:
# Update existing value
x_list_final[index] = (x + int(w / 2))
y_list_final[index] = (y)
IF absolute value of ((x + int(w / 2)) - value) >= 40 AND NOT exist:
# Add a new value
x_list_final.append(x + int(w / 2))
y_list_final.append(y)
exist = True
```