Pythonで写真の中の線を抽出してみた
Pythonでグレースケールの写真に書き込まれた線を抽出してみました。イメージとしては、X線写真の後処理で書き込まれた線を取り出してみるという感じです。
目次
サンプル
グレースケールの写真に各色で書き込まれた線があります。
この写真から、各色で描かれた線を取り出してみます。
線を取り出す手順
白色以外の色の部分
まず、HSV形式に色形式を変換します。S成分(彩度)がどのように分布しているか見てみると、このようになります。
グレースケールの箇所は彩度が低く、色が付いているところだけが彩度が高くなっていることがわかりますね。この彩度の分布画像を2値化して、マスクとして使います。
白色部分
まず、グレースケールに変換します。
そして、閾値を高めに設定して2値化をします。これが白色部分のマスクになります。
マスクを使って色抽出をする
2つのマスクを合成します。
この合成したマスクを元画像に適用します。マスクを画像に適用すると、マスクの画素の色が0の部分(上記マスク画像で黒色の部分)だけが黒色に塗りつぶされます。その結果、色の付いた線の部部だけが残って表示されるのです。
元画像がJPEGだったりすると、JPEG特有のブロックノイズの影響で線の輪郭がうまく出ない場合があります。画像処理ソフトからの出力は、できればBMPかPNGが良いです。
プログラム
上記の処理をプログラムにすると下記のようになります。OpenCVを使いますので、予めPythonのOpenCVモジュールをインストールしておいてください。
import cv2
im = cv2.imread('sample.png', cv2.IMREAD_COLOR)
# 彩度によるマスクを生成する
# BGRからHSVへ変換する
im_hsv = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
# S成分を抜き出す
im_h, im_s, im_v = cv2.split(im_hsv)
# S成分を2値化する
r_, im_s_mask = cv2.threshold(im_s, 200, 255, cv2.THRESH_BINARY)
# 白色部分のマスクを生成する
im_gr = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
r_, im_w_mask = cv2.threshold(im_gr, 253, 255, cv2.THRESH_BINARY)
# マスクを合成する
im_mask = cv2.bitwise_or(im_s_mask, im_w_mask)
# マスクを画像に適用する
im_m = cv2.bitwise_and(im, im, mask=im_mask)
cv2.imwrite('out.jpg', im_m)
背景を白色にする
背景が黒色では利用しにくい場合もありますので、背景を白色にしてみます。また、白色の線の部分は黒色に変換します。
import numpy as np
import cv2
im = cv2.imread('sample.png', cv2.IMREAD_COLOR)
# 彩度によるマスクを生成する
# BGRからHSVへ変換する
im_hsv = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
# S成分を抜き出す
im_h, im_s, im_v = cv2.split(im_hsv)
# S成分を2値化する
r_, im_s_mask = cv2.threshold(im_s, 200, 255, cv2.THRESH_BINARY)
# 白色部分のマスクを生成する
im_gr = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
r_, im_w_mask = cv2.threshold(im_gr, 253, 255, cv2.THRESH_BINARY)
# マスクを画像に適用する
im[im_s_mask==0] = [255,255,255]
im[im_w_mask==255] = [0,0,0]
cv2.imwrite('out.jpg', im)
白色部分と白色以外の部分を分けて元画像に適用するので、マスクの合成は不要になります。
元画像へのマスクの適用の仕方が最初のプログラムと異なっています。こちらは、NumPyを使用した例です。
[255,255,255]の部分を変更すれば、好きな背景色に変更できます。
このプログラムの出力はこうなります。
公開日
広告
作ってみたカテゴリの投稿
- PythonでFizzBuzz問題をやってみた
- PythonでPDFファイルのサムネイル画像を作る
- Pythonでオブジェクトを選択してクロップするツールを作ってみた
- Pythonでデータロガーのログから瞬断を抽出してみる
- Pythonで写真の中の線を抽出してみた
- Pythonで動画から静止部分を抜き出してみた
- Pythonで測定データのピーク値を検出してみる
- Pythonで複数のCSVデータを1つのファイルにまとめてみた
- PythonとExcelでフォルダの使用量を調べてみた
- Sphinx(ablog)の後処理をする
- WordPressのブログを静的サイトに書き換えてみました
- シェルスクリプトでSphinxのビルドの前処理をする
- 数式を中置記法から後置記法(逆ポーランド記法)に変換してみた