1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

10bit・12bitグレースケール画像の扱い方 ~保存・表示・処理でつまずかないために~

Last updated at Posted at 2025-04-20

1. はじめに

最近のマシンビジョンカメラでは、10bitや12bitのグレースケール画像出力に対応する製品が増えてきました。
これは微細な濃淡の変化を捉えたり、高ダイナミックレンジ(HDR)画像処理に対応するために有効です。

しかし、10bit/12bit画像には3つの大きな落とし穴があります:

  1. 画像が正しく表示できない
  2. 適切な保存や読込ができない
  3. 画像処理ライブラリが対応していない

この記事では、これらの問題に対する実践的な解決策を、Python + OpenCV環境を中心に紹介します。


2. なぜ10bit/12bit画像は扱いが難しいのか?

通常の8bitグレースケール画像(0〜255)に比べ、
10bit画像は 0〜1023、12bit画像は 0〜4095 というより広い階調を持ちます。

このため、従来の8bit前提のソフトウェアでは、正しく表示・保存・処理ができないという問題が発生します。


3. 表示:OpenCVで10bit/12bit画像を明るく表示するには?

❌ 問題点:そのまま表示すると「真っ暗」に見える

OpenCVのcv2.imshow()で16bit画像を表示すると、ダイナミックレンジが0〜65535として扱われます。
そのため、10bit(最大1023)や12bit(最大4095)画像は、非常に暗く表示されてしまいます。

(10bitグレースケール画像の表示例)
2025-04-20_22h15_24.png

✅ 対処法:ビットシフトで8bitに変換

import cv2
import numpy as np

img_16bit = cv2.imread("image_10bit.tiff", cv2.IMREAD_UNCHANGED)  # dtype=uint16
img_8bit = (img_16bit >> 2).astype(np.uint8)  # 10bit → 8bit(右に2bitシフト)

cv2.imshow("10bit image (converted)", img_8bit)
cv2.waitKey(0)
cv2.destroyAllWindows()

📌 10bit画像 → 2bitシフト
📌 12bit画像 → 4bitシフト

(10bitグレースケール画像を2bitシフトした画像表示)
2025-04-20_22h15_53.png

これは表示専用の変換です。元のbit深度のまま処理したい場合は、uint16のまま扱います。


4. 保存・読込:10bit/12bit画像は保存できない? → TIFFを使う

❌ 問題点:そもそも対応していないフォーマットが多い。

  • Bitmap(*.bmp)ファイルでBitfieldを使って10bit/12bitとして保存することもできますが、画像を開くアプリが対応していないことが多い。
  • 保存時に自動で他bitに変換されることがあります。(ライブラリ、アプリ依存です。)

✅ 対処法:TIFF形式で保存(MinSampleValue/MaxSampleValueタグ付き)

TIFF形式は柔軟性が高く、以下のようなタグで階調情報を保持できます:

  • BitsPerSample = 16
  • MinSampleValue = 0
  • MaxSampleValue = 1023 or 4095

🧪 保存例:tifffileで10bit TIFF保存

import tifffile
import numpy as np

width = 1024
height = 256
gradient_line = np.linspace(0, 1023, width, dtype=np.uint16)
img_10bit = np.tile(gradient_line, (height, 1))

tifffile.imwrite(
    "output_10bit.tiff",
    img_10bit,
    metadata={"MinSampleValue": 0, "MaxSampleValue": 1023},
)

ほとんどの画像表示ソフトではMinSampleValue/MaxSampleValueタグを無視します。
画像解析ソフトをして有名なImageJでは、初期設定で、最小輝度値を、最大輝度値をとなるように明るさが調整され表示されます。


📥 読込例:TIFF画像の読込と確認

import tifffile
import cv2
import numpy as np

# 読込
img = tifffile.imread("output_10bit.tiff")  # dtype=np.uint16

# 情報確認
print("dtype:", img.dtype)
print("shape:", img.shape)

# 表示用に8bit変換
img_8bit = (img >> 2).astype(np.uint8)
cv2.imshow("TIFF 10bit image (converted)", img_8bit)
cv2.waitKey(0)
cv2.destroyAllWindows()

5. 処理:OpenCVなどのライブラリで対応できる?

❌ 問題点:多くの関数は8bit専用

以下のOpenCV関数は、uint16には非対応です:

関数名 対応bit深度
cv2.Canny() uint8 のみ
cv2.equalizeHist() uint8 のみ
cv2.findContours() uint8 のみ

✅ 対処法:処理前に一時的に8bitへ変換する

# 10bit画像(uint16)→ 8bit に変換して処理
img_8bit = (img_16bit >> 2).astype(np.uint8)
edges = cv2.Canny(img_8bit, 50, 150)

6. おわりに

10bitや12bitグレースケール画像は、高精細な画像処理を実現する強力な手段です。
しかし、次のような落とし穴に注意が必要です:

課題 対処方法
表示が真っ暗になる → ビットシフトして8bitに変換
保存ができない → TIFF形式+タグ付きで保存
処理できない関数が多い → 処理前に一時的に8bit変換 or ライブラリ選定 or 自作
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?