21
15

More than 3 years have passed since last update.

間違い探しを秒で解いてくれるプログラムを作ってみた

Last updated at Posted at 2019-12-13

富士通システムズウェブテクノロジー Advent Calendar 2019 16日目の投稿です。
記事の内容は全て個人の見解であり、執筆内容は執筆者自身の責任です。所属する組織は関係ありません。

はじめに

16日目の今回は、サイゼリア サイゼリヤ の間違い探しを自力でクリアしたことがないでお馴染みの私が

二枚の画像から差分をとって相違点をぱっとみでわかりやすく表示できるプログラム

を作る方法を、拙筆ながら書かせていただきたいと思いますまる

おおまかなイメージ図

スクリーンショット 2019-12-13 21.04.06.png
スクリーンショット 2019-12-13 21.04.16.png

実装環境

  • OS
    • MacOS Mojave10.14.5
  • 言語
    • python 3.7.4
  • ライブラリ
    • openCV 3.4.2
    • NumPy 1.17.4
    • matplotlib 3.1.1
  • その他
    • jupyter notebook 6.0.1
    • anaconda navigator

事前準備

(なんの保証もないですがpythonと各種ライブラリが使えれば普通に動作すると思うので流し見程度でお願いします)

  • anaconda navigatorとかいうguiでわかりやすくanacondaを扱えるツールを入れます。
  • 並行して(別に並行してなくてもいい)pythonのインストールとかもしとけばいいとおもいます。
  • anaconda navigator使ってjupyterとか各種ライブラリとかをよしなに入れます。

(詳しい導入方法は 'anaconda navigator jupyter インストール'とかでぐぐれば色々出てくると思います。)

ソース解説

ではここからが本番、ソースの内容についてです。

パーツとしては大きく分けて3つ

  • 差分のマスク画像を作成
  • マスク画像のマスク部に色をのせる
  • マスク画像の透過度を変更し、合成する

といった感じになりマウス

importとか変数設定とか


import cv2, matplotlib
import numpy as np
from IPython.display import Image, display_png

# 元画像1
img_01 = "sample1.png"
# 元画像2
img_02 = "sample2.png"
# 出力後の画像につけたい名前を入力してください
outImg = "output.png"

差分のマスク画像を作成


# 元画像1をカラーで読み込み
img_src01 = cv2.imread(img_01, 1)

# 元画像2をカラーで読み込み
img_src02 = cv2.imread(img_02, 1)

# 混合正規分布(Gaussian Mixture)を基にした前景・背景の領域分割アルゴリズムらしいです。
bg = cv2.bgsegm.createBackgroundSubtractorMOG()

# マスク画像を生成
mask = bg.apply(img_src01)
mask = bg.apply(img_src02)

# マスク画像を出力
cv2.imwrite("output/machigai_mask.png", mask)

print("元画像1")
display_png(Image(img_01))
print("元画像2")
display_png(Image(img_02))
print("マスク画像")
display_png(Image("output/machigai_mask.png"))

ここでの出力結果は以下のようになりました。
スクリーンショット 2019-12-13 22.21.20.png

マスク画像のマスク部に色をのせる


mask_img = cv2.imread("output/machigai_mask.png", 1)

# 画像の白い部分を赤に置き換える
red = [240, 20, 20]
white = [255, 255, 255]
mask_img[np.where((mask_img == white).all(axis=2))] = red

# BGR to RGB
mask_img = cv2.cvtColor(mask_img, cv2.COLOR_BGR2RGB)

# 結果を保存する。
cv2.imwrite("output/color_mask_img.png", mask_img)

color_mask_img = cv2.imread("output/color_mask_img.png", 1)
display_png(Image("output/color_mask_img.png"))

ここでの出力結果は以下のように。
スクリーンショット 2019-12-14 0.05.36.png

マスク画像の透過度を変更し、合成する

最後にこれができれば完成ですね。


# src1 = 元画像1、src2 = マスク画像、alpha(beta) = あわせて1になるくらいの比率で調整するのが良さそう、gamma = 0だといい感じになった
diff_image = cv2.addWeighted(src1=img_src01,alpha=0.3,src2=color_mask_img,beta=0.7,gamma=0)
cv2.imwrite(outImg, diff_image)

display_png(Image(outImg))

はい、完成です
スクリーンショット 2019-12-14 0.11.25.png

間違い探しっぽい画像でやってみた

このために間違い探し作ってみました。
まずはご自身の力でやってみてください(間違いは6箇所あります)

machigai_1_2.png
  
  
  
  
  
  
  
  
  
  
  
  
  

さあ、間違いを探し出すことはできたでしょうか。

続いては全自動卵割り機間違い探し機に解いてもらった結果をご覧入れましょう

  
  
  
こちらです
diff_image (1).png

どうでしょう。
すごい正答率ですね。

ただまぁ先生のかつらがスイカに変わっていたことの検出精度はあまりよくないですね。

背景差分法について

そもそもこの背景差分法というものなんですが、
動画像上での移動物を検出するための方法なのでございます。

要するに

定点カメラで
あー人が通りましたねー
みたいなのを判定する方法なんです

この背景差分の方法、間違い探しに使うとなると大きな問題点が2つございます

  • 差分を取る画像のサイズが同じでないといけない
  • ちょっとでも画素がずれてると全部違う判定される

なので、汎用的に使えるものを作ろうとすると、

  • ちょっとのズレは補正してくれて
  • あと、傾きも補正してくれて
  • 大きさも補正してくれて
  • けど認識精度はある程度保証できる

そんなソフトを作らなきゃいけない気がしてきますね()

最後に

  • ちょっとのズレは補正してくれて
  • あと、傾きも補正してくれて
  • 大きさも補正してくれて
  • けど認識精度はある程度保証できる

そんなソフトを、次は頑張って作ってみようかな(白目)

参考

21
15
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
21
15