!!! サイト改修中のため表示が乱れる場合があります(1月末頃まで) !!!
画像処理

14-13. 光の回折を使って「この中に一つだけ違う文字があります」を解く

やること

正式名称は分かりませんが「この中に一つだけ違う文字があります」という間違い探しがあります。例えばこういうものです↓

予備

こちらのサイトにもたくさんの問題があります。

https://matome.naver.jp/odai/2139636176432242601

このような間違い探しを見るたびに「X線結晶構造解析で解けないかな」と考えています。今回は光の回折の原理を応用して「この中に一つだけ違う文字があります」を解いてみます

実行環境

WinPython3.6をおすすめしています。

WinPython - Browse /WinPython_3.6/3.6.7.0 at SourceForge.net
Portable Scientific Python 2/3 32/64bit Distribution for Windows

Google Colaboratoryが利用可能です。

Google Colab

問題1

自作の問題です。「あ」の中に違うひらがなを混ぜました。「何が」「何個」隠れているのかも問題に含まれますので、ヒントなしの上級問題と言えます。

光の回折とX線結晶構造解析

光の回折については、ヤングの二重スリット実験で学んだ通りです。

ヤングの実験 - Wikipedia

光には物の後ろに回り込むように進む「回析」という現象がある。光は波の性質を持つため、回折光も波のように位相を持つ。規則的に並んでいる物体に光を当てると、その後ろに規則的な回折光が生じ、それらは位相により部分的に強め合ったり弱め合ったりする(=干渉する)ことで規則的な模様を生じる。これを回折像と呼ぶ。

この原理を用いて物質の結晶構造を解析するのが「X線結晶構造解析」です。

X線回折 - Wikipedia

考え方

「この中に一つだけ違う文字があります」の間違い探しでは規則的に文字が並んでいます。規則的に並んでいる文字に光を当てると、規則的な回折像ができると思います。しかし、一つだけ違う文字があった場合、その近くの回折像が乱れることが予想されます。

この回折像の乱れを見て、隠れている文字の場所を特定しようという発想です。

import、パラメータ

必要なパッケージをインポートします。足りないと怒られたらpip installしてください。

import cv2
import numpy as np
from scipy import signal
import matplotlib.pyplot as plt

#============================
# 設定
#============================

#画像パス
img_path = '14-13_1.jpg'

#波を作る半径
r_set = [0, 2, 4, 6, 8, 10]

#波の高さ
wave_set = [+1, -0.8, +0.6, -0.4, +0.2] # 半径の間の数だけ

表示関数、準備

画像をグレースケールで表示する関数、波紋フィルターを表示する関数を用意します。

#============================
# 表示関数
#============================
def show(img, n=0):
    plt.figure(figsize=(15, 15))
    plt.imshow(img, cmap='gray')
    plt.title(n)
    plt.show()
    plt.close()
    print()

def show_filter(img):
    plt.figure(figsize=(10, 10))
    plt.imshow(img, vmin = -1, vmax = 1, cmap='bwr')
    plt.show()
    plt.close()
    print()

#============================
# 準備
#============================
#パラメータ表示
print('r_set:\n{}'.format(r_set))
print('wave_set:\n{}'.format(wave_set))

#波紋フィルターの作成
r_max = r_set[-1]
f = np.zeros((r_max*2 - 1, r_max*2 - 1))
for i in range(len(f)):
    for j in range(len(f[0])):
        #注目するピクセルから中心までの距離
        r = ((i + 1 - r_max)**2 + (j + 1 - r_max)**2)**0.5
        #どの範囲に属するか調べて波の高さを更新
        for k in range(len(r_set) - 1):
            if r_set[k] <= r < r_set[k+1]:
                f[i, j] = wave_set[k]
                break
show_filter(f)
r_set:
[0, 2, 4, 6, 8, 10]
wave_set:
[1, -0.8, 0.6, -0.4, 0.2]

波紋フィルターは回折光を表現しています。波の高さは中心から+1.0, -0.8, +0.6, -0.4, +0.2と振動しながら減衰していく感じです。

メイン処理

ビックリするくらい短いです。畳み込みでおなじみの signal.convolve2d() 関数を用いて、画像を1ピクセルずつ波紋フィルターで畳み込んでいきます。畳込み処理で回折像を作り、回折像に対してまた繰り返し回折処理を行います。

#============================
# メイン処理
#============================
#画像を読み込んで、幅500のグレースケールに変換
img = cv2.imread(img_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
show(img, 0)

#画像に繰り返し回折処理を適用
for i in range(1, 40):
    img = signal.convolve2d(img, f, mode='same', boundary='wrap')
    show(img, i)

どうでしょう。歪みが見えたでしょうか?心眼で見てください。4箇所歪んでいるところがあります。

隠れている文字は上から順に「ぬ」「お」「め」「ね」でした。

問題2

冒頭のツイートから問題を拝借しました。

結果

こちらも歪みが検出されました。「6」が隠れていました。

問題3

こちらのサイトから問題を拝借しました。

【集中力】この中に一つだけ9以外の数字があります。(見つけたらRT)
【集中力】この中に一つだけ9以外の数字があります。 あれ!? 9の中に一つだけ別の数字がまぎれてる。 見つけたらリツイート! #見つけたらRT 受験勉強順調ですか? ちょっとリフレッシュしてみましょう

結果

一瞬「どこかな?」と思いましたが、左下にわずかに乱れが生じています。「8」が隠れていました。

まとめ

この手法は文字が規則的にぎっしりと並んでいる場合に有効です。文字の間隔が開いている場合は波紋フィルターを大きくすることで対応できますが、計算時間は2乗に比例して伸びます。また、文字が規則的に並んでいない場合はお手上げです。

しかしながら、「何が」「いくつ」隠れているかがわからなくても使用できるという点では使い所はあると言えるでしょう。長年気になっていた検証ができたので及第とします。

リアクションのお願い

「参考になった!」「刺激された!」と思ったらぜひリアクションをしましょう。エンジニアの世界はGive and Takeによって成り立っています。これからも無料で良質な情報にアクセスできるよう、Giveする人への感謝をリアクションで示しましょう!

この記事をシェアする

自身のブログ等で使用する場合は引用を忘れずに!

また、寄付も受け付けています。コーヒー1杯でとても喜びます(*˘︶˘*)

 Amazonでギフト券(アマギフ)を贈る

こちらのリンク から金額を指定してお贈りください。(デフォルトで10000円になっているのでご変更ください)

配送:Eメール
受取人:staffあっとvigne-cla.com
贈り主:あなたのお名前やニックネーム
メッセージ:◯◯の記事が参考になりました。など

のようにご入力ください。見返りはありませんのでご了承ください。

 Amazonで食事券(すかいらーく優待券)を贈る

500円 1000円 2000円 5000円 からお贈りください。

配送:Eメール
受取人:staffあっとvigne-cla.com
贈り主:あなたのお名前やニックネーム
メッセージ:◯◯の記事が参考になりました。など

のようにご入力ください。見返りはありませんのでご了承ください。

 その他、ギフト券やクーポン券をメールで贈る

デジタルのギフト券/クーポン券はメールアドレス(staffあっとvigne-cla.com)までお送りください。受領の返信をいたします。
紙のギフト券/クーポン券は 「郵便物はこちらへ」の住所 まで送付してください。名刺やメールアドレスを同封していただければ受領の連絡をいたします。
余った株主優待券等の処理におすすめです。
いずれも見返りはありませんのでご了承ください。

不明点はSNSでお気軽にご連絡ください

ビネクラのTwitter・Youtubeでコメントをください!


Slack・Discordの場合はこちらの公開グループに参加してShoya YasudaまでDMをください!


※当ブログに関することは何でもご相談・ご依頼可能です。

この記事を書いた人
Yasuda

博士(理学)。専門は免疫細胞、数理モデル、シミュレーション。米国、中国で研究に携わった。遺伝的アルゴリズム信者。物価上昇のため半額弁当とともに絶滅寸前。

タイトルとURLをコピーしました