diff --git a/.github/workflows/calibreapp-image-actions.yml b/.github/workflows/calibreapp-image-actions.yml index 9abfec4631..5dca04c26e 100644 --- a/.github/workflows/calibreapp-image-actions.yml +++ b/.github/workflows/calibreapp-image-actions.yml @@ -22,6 +22,6 @@ jobs: - name: Compress Images uses: calibreapp/image-actions@main with: - # The `GITHUB_TOKEN` is automatically generated by GitHub and scoped only to the repository that is currently running the action. By default, the action can’t update Pull Requests initiated from forked repositories. + # The `GITHUB_TOKEN` is automatically generated by GitHub and scoped only to the repository that is currently running the action. By default, the action can't update Pull Requests initiated from forked repositories. # See https://docs.github.com/en/actions/reference/authentication-in-a-workflow and https://help.github.com/en/articles/virtual-environments-for-github-actions#token-permissions - githubToken: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/content/en/guides/models/track/log/image-normalization.md b/content/en/guides/models/track/log/image-normalization.md new file mode 100644 index 0000000000..d6bacebd03 --- /dev/null +++ b/content/en/guides/models/track/log/image-normalization.md @@ -0,0 +1,141 @@ +--- +title: "Image Normalization Guide" +description: "Learn how wandb.Image handles normalization for different input types and how to control this behavior" +--- + + +When you pass PyTorch tensors or NumPy arrays to `wandb.Image`, the pixel values are automatically normalized to the range [0, 255] unless you set `normalize=False`. This guide explains how image normalization works and how to control it. + +## When normalization is applied + +| Input Type | Format | Normalization Applied | Notes | +|------------|--------|----------------------|-------| +| **PyTorch tensors** | `(channel, height, width)` | ✅ Yes | Automatically normalized to [0, 255] range | +| **NumPy arrays** | `(height, width, channel)` | ✅ Yes | Automatically normalized to [0, 255] range | +| **PIL Images** | PIL Image object | ❌ No | Passed as-is without modification | +| **File paths** | String path to image file | ❌ No | Loaded as-is without modification | + +## Normalization algorithm + +The normalization algorithm automatically detects the input range and applies the appropriate transformation: + +- **If data is in range [0, 1]**: Values are multiplied by 255 and converted to uint8 + ```python + normalized_data = (data * 255).astype(np.uint8) + ``` + +- **If data is in range [-1, 1]**: Values are rescaled to [0, 255] using: + ```python + normalized_data = (255 * 0.5 * (data + 1)).astype(np.uint8) + ``` + +- **For any other range**: Values are clipped to [0, 255] and converted to uint8 + ```python + normalized_data = data.clip(0, 255).astype(np.uint8) + ``` + +## Examples of normalization effects + +### Example 1: [0, 1] range data + +```python +import torch +import wandb + +# Create tensor with values in [0, 1] range +tensor_0_1 = torch.rand(3, 64, 64) # Random values between 0 and 1 + +# This will multiply all values by 255 +image = wandb.Image(tensor_0_1, caption="Normalized from [0,1] range") +``` + +### Example 2: [-1, 1] range data + +```python +import torch +import wandb + +# Create tensor with values in [-1, 1] range +tensor_neg1_1 = torch.rand(3, 64, 64) * 2 - 1 # Random values between -1 and 1 + +# This will rescale: -1 → 0, 0 → 127.5, 1 → 255 +image = wandb.Image(tensor_neg1_1, caption="Normalized from [-1,1] range") +``` + +**Note on visual contrast**: The [-1, 1] normalization creates higher visual contrast compared to [0, 1] normalization. This is because: +- Negative values (like -0.8) become very dark (around 25) +- Positive values (like 0.8) become very bright (around 230) +- Values near 0 become mid-gray (127.5) + +This "stretches" the visual range, making differences between pixel values more pronounced. This is particularly useful for highlighting subtle patterns in machine learning data, but if you want less contrast, consider preprocessing your data to a [0, 1] range before logging. + +### Example 3: Avoid normalization with PIL Images +Normalization is not applied to PIL Images. + +```python +import torch +from PIL import Image as PILImage +import wandb + +# Create tensor with values in [0, 1] range +tensor_0_1 = torch.rand(3, 64, 64) + +# Convert to PIL Image to avoid normalization +pil_image = PILImage.fromarray((tensor_0_1.permute(1, 2, 0).numpy() * 255).astype('uint8')) +image = wandb.Image(pil_image, caption="No normalization applied") +``` + +### Example 4: Using normalize=False +To explicitly turn off image normalization without converting the image, set `normalize=False`. + +```python +import torch +import wandb + +# Create tensor with values in [0, 1] range +tensor_0_1 = torch.rand(3, 64, 64) + +# Disable normalization - values will be clipped to [0, 255] +image = wandb.Image(tensor_0_1, normalize=False, caption="Normalization disabled") +``` + +## When to use different approaches + +### Use PIL conversion when: +- You want complete control over pixel values +- You need custom preprocessing (filters, brightness adjustments, etc.) +- You want to use PIL's image processing capabilities +- You're debugging and want to see exact values being logged + +### Use normalize=False when: +- You want to see raw tensor values as they are +- Your data is already in the correct range (like [0, 255] integers) +- You're debugging normalization issues +- Quick testing without additional processing steps + +### Use automatic normalization when: +- You want consistent behavior across different input types +- Your data is in standard ranges ([0, 1] or [-1, 1]) +- You want W&B to handle the conversion automatically + +## Troubleshooting + +### Best practices + +1. **For consistent results**: Pre-process your data to the expected [0, 255] range before logging +2. **To avoid normalization**: Convert tensors to PIL Images using `PILImage.fromarray()` +3. **For debugging**: Use `normalize=False` to see the raw values (they will be clipped to [0, 255]) +4. **For precise control**: Use PIL Images when you need exact pixel values +5. **For highlighting subtle patterns**: Use [-1, 1] normalization to increase visual contrast +6. **For natural-looking images**: Use [0, 1] normalization or preprocess to [0, 255] range +7. **For custom processing**: Use PIL conversion when you need to apply filters or adjustments + +### Common issues and solutions + +- **Unexpected brightness**: If your tensor values are in [0, 1] range, they will be multiplied by 255, making the image much brighter. **Solution**: Preprocess to [0, 255] range or use PIL conversion. +- **Data loss**: Values outside the [0, 255] range will be clipped, potentially losing information. **Solution**: Check your data range and preprocess appropriately. +- **Inconsistent behavior**: Different input types (tensor vs PIL vs file path) may produce different results. **Solution**: Use consistent input types or understand the normalization behavior for each type. + +## Testing your code + +You can test the normalization behavior using our [Image Normalization Demo Notebook](https://github.com/wandb/wandb/blob/main/wandb_image_normalization_demo.ipynb) which demonstrates all the examples above with visual output. \ No newline at end of file diff --git a/content/en/guides/models/track/log/media.md b/content/en/guides/models/track/log/media.md index 7d118e2db6..730b711c1c 100644 --- a/content/en/guides/models/track/log/media.md +++ b/content/en/guides/models/track/log/media.md @@ -58,7 +58,7 @@ with wandb.init(project="image-log-example") as run: run.log({"examples": images}) ``` -We assume the image is gray scale if the last dimension is 1, RGB if it's 3, and RGBA if it's 4. If the array contains floats, we convert them to integers between `0` and `255`. If you want to normalize your images differently, you can specify the [`mode`](https://pillow.readthedocs.io/en/stable/handbook/concepts.html#modes) manually or just supply a [`PIL.Image`](https://pillow.readthedocs.io/en/stable/reference/Image.html), as described in the "Logging PIL Images" tab of this panel. +W&B assumes the image is gray scale if the last dimension is 1, RGB if it's 3, and RGBA if it's 4. If the array contains floats, W&B automatically normalizes them to integers between `0` and `255`. For detailed information about normalization with PyTorch tensors and NumPy arrays, see the [Image normalization guide]({{< relref "/guides/models/track/log/image-normalization.md" >}}). To normalize your images differently, you can specify the [`mode`](https://pillow.readthedocs.io/en/stable/handbook/concepts.html#modes) manually or supply a [`PIL.Image`](https://pillow.readthedocs.io/en/stable/reference/Image.html), as described in the "Logging PIL Images" tab. {{% /tab %}} {{% tab header="Logging PIL Images" %}} For full control over the conversion of arrays to images, construct the [`PIL.Image`](https://pillow.readthedocs.io/en/stable/reference/Image.html) yourself and provide it directly. @@ -97,7 +97,6 @@ with wandb.init(project="") as run: {{% /tab %}} {{< /tabpane >}} - ## Image overlays diff --git a/content/en/ref/python/sdk/data-types/Image.md b/content/en/ref/python/sdk/data-types/Image.md index 384811b98f..f7cda75d46 100644 --- a/content/en/ref/python/sdk/data-types/Image.md +++ b/content/en/ref/python/sdk/data-types/Image.md @@ -9,10 +9,10 @@ data_type_classification: class -## class `Image` +class `Image` A class for logging images to W&B. -### method `Image.__init__` +method `Image.__init__` ```python __init__( @@ -103,10 +103,13 @@ with wandb.init() as run: run.log({"examples": examples}) ``` +Image normalization + +When you pass PyTorch tensors or NumPy arrays to `wandb.Image`, the pixel values are automatically normalized to the range [0, 255] unless you set `normalize=False`. For detailed information about normalization behavior, examples, and best practices, see the [Image Normalization Guide]({{< relref "/guides/models/track/log/image-normalization.md" >}}). --- -### property Image.image +property Image.image diff --git a/content/ja/guides/integrations/pytorch.md b/content/ja/guides/integrations/pytorch.md index 4577f8cb56..320800c3cb 100644 --- a/content/ja/guides/integrations/pytorch.md +++ b/content/ja/guides/integrations/pytorch.md @@ -49,7 +49,7 @@ for batch_idx, (data, target) in enumerate(train_loader): ## 画像とメディアのログ -画像データを持つ PyTorch `Tensors` を [`wandb.Image`]({{< relref path="/ref/python/data-types/image.md" lang="ja" >}}) に渡すことができ、[`torchvision`](https://pytorch.org/vision/stable/index.html) のユーティリティが自動的に画像に変換します。 +画像データを持つ PyTorch `Tensors` を [`wandb.Image`]({{< relref "/ref/python/data-types/image.md" >}}) に渡すことができ、[`torchvision`](https://pytorch.org/vision/stable/index.html) のユーティリティが自動的に画像に変換します。 ```python images_t = ... # PyTorch Tensors として画像を生成またはロードする diff --git a/content/ja/guides/models/track/log/media.md b/content/ja/guides/models/track/log/media.md index f3d7206d90..c650429d2b 100644 --- a/content/ja/guides/models/track/log/media.md +++ b/content/ja/guides/models/track/log/media.md @@ -52,7 +52,7 @@ images = wandb.Image(image_array, caption="Top: Output, Bottom: Input") wandb.log({"examples": images}) ``` -最後の次元が1の場合はグレースケール、3の場合はRGB、4の場合はRGBAと仮定します。配列が浮動小数点数を含む場合、それらを`0`から`255`の整数に変換します。異なる方法で画像を正規化したい場合は、[`mode`](https://pillow.readthedocs.io/en/stable/handbook/concepts.html#modes)を手動で指定するか、`"Logging PIL Images"`タブで説明されているように、単に[`PIL.Image`](https://pillow.readthedocs.io/en/stable/reference/Image.html)を提供することができます。 +最後の次元が1の場合はグレースケール、3の場合はRGB、4の場合はRGBAと仮定します。配列が浮動小数点数を含む場合、正規化アルゴリズムを使用して自動的に`0`から`255`の整数に変換します。PyTorchテンソルとNumPy配列での正規化の動作についての詳細は、[Imageリファレンスの画像正規化セクション]({{< relref "/ref/python/data-types/image.md#image-normalization" >}})を参照してください。異なる方法で画像を正規화したい場合は、[`mode`](https://pillow.readthedocs.io/en/stable/handbook/concepts.html#modes)を手動で指定するか、`"Logging PIL Images"`タブで説明されているように、単に[`PIL.Image`](https://pillow.readthedocs.io/en/stable/reference/Image.html)を提供することができます。 {{% /tab %}} {{% tab header="PIL Imagesをログする" %}} 配列から画像への変換を完全に制御するために、[`PIL.Image`](https://pillow.readthedocs.io/en/stable/reference/Image.html)を自分で構築し、直接提供してください。 @@ -564,7 +564,7 @@ runが終了すると、UIで分子の3D可視化と対話できるようにな ### PNG 画像 -[`wandb.Image`]({{< relref path="/ref/python/data-types/image.md" lang="ja" >}})は`numpy`配列や`PILImage`のインスタンスをデフォルトでPNGに変換します。 +`wandb.Image`は`numpy`配列や`PILImage`のインスタンスをデフォルトでPNGに変換します。 ```python wandb.log({"example": wandb.Image(...)}) @@ -584,7 +584,7 @@ wandb.log({"example": wandb.Video("myvideo.mp4")}) ## 分子の2Dビュー -[`wandb.Image`]({{< relref path="/ref/python/data-types/image.md" lang="ja" >}})データ型と[`rdkit`](https://www.rdkit.org/docs/index.html)を使用して分子の2Dビューをログできます: +[`wandb.Image`]({{< relref "/ref/python/data-types/image.md" >}})データ型と[`rdkit`](https://www.rdkit.org/docs/index.html)を使用して分子の2Dビューをログできます: ```python molecule = rdkit.Chem.MolFromSmiles("CC(=O)O") diff --git a/content/ja/launch/integration-guides/dagster.md b/content/ja/launch/integration-guides/dagster.md index 89497aa907..dfd089d28d 100644 --- a/content/ja/launch/integration-guides/dagster.md +++ b/content/ja/launch/integration-guides/dagster.md @@ -181,7 +181,7 @@ def create_dataset(): W&B は複数のピクルスベースのシリアライズモジュール([pickle](https://docs.python.org/3/library/pickle.html), [dill](https://github.com/uqfoundation/dill), [cloudpickle](https://github.com/cloudpipe/cloudpickle), [joblib](https://github.com/joblib/joblib)) をサポートしています。また、[ONNX](https://onnx.ai/) や [PMML](https://en.wikipedia.org/wiki/Predictive_Model_Markup_Language) といったより高度なシリアライズも利用できます。[Serialization]({{< relref path="#serialization-configuration" lang="ja" >}}) セクションを参照してください。 {{% /tab %}} {{% tab "W&B Object" %}} -ネイティブ W&B オブジェクト (例: [Table]({{< relref path="/ref/python/data-types/table.md" lang="ja" >}}), [Image]({{< relref path="/ref/python/data-types/image.md" lang="ja" >}}), or [Graph]({{< relref path="/ref/python/data-types/graph.md" lang="ja" >}})) のいずれかが作成された Artifact にインテグレーションによって追加されます。以下は Table を使った例です。 +ネイティブ W&B オブジェクト (例: [Table]({{< relref path="/ref/python/data-types/table.md" lang="ja" >}}), [Image]({{< relref "/ref/python/data-types/image.md" >}}), or [Graph]({{< relref path="/ref/python/data-types/graph.md" lang="ja" >}})) のいずれかが作成された Artifact にインテグレーションによって追加されます。以下は Table を使った例です。 ```python import wandb diff --git a/content/ja/ref/python/data-types/image.md b/content/ja/ref/python/data-types/image.md index a38c29dfdf..d725996f00 100644 --- a/content/ja/ref/python/data-types/image.md +++ b/content/ja/ref/python/data-types/image.md @@ -30,9 +30,107 @@ Image( 注意 : `wandb.Image` として `torch.Tensor` をログする際、画像は正規化されます。画像を正規化したくない場合は、テンソルを PIL Image に変換してください。 -#### 例: +画像の正規化 -### numpy 配列から wandb.Image を作成 +PyTorch テンソルや NumPy 配列を `wandb.Image` に渡すと、`normalize=False` を設定しない限り、ピクセル値は自動的に [0, 255] の範囲に正規化されます。この正規化は、一般的な画像データ形式を処理し、適切な表示を確保するために設計されています。 + +正規化が適用される場合 + +正規化は以下に適用されます: +- **PyTorch テンソル** (形式: `(channel, height, width)`) +- **NumPy 配列** (形式: `(height, width, channel)`) + +正規化は以下には適用されません: +- **PIL 画像** (そのまま渡される) +- **ファイルパス** (そのまま読み込まれる) + +正規化アルゴリズム + +正規化アルゴリズムは入力範囲を自動的に検出し、適切な変換を適用します: + +1. **データが [0, 1] の範囲にある場合**: 値に255を掛けてuint8に変換 + ```python + normalized_data = (data * 255).astype(np.uint8) + ``` + +2. **データが [-1, 1] の範囲にある場合**: 以下の式で [0, 255] にリスケール + ```python + normalized_data = (255 * 0.5 * (data + 1)).astype(np.uint8) + ``` + +3. **その他の範囲の場合**: 値を [0, 255] にクリップしてuint8に変換 + ```python + normalized_data = data.clip(0, 255).astype(np.uint8) + ``` + +正規化効果の例 + +**例1: [0, 1] 範囲のデータ** +```python +import torch +import wandb + +# [0, 1] 範囲の値を持つテンソルを作成 +tensor_0_1 = torch.rand(3, 64, 64) # 0から1の間のランダム値 + +# すべての値に255を掛ける +image = wandb.Image(tensor_0_1, caption="[0,1]範囲から正規化") +``` + +**例2: [-1, 1] 範囲のデータ** +```python +import torch +import wandb + +# [-1, 1] 範囲の値を持つテンソルを作成 +tensor_neg1_1 = torch.rand(3, 64, 64) * 2 - 1 # -1から1の間のランダム値 + +# リスケール: -1 → 0, 0 → 127.5, 1 → 255 +image = wandb.Image(tensor_neg1_1, caption="[-1,1]範囲から正規化") +``` + +**例3: PIL画像で正規化を回避** +```python +import torch +from PIL import Image as PILImage +import wandb + +# [0, 1] 範囲の値を持つテンソルを作成 +tensor_0_1 = torch.rand(3, 64, 64) + +# PIL画像に変換して正規化を回避 +pil_image = PILImage.fromarray((tensor_0_1.permute(1, 2, 0).numpy() * 255).astype('uint8')) +image = wandb.Image(pil_image, caption="正規化は適用されません") +``` + +**例4: normalize=False を使用** +```python +import torch +import wandb + +# [0, 1] 範囲の値を持つテンソルを作成 +tensor_0_1 = torch.rand(3, 64, 64) + +# 正規化を無効化 - 値は [0, 255] にクリップされる +image = wandb.Image(tensor_0_1, normalize=False, caption="正規化無効") +``` + +ベストプラクティス + +1. **一貫した結果のため**: ログする前にデータを期待される [0, 255] 範囲に前処理する +2. **正規化を回避するため**: `PILImage.fromarray()` を使用してテンソルをPIL画像に変換する +3. **デバッグのため**: `normalize=False` を使用して生の値を確認する([0, 255] にクリップされる) +4. **精密な制御のため**: 正確なピクセル値が必要な場合はPIL画像を使用する + +よくある落とし穴 + +- **予期しない明度**: テンソル値が [0, 1] 範囲にある場合、255倍されるため画像が非常に明るくなる +- **データ損失**: [0, 255] 範囲外の値はクリップされ、情報が失われる可能性がある +- **一貫性のない動作**: 異なる入力タイプ(テンソル vs PIL vs ファイルパス)で異なる結果が得られる可能性がある + +例: + +numpy 配列から wandb.Image を作成 ```python import numpy as np @@ -47,7 +145,7 @@ with wandb.init() as run: run.log({"examples": examples}) ``` -### PILImage から wandb.Image を作成 +PILImage から wandb.Image を作成 ```python import numpy as np @@ -66,7 +164,7 @@ with wandb.init() as run: run.log({"examples": examples}) ``` -### .png (デフォルト) ではなく .jpg をログ +.png (デフォルト) ではなく .jpg をログ ```python import numpy as np @@ -84,9 +182,9 @@ with wandb.init() as run: | Attributes | | | :--- | :--- | -## メソッド +メソッド -### `all_boxes` +`all_boxes` [View source](https://www.github.com/wandb/wandb/tree/637bddf198525810add5804059001b1b319d6ad1/wandb/sdk/data_types/image.py#L610-L631) @@ -100,7 +198,7 @@ all_boxes( ) -> Union[List[Optional[dict]], bool] ``` -### `all_captions` +`all_captions` [View source](https://www.github.com/wandb/wandb/tree/637bddf198525810add5804059001b1b319d6ad1/wandb/sdk/data_types/image.py#L633-L637) @@ -111,7 +209,7 @@ all_captions( ) -> Union[bool, Sequence[Optional[str]]] ``` -### `all_masks` +`all_masks` [View source](https://www.github.com/wandb/wandb/tree/637bddf198525810add5804059001b1b319d6ad1/wandb/sdk/data_types/image.py#L587-L608) @@ -125,7 +223,7 @@ all_masks( ) -> Union[List[Optional[dict]], bool] ``` -### `guess_mode` +`guess_mode` [View source](https://www.github.com/wandb/wandb/tree/637bddf198525810add5804059001b1b319d6ad1/wandb/sdk/data_types/image.py#L474-L486) @@ -137,7 +235,7 @@ guess_mode( np.array が表している画像の種類を推測します。 -### `to_uint8` +`to_uint8` [View source](https://www.github.com/wandb/wandb/tree/637bddf198525810add5804059001b1b319d6ad1/wandb/sdk/data_types/image.py#L488-L511) diff --git a/content/ko/guides/integrations/pytorch.md b/content/ko/guides/integrations/pytorch.md index 403e106a1a..d4e107d6ea 100644 --- a/content/ko/guides/integrations/pytorch.md +++ b/content/ko/guides/integrations/pytorch.md @@ -49,7 +49,7 @@ gradient, metrics 및 그래프는 순방향 _및_ 역방향 패스 후에 `wand ## 이미지 및 미디어 로그 -이미지 데이터가 포함된 PyTorch `Tensors`를 [`wandb.Image`]({{< relref path="/ref/python/data-types/image.md" lang="ko" >}})로 전달할 수 있으며, [`torchvision`](https://pytorch.org/vision/stable/index.html)의 유틸리티가 자동으로 이미지를 변환하는 데 사용됩니다. +이미지 데이터가 포함된 PyTorch `Tensors`를 [`wandb.Image`]({{< relref "/ref/python/data-types/image.md" >}})로 전달할 수 있으며, [`torchvision`](https://pytorch.org/vision/stable/index.html)의 유틸리티가 자동으로 이미지를 변환하는 데 사용됩니다. ```python images_t = ... # generate or load images as PyTorch Tensors diff --git a/content/ko/guides/models/track/log/media.md b/content/ko/guides/models/track/log/media.md index 8758e4501a..e9fc560072 100644 --- a/content/ko/guides/models/track/log/media.md +++ b/content/ko/guides/models/track/log/media.md @@ -53,7 +53,7 @@ images = wandb.Image(image_array, caption="Top: Output, Bottom: Input") wandb.log({"examples": images}) ``` -마지막 차원이 1이면 이미지가 회색조, 3이면 RGB, 4이면 RGBA라고 가정합니다. 배열에 float가 포함된 경우 `0`과 `255` 사이의 정수로 변환합니다. 이미지를 다르게 정규화하려면 [`mode`](https://pillow.readthedocs.io/en/stable/handbook/concepts.html#modes)를 수동으로 지정하거나 이 패널의 "PIL 이미지 로깅" 탭에 설명된 대로 [`PIL.Image`](https://pillow.readthedocs.io/en/stable/reference/Image.html)를 제공하면 됩니다. +마지막 차원이 1이면 이미지가 회색조, 3이면 RGB, 4이면 RGBA라고 가정합니다. 배열에 float가 포함된 경우 정규화 알고리즘을 사용하여 자동으로 `0`과 `255` 사이의 정수로 변환합니다. PyTorch 텐서와 NumPy 배열에서 정규화가 어떻게 작동하는지에 대한 자세한 정보는 [Image 참조 문서의 이미지 정규화 섹션]({{< relref "/ref/python/data-types/image.md#image-normalization" >}})을 참조하세요. 이미지를 다르게 정규화하려면 [`mode`](https://pillow.readthedocs.io/en/stable/handbook/concepts.html#modes)를 수동으로 지정하거나 이 패널의 "PIL 이미지 로깅" 탭에 설명된 대로 [`PIL.Image`](https://pillow.readthedocs.io/en/stable/reference/Image.html)를 제공하면 됩니다. {{% /tab %}} {{% tab header="PIL 이미지 로깅" %}} 배열을 이미지로 변환하는 것을 완벽하게 제어하려면 [`PIL.Image`](https://pillow.readthedocs.io/en/stable/reference/Image.html)를 직접 구성하여 제공합니다. @@ -557,7 +557,7 @@ run이 완료되면 UI에서 분자의 3D 시각화와 상호 작용할 수 있 ### PNG 이미지 -[`wandb.Image`]({{< relref path="/ref/python/data-types/image.md" lang="ko" >}})는 `numpy` 배열 또는 `PILImage` 인스턴스를 기본적으로 PNG로 변환합니다. +`wandb.Image`는 `numpy` 배열 또는 `PILImage` 인스턴스를 기본적으로 PNG로 변환합니다. ```python wandb.log({"example": wandb.Image(...)}) @@ -577,7 +577,7 @@ wandb.log({"example": wandb.Video("myvideo.mp4")}) ## 분자의 2D 보기 -[`wandb.Image`]({{< relref path="/ref/python/data-types/image.md" lang="ko" >}}) 데이터 유형과 [`rdkit`](https://www.rdkit.org/docs/index.html)을 사용하여 분자의 2D 보기를 기록할 수 있습니다. +[`wandb.Image`]({{< relref "/ref/python/data-types/image.md" >}}) 데이터 유형과 [`rdkit`](https://www.rdkit.org/docs/index.html)을 사용하여 분자의 2D 보기를 기록할 수 있습니다. ```python molecule = rdkit.Chem.MolFromSmiles("CC(=O)O") diff --git a/content/ko/launch/integration-guides/dagster.md b/content/ko/launch/integration-guides/dagster.md index 036d57afb2..a22daa7844 100644 --- a/content/ko/launch/integration-guides/dagster.md +++ b/content/ko/launch/integration-guides/dagster.md @@ -182,7 +182,7 @@ def create_dataset(): W&B는 여러 Pickle 기반 직렬화 모듈을 지원합니다 ([pickle](https://docs.python.org/3/library/pickle.html), [dill](https://github.com/uqfoundation/dill), [cloudpickle](https://github.com/cloudpipe/cloudpickle), [joblib](https://github.com/joblib/joblib)). [ONNX](https://onnx.ai/) 또는 [PMML](https://en.wikipedia.org/wiki/Predictive_Model_Markup_Language)과 같은 고급 직렬화를 사용할 수도 있습니다. 자세한 내용은 [직렬화]({{< relref path="#serialization-configuration" lang="ko" >}}) 섹션을 참조하십시오. {{% /tab %}} {{% tab "W&B Object" %}} -모든 기본 W&B 오브젝트 (예: [Table]({{< relref path="/ref/python/data-types/table.md" lang="ko" >}}), [Image]({{< relref path="/ref/python/data-types/image.md" lang="ko" >}}) 또는 [Graph]({{< relref path="/ref/python/data-types/graph.md" lang="ko" >}}))가 통합에서 생성된 Artifact에 추가됩니다. 다음은 Table을 사용하는 예입니다. +모든 기본 W&B 오브젝트 (예: [Table]({{< relref path="/ref/python/data-types/table.md" lang="ko" >}}), [Image]({{< relref "/ref/python/data-types/image.md" >}}) 또는 [Graph]({{< relref path="/ref/python/data-types/graph.md" lang="ko" >}}))가 통합에서 생성된 Artifact에 추가됩니다. 다음은 Table을 사용하는 예입니다. ```python import wandb diff --git a/content/ko/ref/python/data-types/image.md b/content/ko/ref/python/data-types/image.md index 5d2b7e576e..74061550c3 100644 --- a/content/ko/ref/python/data-types/image.md +++ b/content/ko/ref/python/data-types/image.md @@ -30,9 +30,107 @@ Image( 참고 : `torch.Tensor`를 `wandb.Image`로 로깅할 때 이미지는 정규화됩니다. 이미지를 정규화하지 않으려면 텐서를 PIL Image로 변환하십시오. -#### 예시: +이미지 정규화 -### numpy array에서 wandb.Image 생성 +PyTorch 텐서나 NumPy 배열을 `wandb.Image`에 전달하면 `normalize=False`를 설정하지 않는 한 픽셀 값이 자동으로 [0, 255] 범위로 정규화됩니다. 이 정규화는 일반적인 이미지 데이터 형식을 처리하고 적절한 표시를 보장하기 위해 설계되었습니다. + +정규화가 적용되는 경우 + +정규화는 다음에 적용됩니다: +- **PyTorch 텐서** (형식: `(channel, height, width)`) +- **NumPy 배열** (형식: `(height, width, channel)`) + +정규화는 다음에 적용되지 않습니다: +- **PIL 이미지** (그대로 전달됨) +- **파일 경로** (그대로 로드됨) + +정규화 알고리즘 + +정규화 알고리즘은 입력 범위를 자동으로 감지하고 적절한 변환을 적용합니다: + +1. **데이터가 [0, 1] 범위에 있는 경우**: 값에 255를 곱하고 uint8로 변환 + ```python + normalized_data = (data * 255).astype(np.uint8) + ``` + +2. **데이터가 [-1, 1] 범위에 있는 경우**: 다음 공식으로 [0, 255]에 리스케일 + ```python + normalized_data = (255 * 0.5 * (data + 1)).astype(np.uint8) + ``` + +3. **기타 범위의 경우**: 값을 [0, 255]로 클립하고 uint8로 변환 + ```python + normalized_data = data.clip(0, 255).astype(np.uint8) + ``` + +정규화 효과 예시 + +**예시 1: [0, 1] 범위 데이터** +```python +import torch +import wandb + +# [0, 1] 범위의 값을 가진 텐서 생성 +tensor_0_1 = torch.rand(3, 64, 64) # 0에서 1 사이의 랜덤 값 + +# 모든 값에 255를 곱함 +image = wandb.Image(tensor_0_1, caption="[0,1] 범위에서 정규화") +``` + +**예시 2: [-1, 1] 범위 데이터** +```python +import torch +import wandb + +# [-1, 1] 범위의 값을 가진 텐서 생성 +tensor_neg1_1 = torch.rand(3, 64, 64) * 2 - 1 # -1에서 1 사이의 랜덤 값 + +# 리스케일: -1 → 0, 0 → 127.5, 1 → 255 +image = wandb.Image(tensor_neg1_1, caption="[-1,1] 범위에서 정규화") +``` + +**예시 3: PIL 이미지로 정규화 회피** +```python +import torch +from PIL import Image as PILImage +import wandb + +# [0, 1] 범위의 값을 가진 텐서 생성 +tensor_0_1 = torch.rand(3, 64, 64) + +# PIL 이미지로 변환하여 정규화 회피 +pil_image = PILImage.fromarray((tensor_0_1.permute(1, 2, 0).numpy() * 255).astype('uint8')) +image = wandb.Image(pil_image, caption="정규화가 적용되지 않음") +``` + +**예시 4: normalize=False 사용** +```python +import torch +import wandb + +# [0, 1] 범위의 값을 가진 텐서 생성 +tensor_0_1 = torch.rand(3, 64, 64) + +# 정규화 비활성화 - 값은 [0, 255]로 클립됨 +image = wandb.Image(tensor_0_1, normalize=False, caption="정규화 비활성화") +``` + +모범 사례 + +1. **일관된 결과를 위해**: 로깅하기 전에 데이터를 예상되는 [0, 255] 범위로 전처리 +2. **정규화를 회피하기 위해**: `PILImage.fromarray()`를 사용하여 텐서를 PIL 이미지로 변환 +3. **디버깅을 위해**: `normalize=False`를 사용하여 원시 값 확인 ([0, 255]로 클립됨) +4. **정밀한 제어를 위해**: 정확한 픽셀 값이 필요한 경우 PIL 이미지 사용 + +일반적인 함정 + +- **예상치 못한 밝기**: 텐서 값이 [0, 1] 범위에 있으면 255배되어 이미지가 매우 밝아짐 +- **데이터 손실**: [0, 255] 범위를 벗어나는 값은 클립되어 정보가 손실될 수 있음 +- **일관성 없는 동작**: 다른 입력 유형(텐서 vs PIL vs 파일 경로)에서 다른 결과가 나올 수 있음 + +예시: + +numpy array에서 wandb.Image 생성 ```python import numpy as np @@ -47,7 +145,7 @@ with wandb.init() as run: run.log({"examples": examples}) ``` -### PILImage에서 wandb.Image 생성 +PILImage에서 wandb.Image 생성 ```python import numpy as np @@ -66,7 +164,7 @@ with wandb.init() as run: run.log({"examples": examples}) ``` -### .png (기본값) 대신 .jpg 로깅 +.png (기본값) 대신 .jpg 로깅 ```python import numpy as np @@ -84,9 +182,9 @@ with wandb.init() as run: | 속성 | | | :--- | :--- | -## Methods +Methods -### `all_boxes` +`all_boxes` [View source](https://www.github.com/wandb/wandb/tree/637bddf198525810add5804059001b1b319d6ad1/wandb/sdk/data_types/image.py#L610-L631) @@ -100,7 +198,7 @@ all_boxes( ) -> Union[List[Optional[dict]], bool] ``` -### `all_captions` +`all_captions` [View source](https://www.github.com/wandb/wandb/tree/637bddf198525810add5804059001b1b319d6ad1/wandb/sdk/data_types/image.py#L633-L637) @@ -111,7 +209,7 @@ all_captions( ) -> Union[bool, Sequence[Optional[str]]] ``` -### `all_masks` +`all_masks` [View source](https://www.github.com/wandb/wandb/tree/637bddf198525810add5804059001b1b319d6ad1/wandb/sdk/data_types/image.py#L587-L608) @@ -125,7 +223,7 @@ all_masks( ) -> Union[List[Optional[dict]], bool] ``` -### `guess_mode` +`guess_mode` [View source](https://www.github.com/wandb/wandb/tree/637bddf198525810add5804059001b1b319d6ad1/wandb/sdk/data_types/image.py#L474-L486) @@ -137,7 +235,7 @@ guess_mode( np.array가 나타내는 이미지 유형을 추측합니다. -### `to_uint8` +`to_uint8` [View source](https://www.github.com/wandb/wandb/tree/637bddf198525810add5804059001b1b319d6ad1/wandb/sdk/data_types/image.py#L488-L511)