#概要
実験などで,オシロスコープの波形を保存し,レポートに貼り付けるなんてことがあったのですが,
オシロスコープの波形は黒ベースの画像なので,そのまま貼り付けると,見づらいかつ,大量のインクを使ってしまうため,
あるアプリケーションで色を反転してから,レポートに貼っていました.
しかし,1枚1枚色を反転してというのは非常にめんどくさい!
ということで,画像のネガポジ反転をPythonを使って自動化してみました!
#動作環境
- Windows10(64bit)
- Python 3.7.2
- OpenCV 4.1.0
#やりたいこと
上の画像を下の画像のようにするのが目標です.
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
#どのようにしてネガポジ反転を行うのか
OpenCVにあるbitwise_not()関数を使ってあげれば,ネガポジ反転した画像を得られます.非常に簡単ですね.
bitwiseとはビット単位という意味です.それをnotすることで反転するというイメージでしょうか?
もしくは,関数を使わなくても,以下の1行でもできます.numpy恐ろしやですね.
計算時間も%timeitコマンドで調べてみましたが,数枚程度の画像であればそれほど変わりません.
img2 = 255 - img
#ネガポジ反転させる関数の定義
では,ネガポジ反転させる関数を定義します.これがこのプログラムの核となる部分です.
# 画像のネガポジ反転をする関数
def negaposi(image):
# 画像の読み込み
img = cv2.imread(image)
# ネガポジ反転
img2 = cv2.bitwise_not(img)
return img, img2
#コードの解説
では解説をしていきます.
- 画像の読み込み
まずは,画像を読み込ませます.
img = cv2.imread(image)
- ネガポジ反転
次に,先ほど説明したbitwise_not()関数を用いて,ネガポジ反転をさせます.
img2 = cv2.bitwise_not(img)
あとはこの関数の返り値に対して,画像を表示したり保存したりすれば,所望の画像を保存することができます.
#複数の画像に対して一気にネガポジ反転を行う
では複数の画像に対して,一気にネガポジ反転をやってみようと思います.
ネガポジ反転させたい画像がimages_for_negaposiディレクトリにあり,拡張子は.bmpであるとします.
そして保存先のディレクトリはnegaposi_imagesとします.
INPUTDIR = 'images_for_negaposi'
OUTPUTDIR = 'negaposi_images'
EXT = 'bmp'
# 編集後の画像の保存ディレクトリの作成
if not os.path.isdir(OUTPUTDIR):
os.mkdir(OUTPUTDIR)
# ORIGINALFILE内の全ての画像に対してループ
for image in glob.glob(INPUTDIR + '/*.' + EXT):
img, img2 = negaposi(image)
# cv2.imshow('unedited', img) # 編集前の画像
# 相対パスの部分を削除
image = image[len(INPUTDIR) + 1:]
# ネガポジ反転した画像を表示
cv2.imshow(image, img2)
# cv2.moveWindow('unedited', 400, 0)
# cv2.moveWindow(image, 0, 0) # 画像表示の位置変更
cv2.waitKey(0) # 何らかのキーが押されるまで待機
cv2.destroyAllWindows() # 全てのウィンドウを削除
# 画像を保存
cv2.imwrite(OUTPUTDIR + '/' + image, img2) # 画像の保存
#コードの解説
それでは,コードの解説をしていきます.
- 保存用ディレクトリの作成
保存先のディレクトリを作成します.同名のファイルがあるとエラーが出てしまうので,isdir()関数で,引数名のディレクトリがあるか否かを確認し,なければmkdir()関数で作成します.
if not os.path.isdir(OUTPUTDIR):
os.mkdir(OUTPUTDIR)
- ループ
INPUTDIR内の全ての画像に対して,ループします.
glob.glob()は引数パターンにマッチするファイルリストの作成を行います.
ここで,*はいわゆるワイルドカードです.
EXTは拡張子extensionの略です。
for image in glob.glob(INPUTDIR + '/*.' + EXT):
- 相対パスの部分を削除
glob.glob()関数は,パターンにマッチしたファイルを相対パスの形で返すので,相対パスの部分を削除することで,
元のファイルと同じ名前で,ネガポジ反転後のファイルを保存できます.
具体的に説明すると,今の場合には,imageはimages_for_negaposi/*.bmpなので,最初のimages_for_negaposi/の部分をスライスによって削除します.
[start:]はstratオフセットから末尾までのシーケンスを抽出します.ちなみにオフセットはゼロから始まります.
image = image[len(INPUTDIR) + 1:]
- 画像の表示
1行目で画像を表示します.これだけだと,すぐにウィンドウが消えてしまうので,
waitKey(0)で何らかのキーが入力されるまで,ここで待機します.
何らかのキーが押されたら,プログラムを再開し,destroyAllWindows()で全てのウインドウを削除します.
コメントアウトの部分は,ネガポジ反転前の画像も表示したいときに使います.
そのままimshow()だけだと,ウインドウが重なってしまうことがあるため,moveWindow()でウインドウを移動させます.
cv2.imshow(image, img2)
# cv2.moveWindow('unedited', 400, 0)
# cv2.moveWindow(image, 0, 0) # 画像表示の位置変更
cv2.waitKey(0) # 何らかのキーが押されるまで待機
cv2.destroyAllWindows() # 全てのウィンドウを削除
- 画像の保存
最後に画像を保存します.ここでも保存先はもちろん相対パスで指定します.
cv2.imwrite(OUTPUTDIR + '/' + image, img2) # 画像の保存
#まとめ
いかがだったでしょうか?今回はOpenCVを使って画像をネガポジ反転させる方法を説明しました.
これを使えばとても効率的ですね.ぜひ,活用してみてください.
また,プログラムに関する建設的なフィードバックもお待ちしています!