> For the complete documentation index, see [llms.txt](https://docs.xiwind-corp.com/tech/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.xiwind-corp.com/tech/python-library/enum-lie-ju-class/fan-li.md).

# 範例

## 範例

***

### 範例 – 使用 Enums 進行比較

Enums 可以進行比較。例如：`is`, `==`...。

當您比較 enum members 時，最好透過它們的 identity來比較它們(使用 `is`)，而不是通過它們的值來比較它們(使用 `==` )。 這是因為不同的 enum members "可能"具有相同的值。

{% code title="PYTHON" %}

```python
from enum import Enum

class Size(Enum):
    S = 1
    M = 2
    L = 3
    XL = 4

print(Size.S.value < Size.M.value)    # Output: True
print(Size.L.value > Size.XL.value)   # Output: False
print(Size.L.value is Size.XL.value)  # Output: False
```

{% endcode %}

### 範例 – 影像處理

***

{% code title="PYTHON" %}

```python
import cv2
from enum import Enum

class Operation(Enum):
    GRAYSCALE = 1
    BLUR = 2
    EDGE_DETECTION = 3

def process_image(img_path, operation):
    img = cv2.imread(img_path)

    if operation == Operation.GRAYSCALE:
        processed_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    elif operation == Operation.BLUR:
        processed_img = cv2.GaussianBlur(img, (15, 15), 0)
    elif operation == Operation.EDGE_DETECTION:
        processed_img = cv2.Canny(img, 100, 200)

    cv2.imshow('Processed Image', processed_img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

# Usage:
process_image('path_to_image.jpg', Operation.GRAYSCALE)

```

{% endcode %}

### 範例 – 深度學習

***

**建立不同類型的深度學習模型：**

{% code title="PYTHON" %}

```python
import torch
from torchvision import models
from enum import Enum

class ModelType(Enum):
    RESNET = 1
    ALEXNET = 2
    VGG = 3

def get_model(model_type):
    if model_type == ModelType.RESNET:
        model = models.resnet50(weights='DEFAULT')
    elif model_type == ModelType.ALEXNET:
        model = models.alexnet(weights='DEFAULT')
    elif model_type == ModelType.VGG:
        model = models.vgg16(weights='DEFAULT')

    return model

# Usage:
model = get_model(ModelType.RESNET)

```

{% endcode %}

**建立不同類型的損失函數：**

{% code title="PYTHON" %}

```python
import torch.nn as nn
from enum import Enum

class LossType(Enum):
    CROSS_ENTROPY = 1
    MSE = 2
    NLL = 3

def get_loss(loss_type):
    if loss_type == LossType.CROSS_ENTROPY:
        loss_function = nn.CrossEntropyLoss()
    elif loss_type == LossType.MSE:
        loss_function = nn.MSELoss()
    elif loss_type == LossType.NLL:
        loss_function = nn.NLLLoss()

    return loss_function

# Usage:
loss_function = get_loss(LossType.CROSS_ENTROPY)
```

{% endcode %}

### 範例 – 應用

***

在此範例中，使用 enum 的好處變得更加明顯。 您可以使用 enums 擁有統一的介面 (interface)，而不是使用多個方法或 string 參數來指定 operation 和輸出。 這將使您的程式碼更易於維護並降低錯誤風險。

此外，透過將這些相關常數分組為 enums Class，您可以在程序中傳遞它們並在各種 contexts 中使用它們，因為您知道它們只能具有一組定義的值。

使用 `@property` 和 `@setter` 的主要優點是能夠在設置 enum 時加入驗證。 在這種情況下，我們確保提供的值是適當的 enum 實例。 如果不是，則會引發 `ValueError`。 這可以使您的代碼更加 robust，並防止出現難以追蹤的錯誤。

{% code title="PYTHON" %}

```python
import cv2
import torch
import numpy as np
from enum import Enum
from torchvision import models
from torchvision import transforms

class ImageOperation(Enum):
    GRAYSCALE = 1
    BLUR = 2
    EDGE_DETECTION = 3
    DEEP_LEARNING = 4

class OutputFormat(Enum):
    JPG = 1
    PNG = 2
    TIFF = 3

class ImageProcessor:
    def __init__(self, operation, output_format):
        self._operation = ImageOperation(operation)
        self._output_format = output_format if output_format is None else OutputFormat(output_format)
        self.model = models.resnet50(weights='DEFAULT')

    def process_image(self, img_path):
        img = cv2.imread(img_path)

        if self.operation == ImageOperation.GRAYSCALE:
            processed_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        elif self.operation == ImageOperation.BLUR:
            processed_img = cv2.GaussianBlur(img, (15, 15), 0)
        elif self.operation == ImageOperation.EDGE_DETECTION:
            processed_img = cv2.Canny(img, 100, 200)
        elif self.operation == ImageOperation.DEEP_LEARNING:
            # Preprocess and run through model (assumes model is some kind of image classifier)
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # Convert from BGR to RGB
            img_tensor = self.preprocess(img)
            output = self.model(img_tensor.unsqueeze(0))
            confidence_score, predicted = torch.max(output, 1)
            processed_img = self.visualize(img, confidence_score, predicted)

        # Save image in desired format
        if self.output_format is None:
            return processed_img
        elif self.output_format == OutputFormat.JPG:
            cv2.imwrite('output.jpg', processed_img, [cv2.IMWRITE_JPEG_QUALITY, 100])
        elif self.output_format == OutputFormat.PNG:
            cv2.imwrite('output.png', processed_img)
        elif self.output_format == OutputFormat.TIFF:
            cv2.imwrite('output.tiff', processed_img)

    def preprocess(self, img):
        # Define the transformations: resize -> to tensor -> normalize
        transform = transforms.Compose([
            transforms.ToPILImage(),
            transforms.Resize((224, 224)),  # Most pretrained models expect 224x224 images
            transforms.ToTensor(),
            transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])  # Values from ImageNet
        ])
    
        # Apply the transformations
        img_tensor = transform(img)
        return img_tensor


    def visualize(self, img, confidence_score, predicted):
        # Placeholder for your visualization method based on the model's output
        print(f"imagenet labels id:{predicted.item()}, confidence_score:{confidence_score.item():.2f}")
        return img

    @property
    def operation(self):
        return self._operation

    @operation.setter
    def operation(self, operation):
        if not isinstance(operation, ImageOperation):
            raise ValueError("operation must be an instance of ImageOperation Enum.")
        self._operation = operation

    @property
    def output_format(self):
        return self._output_format

    @output_format.setter
    def output_format(self, output_format):
        if output_format is not None and not isinstance(output_format, OutputFormat):
            raise ValueError("output_format must be an instance of OutputFormat Enum or None.")
        self._output_format = output_format

# Usage:
processor = ImageProcessor(ImageOperation.DEEP_LEARNING, None)
processor.process_image('n02085782_2.jpg')

# Change operation and output format
processor.operation = ImageOperation.GRAYSCALE
processor.output_format = OutputFormat.PNG
processor.process_image('n02085782_2.jpg')
```

{% endcode %}

**執行結果：**

```
imagenet labels id:152, confidence_score:0.89
```

<div><figure><img src="/files/cKWDDjViyR2rGSg5jtcT" alt=""><figcaption><p>輸入</p></figcaption></figure> <figure><img src="/files/sun8KAQGWLQWVlC6NAFq" alt=""><figcaption><p>輸出</p></figcaption></figure></div>

{% hint style="info" %}
Imagenet labels id 解碼詳見: [imagenet 1000 class idx to human readable labels](https://gist.github.com/yrevar/942d3a0ac09ec9e5eb3a#file-imagenet1000_clsidx_to_labels-txt)
{% endhint %}

## 參考資料

***

[enum — Support for enumerations — Python 3.11.4 documentation](https://docs.python.org/3.11/library/enum.html#)

[Enum HOWTO — Python 3.11.4 documentation](https://docs.python.org/3.11/howto/enum.html#enum-howto)
