---
# System prepended metadata

title: roLabelImg Trouble Shooting
tags: [Machine Learning]

---

跟 LabelImg 不同，roLabelImg 在原本的基礎上，新增旋轉標記框的功能，可以符合 OBB 需求，但在實際操作上有些問題，在下面會記錄我在操作中的相關問題

# INSTALL

下載 https://github.com/cgvict/roLabelImg?tab=readme-ov-file 後運行，在執行過程中只要依照缺少的套件進行安裝，就可以完成預備

# FIX pascal_voc_io.py

存儲 Label 檔案時會跳出 error，主因跟 pascal_voc_io.py 的 prettify 有關。
原本的程式碼在處理純英文時可能沒問題，但在處理中文標籤時可能會出現編碼問題。現在的程式碼透過明確的編碼處理，確保中文字元能夠正確地被處理和儲存。

原始程式
``` python
def prettify(self, elem):
    """
        Return a pretty-printed XML string for the Element.
    """
    rough_string = ElementTree.tostring(elem, 'utf8')
    root = etree.fromstring(rough_string)
    try:
        return etree.tostring(root, pretty_print=True)
    except TypeError:
        return etree.tostring(root)
```
修改後
``` python
def prettify(self, elem):
    """
        Return a pretty-printed XML string for the Element.
    """
    # 先將 Element 轉換為字串
    rough_string = ElementTree.tostring(elem, 'utf8')

    # 將字串解碼為 Python 字串
    decoded_string = rough_string.decode('utf-8')

    # 使用 lxml 解析字串
    parser = etree.XMLParser(encoding='utf-8')
    root = etree.fromstring(decoded_string.encode('utf-8'), parser=parser)

    # 使用 lxml 的 tostring 方法，不使用 pretty_print 參數
    return etree.tostring(root, encoding='utf-8')
```

主要差異在於：
1. 編碼處理：
原本：直接使用 ElementTree.tostring(elem, 'utf8') 產生的位元組字串
現在：增加了編碼/解碼步驟，確保中文字元能正確處理
    ``` python
    decoded_string = rough_string.decode('utf-8')
    root = etree.fromstring(decoded_string.encode('utf-8'), parser=parser)
    ```
2. XML 解析器：
原本：使用預設的 XML 解析器
現在：明確指定使用 UTF-8 編碼的解析器
    ``` python
    parser = etree.XMLParser(encoding='utf-8')
    ```
3. 錯誤處理：
原本：使用 try-except 來處理 pretty_print 參數可能不支援的情況
現在：移除了 pretty_print 參數，直接使用基本的 tostring 功能
4. 輸出格式：
原本：嘗試使用 pretty_print=True 來美化輸出格式
現在：使用基本的輸出格式，確保相容性

這些修改主要是為了解決：中文字元處理的問題、XML 解析時的編碼問題、lxml 版本相容性問題

# predefined_classes.txt

data/predefined_classes.txt 為默認的類別檔案
要使軟體使用自定義的 label，可以直接修改 roLabelImg.py 第 1352 行標記檔案

將 predefined_classes.txt 修改成自定義的檔案

``` python
win = MainWindow(argv[1] if len(argv) >= 2 else None,
                     argv[2] if len(argv) >= 3 else os.path.join('data', 'predefined_classes.txt'))
```

