Pythonで画像処理をした話

アイキャッチ画像

はじめに

自分が画像処理を本格的に触り始めたのは、半導体検査装置メーカーへ常駐していた頃でした。

装置が撮影した画像を解析し、欠陥の有無を判断するアルゴリズムを作るのが主な業務でしたが、最初はとにかく「画像処理って難しい」という印象が強かったのを覚えています。 

Python と OpenCV を使えば画像処理は簡単にできる。

そう思っていたのですが、実際の現場では想像以上に落とし穴が多く、基礎を理解していないと正しく処理できない場面が何度もありました。

特に半導体検査装置の画像は 白黒(グレースケール) が基本で、

一般的なカラー画像処理とは違うポイントでつまずくことが多かったのです。

最初に作ったのは「エッジ検出ツール」

画像処理の基本として最初に取り組んだのが エッジ検出 でした。

製品の輪郭や欠陥の境界を抽出するために、Sobel や Laplacian フィルタを使いました。  

ただ実務で扱う半導体検査装置の画像はノイズが多く、そのままエッジ検出を行うと 微細なノイズまで反応してしまう という問題がありました。 

そこで、前処理としてGaussianフィルタを入れることでエッジ検出の安定性が大きく向上しました。 

  • Gaussianフィルタで画像を滑らかに

import cv2

img = cv2.imread(“image.png”, 0)

blur = cv2.GaussianBlur(img, (3, 3), 0)

ガウシアンフィルタは、画像の細かいノイズを滑らかにし輪郭情報は残してくれるため、エッジ検出の前処理として最適です。 

実務では「ガウシアン → エッジ検出」はほぼ必須の流れでした。 

  • Sobelフィルタで輪郭抽出

import cv2

img = cv2.imread(“image.png”, 0)

sobel = cv2.Sobel(img, cv2.CV_64F, 1, 0)

Sobelは縦・横のエッジを検出できるため、

「どこに境界があるか」を把握するのに役立ちました。

  • Laplacianで細かい部分を検出

lap = cv2.Laplacian(img, cv2.CV_64F)

微細な傷や天井の欠陥はLaplacianが見つけやすく、

装置の精度向上には必須の処理となっていました。

画像処理で最初の落とし穴

半導体検査装置で扱う画像は、基本的に 白黒(グレースケール) です。

そのため、一般的なカラー画像処理とは違うポイントでつまずくことが多く、自分も最初は何度も苦労しました。 

  • 白黒画像なのに「RGB前提」で処理してしまう 

OpenCV の cv2.imread() は、引数によって読み込みモードが変わります。 

しかし、初心者の頃の自分はこれを知らずデフォルト(カラー)で読み込んでしまい、3チャンネル画像として扱っていたことがありました。 

最初に必ずグレースケールで読み込む必要があります。 

  • 画像のビット深度(8bit / 10bit)を見落とす 

半導検査装置の画像は、一般的な 8bit ではなく 10bit などの高ビット深度で出力されることがあります。 

[起きる問題]

・画素値が 0〜1023(10bit)なのに、8bit前提で処理してしまう

・閾値が合わず、欠陥が検出できない 

・正規化していないため、フィルタの結果が不安定になる

[解決策]

・8bitに正規化する処理を入れる。

ビット深度を正しく扱うだけで、欠陥検出の精度が大きく改善しました。 

  • 画像が巨大でメモリ不足になる

半導体検査装置の画像は高解像度で、白黒でも数千×数千ピクセルになることがあります。

そのまま NumPy 配列にするとメモリを大量に消費し、処理が途中で落ちることもありました。 

そこで活躍したのが ROI(Region of Interest) です。

ROIで必要な領域を切り出すことで、

・メモリの使用量の現象

・処理速度の向上

などといったメリットが得られました。

まとめ

Python で画像処理を学び始めた頃は、白黒画像の扱い方やビット深度の違いや前処理の重要性など、基礎的な部分で何度もつまずきました。 

しかし、これらの基礎をひとつずつ理解していくことで、

「画像がどう記録されているのか」「画素値がどう変化するのか」

といった根本的な仕組みが見えるようになりました。

この“基礎の理解”が、後の新規アルゴリズム開発に大きく役立ちました。

結果として、 新しい欠陥検出アルゴリズムの設計や改善提案を自分から行えるようになり、 現場の検査精度向上に直接貢献することができました。