---
# System prepended metadata

title: python 腳本整理

---

# python 腳本整理
---

# 頁首
https://hackmd.io/@cssmiley/SJ4MDTPLj
檔案位置: https://drive.google.com/drive/folders/1ORXhxrOXyHKQ9HvkS0dvmKb4rn5SgCg5?usp=sharing
|-[使用 kivy ,Camera + autopredictor 拍照後傳回辨識檔案,使用 python kivy套件寫 iOS 和 Android APP](https://hackmd.io/@cssmiley/rk3T64_l3)
|- [打包作業: .py打包成.pyd 動態連接檔和.exe 執行檔交給客戶](#打包作業)
<details><summary>打包作業推薦寫法</summary>

推薦使用方法1. ,不用一個一個--follow-import-to=xxx 導入第三方模組
1. 生成 .pyd 時不匯入第三方模組((python IDLE內可匯入 .pyd 使用), 所有import加入到 main.py 再生成 .exe
```
nuitka --module data_analysis.py
=> 產生 data_analysis.pyd
nuitka --module auto_predictor.py
=> 產生 auto_predictor.pyd

在 main.py 加入 import requests,tqdm,lxml (auto_predictor.py 和 data_analysis.py所需的第三方模組) 
nuitka --standalone --onefile main.py
=> 產生 main.exe (不依賴於python3x.dll)
```
</details>

|- jpg_xml_rename.py
<details><summary>jpg_xml_rename.py寫法</summary>

</details>

|- [files_dispatch.py 資料夾比對](#資料夾比對)
<details><summary>資料夾比對 寫法</summary>

- 執行 python:
```
    下面指令會把 [path 資料夾]內.jpg .xml 檔, 比對 [cpath 資料夾] 內的檔案,符合的放到 matched 資料夾,不符合的放到 unmatched 資料夾,剩下的放到 other 資料夾 
    > python3 files_dispatch.py --path "現在資料夾路徑" --cpath  "對照資料夾路徑"
    例如.
    > python3 files_dispatch.py --path D:\labelImg提交檔案 --cpath  D:\labelImg提交檔案\對照資料夾

    可以把上面的 --path --cpath 換成簡寫的 -p -c ,如下所示（空格是為了和上面清楚對照可以不需要這麼多空格) 
    > python3 files_dispatch.py -p     "現在資料夾路徑" -c       "對照資料夾路徑"
    例如.
    > python3 files_dispatch.py -p D:\labelImg提交檔案 -c D:\labelImg提交檔案\對照資料夾
```
</details>

|- [xml_node_move.py 置換劣化節點](#置換劣化節點)
<details><summary>置換劣化節點 寫法</summary>

- 執行 python:
```
    @ 置換劣化類別:
	
    下面指令會使用 [new_folder 資料夾]內的[deteriorate指定劣化類別節點],替代掉 [old_folder 資料夾]內的指定劣化類別節點
    > python3 xml_node_move.py --deteriorate crack efflorescence --old_folder "要被置換的舊節點資料夾路徑" --new_folder "新節點資料夾路徑"
	> python3 xml_node_move.py --deteriorate 
    簡寫
    > python3 xml_node_move.py -d            crack efflorescence -o           "要被置換的舊節點資料夾路徑" -n           "新節點資料夾路徑"

    @ 保留劣化類別:
	
    下面指令會使用 --new_folder 資料夾內的指定保留劣化類別以外的所有節點 --keep_deteriorate , 替代掉 --old_folder 內的指定劣化類別節點
    > python3 xml_node_move.py --keep_deteriorate crack efflorescence --old_folder "要被置換的舊節點資料夾路徑" --new_folder "新節點資料夾路徑"
    簡寫
    > python3 xml_node_move.py -k            crack efflorescence -o           "要被置換的舊節點資料夾路徑" -n           "新節點資料夾路徑"
```
</details>

|- [xml_node_rename.py 更改標註名稱](#更改標註名稱)
<details><summary>更改標註名稱 寫法</summary>

```
 把[path資料夾]內的[old_tag舊劣化名稱]置換成[new_tag新劣化名稱]
    > python3 xml_node_rename.py --path "資料夾路徑" --old_tag "舊劣化名稱" --new_tag "新名稱"
    > python3 xml_node_rename.py --path D:\labelImg提交檔案 --old_tag crack_01 water_gain --new_tag crack_fissures infiltration_crack
    可以把上面的 --path --old_tag --new_tag 換成簡寫的 -p -o -n ,如下所示
    > python3 xml_node_rename.py -p D:\labelImg提交檔案 -o crack_01 water_gain -n crack_fissures infiltration_crack
```
</details>

|- [xml_parse_count.py 計算劣化數量](#計算劣化數量)
<details><summary>計算劣化數量 寫法</summary>

-   執行 python檔: 
    ```
    > python3 xml_parse_count_csv.py -p "要處理的資料夾路徑"
    > python3 xml_parse_count_csv.py -p D:\labelImg提交檔案\測試
    
    > python3 xml_parse_count_csv.py -r "要處理的遞迴資料夾路徑"
    > python3 xml_parse_count_csv.py -r D:\labelImg提交檔案\
    ```
    - 印出總數及各劣化數量如下範例:
```
    Total xml : 6, defaultdict(<class 'int'>, {'crack_00': 3, 'rusty_water': 1, 'spalling': 4, 'crack_AC': 1, 'crack': 1, 'corrosion': 1})
```
</details>

|- [xml_parse_count_csv.py 計算劣化數量](#計算劣化數量)
<details><summary>寫法</summary>

- 執行 python檔: 
```
    `> python3 xml_parse_count_csv.py "要處理的資料夾路徑"`
    - 印出總數及各劣化數量如下範例:
    `Total xml : 6, defaultdict(<class 'int'>, {'crack_00': 3, 'rusty_water': 1, 'spalling': 4, 'crack_AC': 1, 'crack': 1, 'corrosion': 1})`
    - 輸出 .csv 檔包含劣化數量資訊方便匯入到 excel 處理
    (_csvfile.csv 存放處理一個資料夾的結果)
    (_csvtotal.csv 存放處理多個資料夾的結果,用excel 匯入來加總所有處理資料夾的結果)
```
</details>

|- [xml_parse_split_deteriorate.py 分離劣化資料](#分離劣化資料)
<details><summary>分離劣化資料 寫法</summary>

- 執行 python檔:
    
```
    > python3 xml_parse_split_deteriorate.py -p "要處理的資料夾路徑"
    e.g.  python3 xml_parse_split_deteriorate.py -p D:\labelImg提交檔案\測試xml_parse_split_deteriorate\檔案重複bug測試
    > python3 xml_parse_split_deteriorate.py -r "要遞迴處理的資料夾路徑"
    e.g.  python3 xml_parse_split_deteriorate.py -r D:\labelImg提交檔案\測試xml_parse_split_deteriorate\檔案重複bug測試
```
    
    輸出單一劣化資料到對應的資料夾,複製.jpg 圖片檔並抽取單一劣化 .xml 檔進資料夾
</details>

|- python_image_upload.py
<details><summary>python_image_upload.py 寫法</summary>

</details>

|-image_filter.py
<details><summary>image_filter.py 寫法</summary>
'''

## 使用
- 需安裝套件 : conda install -c conda-forge opencv
python3 -m pip install opencv-python
(ref: https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwi_t9_Rwov5AhVMqVYBHdLODrQQFnoECCcQAQ&url=https%3A%2F%2Fresearchdatapod.com%2Fpython-modulenotfounderror-no-module-named-cv2%2F&usg=AOvVaw2_s76JWRae1yekPVnlgZhZ)
- 將這個 .py 檔放到想篩選圖片的資料夾內
- 執行 python檔: python3 image_filter.py
- 若有不符合之色碼會新建資料夾,複製.png圖片檔進資料夾,並建立 .csv檔,顯示不符合色碼之 [X座標, y座標, 色碼],可用 Excel 匯入 .csv檔查看  
## 需求
- 請使用者輸入符合色碼組(零到多組不等)
- 選擇想篩選的資料夾(內含 .jpg .png .xcf)
    - 讀取圖片,只讀取 png 檔
    - 遍歷圖片所有 pixel 
    - 取得每一 pixel 的 hex 色碼
    - 判斷是否符合輸入篩選的色碼組
    - 若不符合，
        - 檢查資料夾是否存在,若不存在就新增資料夾
        - 檢查圖片是否存在,若不存在就複製圖片檔到新資料夾內
        - 新增csv檔
        - 紀錄xy位置和色碼
        - [excel] 在 excel 整理出不符合單一色碼(e.g. 若有 3 個不符合的 #ffffff 色碼,只記錄一個 #ffffff)
- 模組化
'''

"""
- 請使用者輸入符合色碼組(零到多組不等)
- 選擇想篩選的資料夾(內含 .jpg .png .xcf)
    - 讀取圖片,只讀取 png 檔
    - 遍歷圖片所有 pixel 
    - 取得每一 pixel 的 hex 色碼
    - 判斷是否符合輸入篩選的色碼組
    - 若不符合，新增資料夾，複製圖片檔到新資料夾內，新增csv檔，紀錄xy位置和色碼,在 excel 整理出不符合單一色碼(e.g. 若有 3 個不符合的 #ffffff 色碼,只記錄一個 #ffffff)

"""
</details>

---
## 打包作業: 
.py打包成.pyd 動態連接檔和.exe 執行檔交給客戶
[回頁首](#頁首)
 檔案準備:
303,104 data_analysis.cp39-win_amd64.pyd
3,524,096 auto_predictor.cp39-win_amd64.pyd (會 import data_analysis)
main.py (會 import auto_predictor)

注意事項:
	打包環境需要有要 import 的模組,requests、tqdm、lxml

### 整理
```
auto_predictor.py (匯入import data_analysis)
data_analysis.py
main.py (匯入import auto_predictor)
```
打包環境中必須有所需的第三方模組,以這邊為例是需要 requests, tqdm, lxml

推薦使用方法1. ,不用一個一個--follow-import-to=xxx 導入第三方模組
1. 生成 .pyd 時不匯入第三方模組((python IDLE內可匯入 .pyd 使用), 所有import加入到 main.py 再生成 .exe
```
nuitka --module data_analysis.py
=> 產生 data_analysis.pyd
nuitka --module auto_predictor.py
=> 產生 auto_predictor.pyd

在 main.py 加入 import requests,tqdm,lxml (auto_predictor.py 和 data_analysis.py所需的第三方模組) 
nuitka --standalone --onefile main.py
=> 產生 main.exe (不依賴於python3x.dll)
```

2. 生成 .pyd 時匯入必要第三方模組(python IDLE內匯入 .pyd 會出現錯誤但打包 .exe 後可正常運作), 生成 .exe 
```
用 --follow-import-to=xxx 加入第三方模組
nuitka --module data_analysis.py
=> 產生 data_analysis.pyd
nuitka --module --follow-import-to=requests --folow-import-to=tqdm --follow-import-to=lxml  auto_predictor.py
=> 產生 auto_predictor.pyd

nuitka --stanalond --onefile main.py
=> 產生 main.exe

** 使用--windows-disable-console  產生執行 main.exe 時,不跳出 cmd 視窗**
nuitka --standalone --onefile --windows-disable-console main.py
```

---

## 資料夾比對
[回頁首](#頁首)
files_dispatch.py

需求:
1. 指定 現在資料夾路徑 和 對照用的資料夾路徑 進行比對 .xml .jpg 檔案
2. 把比對符合 對照用資料夾 內的檔案存放到 matched 資料夾,不符合的放到 unmatched 資料夾,把剩下的 .xml .jpg 檔案存放到 other 資料夾
3. 產生 紀錄有比對符合 matched 和比對不存在的(對照資料夾有但現有資料夾沒有) unmatched 列表的 .csv 檔案(方便用 excel 匯入查看確認)

@ 紀錄有比對符合 matched 和比對不存在的(對照資料夾有但現有資料夾沒有) unmatched 列表的 .csv 檔案
![csv檔](https://i.imgur.com/bP9tBW2.png)
    
@ csv檔的內文如下:
![csv檔內容](https://i.imgur.com/H8rsRYt.png)
    
@excel匯入.csv檔時,使用 UTF-8 編碼 (這邊用LibreOffice excel 畫面示意,沒有Microsoft excel)
![](https://i.imgur.com/3cpKyGu.png)

@ 匯入excel 後方便確認比對符合和比對不符合的(對照資料夾有但現有資料夾沒有)檔案
![](https://i.imgur.com/kCAN11w.png)

程式:
- 選取新、舊資料夾路徑(GUI或手動填)-手動填
- 比對 對照資料夾 和 原資料夾是否有相符的檔案,並移動 .jpg .xml 檔案到 matched 資料夾和 unmatched 資料夾
- 寫入比對符合和比對不存在的(對照資料夾有但現有資料夾沒有)檔案名稱到 .csv檔方便確認
- 將比對完移動後,剩下來的 .jpg .xml 檔案移動到 other 資料夾 

使用:
- 安裝套件 : 不需安裝,使用內建lib
- 執行 python:
```
    下面指令會把 --path 資料夾內.jpg .xml 檔, 比對 --cpath  內的檔案,符合的放到 matched 資料夾,
    不符合的放到 unmatched 資料夾,剩下的放到 other 資料夾 
    > python3 files_dispatch.py --path "現在資料夾路徑" --cpath  "對照資料夾路徑"
    例如.
    > python3 files_dispatch.py --path D:\labelImg提交檔案 --cpath  D:\labelImg提交檔案\對照資料夾

    可以把上面的 --path --cpath 換成簡寫的 -p -c ,如下所示（空格是為了和上面清楚對照可以不需要這麼多空格) 
    > python3 files_dispatch.py -p     "現在資料夾路徑" -c       "對照資料夾路徑"
    例如.
    > python3 files_dispatch.py -p D:\labelImg提交檔案 -c D:\labelImg提交檔案\對照資料夾
```
指令參數說明：
```
    -p, --path 
        現在資料夾 路徑,例如. `D:\labelImg提交檔案`
    -c, --cpath
        用來比對用的 .xml 檔所在的 對照資料夾 路徑,例如. `D:\labelImg提交檔案\對照資料夾`
```


---

## 更改標註名稱
[回頁首](#頁首)
xml_node_rename.py

需求:
1. 指定資料夾路徑,舊劣化名稱、新劣化名稱
2. 把資料夾內的 .xml 檔內的舊劣化名稱置換成新劣化名稱
3. 防呆: 
```
        若原本的劣化有 crack_01 efflorescence,更名時誤下指令 把 crack_01 更名成 efflorescence 而不是原本要換的 crack_fissures,
        會造成更名後的 efflorescence(實際上是裂縫龜裂) 和原本已經有的 efflorescence(白華) 混在一起,變成全部都必須重新人工標註修正,
        因此需要在更名時,若更改名稱和已有的劣化名稱重疊,需提示 
```
4. 注意事項!!: (!!注意!! 程式無法判斷,所以須正確下指令或是一次執行指處理一個劣化名稱比較保險)
```
        下指令時 --old_tag 和 --new_tag 項目需前後對照順序一致
        例如.
        (O)正確的例子
        ` --old_tag crack_01 water_gain --new_tag crack_fissures infiltration_crack` 
        crack_01 對到 crack_fissures, water_gain 對到 infiltration_crack
        (X) 錯誤的例子
        --old_tag crack01 water_gain --new_tag infiltration_crack crack_fissures
        crack_01 對到 infiltration_crack, water_gain 對到 crack_fissures
```
程式:
- 選取資料夾路徑(GUI或手動填)-手動填 , 指定舊劣化名稱、新劣化名稱
- 遍歷選取資料夾讀取 .xml 檔,取得劣化資訊
- 防呆: 比對劣化資訊,若更改名稱是已存在劣化標註,就詢問確認
- 更換指定的舊的劣化類別名稱,並寫入到 .xml 檔


使用:
- 安裝套件 : 不需安裝,使用內建lib
- 執行 python:
```
    下面指令會把 --path 資料夾內的 --old_tag 舊劣化名稱  置換成 --new_tag 新劣化名稱
    > python3 xml_node_rename.py --path "資料夾路徑" --old_tag "舊劣化名稱" --new_tag "新名稱"
    > python3 xml_node_rename.py --path D:\labelImg提交檔案 --old_tag crack_01 water_gain --new_tag crack_fissures infiltration_crack
    可以把上面的 --path --old_tag --new_tag 換成簡寫的 -p -o -n ,如下所示
    > python3 xml_node_rename.py -p     D:\labelImg提交檔案 -o        crack_01 water_gain -n        crack_fissures infiltration_crack
```
指令參數說明：
```
    -p, --path
        指定被置換掉的 .xml 檔案所在的資料夾路徑,例如. `D:\labelImg提交檔案`
    -o, --old_tag
        要被置換掉的劣化類別名稱,例如. crack_01
    -n, --new_tag
        用來置換的調劣化類別名稱,例如. crack_fissures
```
- 將 old 資料夾的 .xml檔內的特定劣化節點名稱(e.g. <crack_01> ) 換成新名稱(e.g. <crack_fissures>)

---
##  置換劣化節點
[回頁首](#頁首)
xml_node_move.py

需求:
1. 指定 old xml 和 new xml 路徑 (檔名相同) 及更動的劣化類別
2. 新建 xml,裏面包含  old xml 移除特定劣化類別節點 (ex. <crack>)後,把 new xml 特定劣化類別節點 append 到 old xml ,放到 replaced 資料夾

程式:
- 選取新、舊資料夾路徑(GUI或手動填)-手動填 , 指定劣化類別
- 遍歷選取資料夾讀取 .xml 檔
- 新建空xml,裡面包含移除舊的劣化類別節點,將更動的劣化類別節點複製,並寫入到舊的 .xml 放到 replaced 資料夾(沒有更動 old xml 和 new xml)

使用:
- 安裝套件 : 不需安裝,使用內建lib
- 執行 python:
```
    @ 置換劣化類別:
    下面指令會使用 --new_folder 資料夾內的指定劣化類別節點 --deteriorate , 替代掉 --old_folder 內的指定劣化類別節點
    > python3 xml_node_move.py --deteriorate crack efflorescence --old_folder "要被置換的舊節點資料夾路徑" --new_folder "新節點資料夾路徑"

    可以把上面的 --deteriorate --old_folder --newfolder 換成簡寫的 -d -o -n ,如下所示（空格是為了和上面清楚對照可以不需要這麼多空格) 
    > python3 xml_node_move.py -d            crack efflorescence -o           "要被置換的舊節點資料夾路徑" -n           "新節點資料夾路徑"

    @ 保留劣化類別:
    下面指令會使用 --new_folder 資料夾內的指定保留劣化類別以外的所有節點 --keep_deteriorate , 替代掉 --old_folder 內的指定劣化類別節點
    > python3 xml_node_move.py --keep_deteriorate crack efflorescence --old_folder "要被置換的舊節點資料夾路徑" --new_folder "新節點資料夾路徑"

    可以把上面的 --keep_deteriorate --old_folder --newfolder 換成簡寫的 -k -o -n ,如下所示（空格是為了和上面清楚對照可以不需要這麼多空格) 
    > python3 xml_node_move.py -k            crack efflorescence -o           "要被置換的舊節點資料夾路徑" -n           "新節點資料夾路徑"
```
指令參數說明：
```
    -d 置換劣化節點 和 -k 保留劣化節點 是互斥選項,無法同時執行
    -d, --deteriorate  
        指定要置換的劣化類別,可指定一個到多個,例如. `-d crack` 或 `-d crack efflorescence`,這些劣化類別的節點會被置換掉
    -k, --keep_deteriorate
        指定保留的劣化類別,可指定一個到多個, 例如. `-k crack` 或 `-k crack efflorescence`,除了指定的劣化類別外都會置換成新的版本
    
    -o, --old_folder
        要被置換掉的 .xml 檔案所在的資料夾路徑,例如. `D:\labelImg提交檔案`
    -n, --new_folder
        用來置換的調整過後的新劣化節點的 .xml 檔所在的資料夾路徑,例如. `D:\labelImg提交檔案\白華_efflorescence`
```
- 將 old 資料夾的 .xml檔內的特定劣化節點資訊(e.g. <crack>附帶的框選位置尺寸資訊) 換成 new 資料夾的 .xml檔的劣化節點資訊

---
## 計算劣化數量

[回頁首](#頁首)

```
xml_parse_count.py # 只計算數量不輸出 .csv 檔
xml_parse_count_csv.py # 計算數量並輸出 .csv檔
```
### 需求
"執行的資料夾名稱_csvfile.csv" 存放處理一個資料夾的結果,計算的是以一個框選為單位,只要一個框選標註數量就加 1


"_csvtotal.csv" 存放處理多個資料夾的結果,用excel 匯入來加總所有處理資料夾的結果,計算的是以一張圖出現該種劣化為單位,一張圖有出現劣化計數就加 1,不管多少框選都只算 1 個,下圖說明 對不同資料夾執行多次產生的 "_csvtotal.csv" :
![](https://i.imgur.com/OPr0ymS.png)

1. 計算劣化數量
    - 選取資料夾路徑(GUI或手動填)-手動填
    - 遍歷選取資料夾讀取 .xml 檔
    - 列出該張圖片的所有劣化分類
    - 計算各項劣化圖片總數量
    

    ## 使用
    - 安裝套件 : 不需安裝,使用內建lib
    - 執行 python檔: 
    ```
    > python3 xml_parse_count_csv.py -p "要處理的資料夾路徑"
    > python3 xml_parse_count_csv.py -p D:\labelImg提交檔案\測試
    
    > python3 xml_parse_count_csv.py -r "要處理的遞迴資料夾路徑"
    > python3 xml_parse_count_csv.py -r D:\labelImg提交檔案\
    ```
    - 印出總數及各劣化數量如下範例:
    `Total xml : 6, defaultdict(<class 'int'>, {'crack_00': 3, 'rusty_water': 1, 'spalling': 4, 'crack_AC': 1, 'crack': 1, 'corrosion': 1})`
    - 輸出 .csv 檔包含劣化數量資訊方便匯入到 excel 處理
    (_csvfile.csv 存放處理一個資料夾的結果)
    (_csvtotal.csv 存放處理多個資料夾的結果,用excel 匯入來加總所有處理資料夾的結果)

---
## 分離劣化資料
[回頁首](#頁首)
`xml_parse_split_deteriorate.py`
### 需求
![](https://i.imgur.com/nFt8lB1.png)


複製 .jpg圖片 和輸出 單一劣化 .xml檔 到新建的單一劣化資料夾
前置作業:
- 比對同一張圖片的多重劣化和個單一劣化的 xml 內容結構差異,確認需更改的地方
程式:
- 選取資料夾路徑(GUI或手動填)-手動填
- 遍歷選取資料夾讀取 .xml 檔
- 將劣化類別複製,並寫入到分別的劣化類別 .xml 檔
- 複製.jpg圖片到劣化類別資料夾
- 模組化

使用

    安裝套件 : 不需安裝,使用內建lib
    將這個 .py 檔放到想篩選圖片的資料夾內
    執行 python檔:
    
```
    > python3 xml_parse_split_deteriorate.py -p "要處理的資料夾路徑"
    e.g.  python3 xml_parse_split_deteriorate.py -p D:\labelImg提交檔案\測試xml_parse_split_deteriorate\檔案重複bug測試
    > python3 xml_parse_split_deteriorate.py -r "要遞迴處理的資料夾路徑"
    e.g.  python3 xml_parse_split_deteriorate.py -r D:\labelImg提交檔案\測試xml_parse_split_deteriorate\檔案重複bug測試
```
    
    輸出單一劣化資料到對應的資料夾,複製.jpg 圖片檔並抽取單一劣化 .xml 檔進資料夾

注意:
若是windows下,指令使用
 ```
python xml_parse_split_deteriorate.py -p "D:\labelImg提交檔案\測試\" 
```
最後的雙引號會被跳脫路徑名會變成多了雙引號==> 
```
D:\labelImg提交檔案\測試"
``` 
建議後面不加"\":
```
 python xml_parse_split_deteriorate.py -p D:\labelImg提交檔案\測試 
```

---