質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

1227閲覧

python3で画像の畳み込みをすると白っぽくなる

nobuyo

総合スコア48

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

2グッド

2クリップ

投稿2017/08/18 08:52

編集2017/08/20 03:48

###前提・実現したいこと
pythonで次のような画像どうしの畳み込み演算を行い、手ブレを再現したい。

原画像
ブレを表現した画像

詳細は下記の通りです。
ご教授のほどよろしくお願い致します。

###発生している問題

ImageJのFD Mathという機能で畳み込んだ場合と後述のPythonスクリプトでは、結果が異なります。
ImageJのように原画像の色合いを維持したいのですが、どうも畳み込みの結果を正規化する際に値がごく狭い範囲に補正され、白っぽくなっているような気がします。しかし解決方法がわかりませんでした。

  • python

イメージ説明

  • ImageJ

イメージ説明

###該当のソースコード
引数には原画像のファイル名や出力先のファイル名を適宜与えています。

Python

1import sys 2import numpy as np 3from PIL import Image 4from scipy import signal 5 6if len(sys.argv) != 5: 7 print('python blurer.py input fft_of_blur fft_of_original result') 8 sys.exit(1) 9 10# ブレを表現する画像をつくる 11size = 128 12half_size = int((size-1)/2) 13blur = Image.new('L', (size, size)) 14blur_pixels = blur.load() 15 16for x in range(half_size, half_size+5): 17 for y in range(half_size, half_size+20): 18 blur_pixels[half_size,y] = 255 19 20blur.save('blur.png') 21 22# FFTと畳み込み 23 24# ブレ画像 25blur_arr = np.array(blur) 26Z = np.fft.fft2(blur_arr) 27Z = np.fft.fftshift(Z) 28print(Z) 29P = np.log(np.abs(Z) + 1) 30P_norm = (P * 255.0) / np.amax(P) 31y = np.uint8(np.around(P_norm)) 32img_out = Image.fromarray(y) 33img_out.save(sys.argv[2]) 34 35# 原画像 36img_in = Image.open(sys.argv[1]) 37x = np.array(img_in.convert('L')) 38X = np.fft.fft2(x) 39X = np.fft.fftshift(X) 40print(X) 41P = np.log(np.abs(X) + 1) 42P_norm = (P * 255.0) / np.amax(P) 43y = np.uint8(np.around(P_norm)) 44print(y) 45img_out = Image.fromarray(y) 46img_out.save(sys.argv[3]) 47 48# 畳み込み結果 49W = np.fft.fftshift(np.fft.ifft2(Z*X)) 50print(W) 51P = np.log(np.abs(W) + 1) 52P_norm = P / np.amax(P) * 255 53y = np.uint8(np.around(P_norm)) 54print(y) 55img_out = Image.fromarray(y) 56img_out.save(sys.argv[4])

###補足情報

  • Python 3.5.2 :: Anaconda 4.2.0
  • numpy 1.13.1
  • PIL.Image 1.1.7

追記(20170820)

回答により色の補正ができるようになり、問題解決しました。
最終的なソースコードを文献として残しておきます。

python

1import sys 2import numpy as np 3from PIL import Image 4from matplotlib import pylab as plt 5import cv2 6 7if len(sys.argv) != 2: 8 print('python blurer.py fft_of_original.png') 9 sys.exit(1) 10 11# ブレを表現する画像をつくる 12size = 128 13half_size = int((size - 1) / 2) 14blur = Image.new('L', (size, size)) 15blur_pixels = blur.load() 16 17for x in range(half_size, half_size + 5): 18 for y in range(half_size, half_size + 20): 19 blur_pixels[half_size, y] = 255 20 21blur.save('blur.png') 22 23# FFTと畳み込み 24 25# ブレ画像 26blur_arr = np.array(blur) 27Z = np.fft.fft2(blur_arr) 28Z = np.fft.fftshift(Z) 29P = np.log(np.abs(Z) + 1) 30P_norm = (P * 255.0) / np.amax(P) 31P_norm = (P_norm - np.amin(P_norm)) / np.amax(P_norm) * 255 32y = np.around(P_norm) 33blur_img = np.around(P_norm) 34print("BLUR MIN:%s"%np.min(y)) 35print("BLUR MAX:%s"%np.max(y)) 36img_out = Image.fromarray(y).convert('L') 37img_out.save("blur_arr.png") 38 39# 原画像 40img_in = Image.open(sys.argv[1]) 41x = np.array(img_in.convert('L')) 42dest = np.min(x) 43X = np.fft.fft2(x) 44X = np.fft.fftshift(X) 45P = np.log(np.abs(X) + 1) 46P_norm = (P * 255.0) / np.amax(P) 47y = np.around(P_norm) 48# dest = np.min(y) 49fftshift = np.around(P_norm) 50print("ORIGINAL MIN:%s"%np.min(y)) 51print("ORIGINAL MAX:%s"%np.max(y)) 52img_out = Image.fromarray(y).convert('L') 53img_out.save("fftshift.png") 54 55# 畳み込み結果 56W = np.fft.fftshift(np.fft.ifft2(Z * X)) 57P = np.log(np.abs(W) + 1) 58P_norm = P / np.amax(P) * 255 59src = np.min(P_norm) 60y = np.around(P_norm) 61print("CONV MIN:%s"%np.min(y)) 62print("CONV MAX:%s"%np.max(y)) 63img_out = Image.fromarray(y).convert('L') 64img_out.save("conv.png") 65 66# ガンマ補正 67 68gamma = np.log(src/255) / np.log(dest/255) 69 70print(gamma) 71lookUpTable = np.zeros((256, 1), dtype = 'uint8') 72for i in range(256): 73 if i == 0: 74 lookUpTable[i][0] = 255 * pow(float(0.000001) / 255, 1.0 / gamma) 75 else: 76 lookUpTable[i][0] = 255 * pow(float(i) / 255, 1.0 / gamma) 77 78img = cv2.imread('conv.png', 1) 79img_gamma = cv2.LUT(img, lookUpTable) 80cv2.imwrite('conv-lut.png', img_gamma)
ikuwow👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

■明るすぎる原因
恐らく、畳み込み時の* 255がおかしいのだと思います。

Python

1# 畳み込み結果 2W = np.fft.fftshift(np.fft.ifft2(Z*X)) 3P = np.log(np.abs(W) + 1) 4P_norm = P / np.amax(P) * 255

グレースケールの値を正規化するために、255をかけていますが、
255では大きすぎて「補正後61であってほしい値」が255の88%の値(約220)になってしまっている」
→一番くらい61の明るさが、約220になっていては明るすぎる、ですね。

■処理の段階別の値(目標値)

インデックス生画像畳み込み後(補正前)畳み込み後(補正後)
最小値610.88525491142661
最大値2551.0255

これをグラフにすると、
変換グラフ
※1 原点に近い部分は理屈抜きに勝手に0に近い値を入れました。
※2 0に近い値は「0」にされない程度に「0」に近い値(0.000000001など)を使ってください。

これならガンマ補正の式・グラフで対応できますね。
ここで、dstもrawもわかっているので、γの値が逆算できます。

これを元に畳み込み後(補正値)が計算できないでしょうか?


理屈抜きに直感でまとめているため怪しい気もしますが、これで解決できそうな気がします。

投稿2017/08/20 02:31

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nobuyo

2017/08/20 03:49

無事うまくいきました!大変お世話になりました。ありがとうございました。
guest

0

pythonで次のような画像どうしの畳み込み演算を行い、手ブレを再現したい。

もし手振れ再現が最終的な目的であれば、シンプルにfilter2Dでいけるというのはインチキでしょうか?

ブレ方向を質問と同様にする場合には、kernel_motion_blur[ : , int((size-1)/2)] = np.ones(size)にしたらいけますね。

'---
FFT/畳み込みを使ってる感がいろいろ楽しそうで、質問の方法の解を見てみたい気もします。

2017-08-19 追記
python blurer.py fft_of_original.pngで同じ画像が再現できます。
まだ修正中ですが…

Python

1import sys 2import numpy as np 3from PIL import Image 4# from scipy import signal 5 6# Comment out 7# if len(sys.argv) != 5: 8# print('python blurer.py input fft_of_blur fft_of_original result') 9 10if len(sys.argv) != 2: 11 print('python blurer.py fft_of_original.png') 12 sys.exit(1) 13 14# ブレを表現する画像をつくる 15size = 128 16half_size = int((size - 1) / 2) 17blur = Image.new('L', (size, size)) 18blur_pixels = blur.load() 19 20for x in range(half_size, half_size + 5): 21 for y in range(half_size, half_size + 20): 22 blur_pixels[half_size, y] = 255 23 24blur.save('blur.png') 25 26# FFTと畳み込み 27 28# ブレ画像 29blur_arr = np.array(blur) 30Z = np.fft.fft2(blur_arr) 31Z = np.fft.fftshift(Z) 32P = np.log(np.abs(Z) + 1) 33P_norm = (P * 255.0) / np.amax(P) 34y = np.uint8(np.around(P_norm)) 35print("BLUR MIN:%s"%np.min(y)) 36print("BLUR MAX:%s"%np.max(y)) 37img_out = Image.fromarray(y) 38img_out.save("blur_arr.png") 39 40# 原画像 41img_in = Image.open(sys.argv[1]) 42x = np.array(img_in.convert('L')) 43X = np.fft.fft2(x) 44X = np.fft.fftshift(X) 45P = np.log(np.abs(X) + 1) 46P_norm = (P * 255.0) / np.amax(P) 47y = np.uint8(np.around(P_norm)) 48print("ORIGINAL MIN:%s"%np.min(y)) 49print("ORIGINAL MAX:%s"%np.max(y)) 50img_out = Image.fromarray(y) 51img_out.save("fftshift.png") 52 53# 畳み込み結果 54W = np.fft.fftshift(np.fft.ifft2(Z * X)) 55P = np.log(np.abs(W) + 1) 56P_norm = P / np.amax(P) * 255 57y = np.uint8(np.around(P_norm)) 58print("CONV MIN:%s"%np.min(y)) 59print("CONV MAX:%s"%np.max(y)) 60img_out = Image.fromarray(y) 61img_out.save("conv.png") 62

投稿2017/08/18 10:14

編集2017/08/18 22:25
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nobuyo

2017/08/18 10:50 編集

ご回答ありがとうございます。 > もし手振れ再現が最終的な目的であれば、シンプルにfilter2Dでいけるというのはインチキでしょうか? > ブレ方向を質問と同様にする場合には、kernel_motion_blur[ : , int((size-1)/2)] = np.ones(size)にしたらいけますね。 実は最終的な目的として、ブレている画像をブレの角度・大きさそれぞれで分類し、PSF推定の真似事を行うことを考えておりまして、この方法で大量に生成した画像をCNNを用いた分類器の学習データとするつもりでいます。 ご教示いただいた通りfilter2Dを用いる方法も考えられたのですが、ブレをkernelとして表現する場合、分類するラベルをどのように設定するかをイメージしにくかったため敬遠していた部分がありました。 これを機にそちらを使うことも検討したいと思います。 > FFT/畳み込みを使ってる感がいろいろ楽しそうで、質問の方法の解を見てみたい気もします。 もう少し自分でも調べつつ、他の回答も待ってみようと思います。 せっかくお答えいただいたところ恐縮です。
退会済みユーザー

退会済みユーザー

2017/08/18 12:54 編集

とりあえず動くコードかつ、同じ不具合が起きる状態にしました。 コマンドは、python blur画像 original画像で動きます。 色の修正は追って行います。 コメント欄だとインデントが崩れるのでそこは汲んでください o.0 import sys import numpy as np from PIL import Image from scipy import signal ###Comment out # if len(sys.argv) != 5: # print('python blurer.py input fft_of_blur fft_of_original result') if len(sys.argv) != 2: print('python blurer.py fft_of_original') sys.exit(1) # ブレを表現する画像をつくる size = 128 half_size = int((size-1)/2) blur = Image.new('L', (size, size)) blur_pixels = blur.load() for x in range(half_size, half_size+5): for y in range(half_size, half_size+20): blur_pixels[half_size,y] = 255 blur.save('blur.png') # FFTと畳み込み # ブレ画像 blur_arr = np.array(blur) Z = np.fft.fft2(blur_arr) Z = np.fft.fftshift(Z) P = np.log(np.abs(Z) + 1) P_norm = (P * 255.0) / np.amax(P) y = np.uint8(np.around(P_norm)) img_out = Image.fromarray(y) img_out.save("blur_arr.png") # 原画像 img_in = Image.open(sys.argv[1]) x = np.array(img_in.convert('L')) X = np.fft.fft2(x) X = np.fft.fftshift(X) P = np.log(np.abs(X) + 1) P_norm = (P * 255.0) / np.amax(P) y = np.uint8(np.around(P_norm)) img_out = Image.fromarray(y) img_out.save("fftshift.png") # 畳み込み結果 W = np.fft.fftshift(np.fft.ifft2(Z*X)) P = np.log(np.abs(W) + 1) P_norm = P / np.amax(P) * 255 y = np.uint8(np.around(P_norm)) img_out = Image.fromarray(y) img_out.save("conv.png")
nobuyo

2017/08/18 12:50

> とりあえず動くコードかつ、同じ不具合が起きる状態にしました。色の修正は追って行います。 質問投稿時に掲載したコードでも動作はすると思いますが、引数等を取り払ってファイル名をハードコードするように書き換えたという解釈でよろしいでしょうか(質問するのに引数を使うのは抽象的でなかったですね、すみません) 色の修正にも力をお貸しいただけるとのことで、引き続きよろしくお願い致します。
退会済みユーザー

退会済みユーザー

2017/08/18 12:54

引数の数が合わなくてちょっと触りました。 blurの画像は関数の中で作られる見たいですので、引数から外してしまいました。保存する画像はハードコードしました。 --- ちょっと修正ミスがあったので、先のコメントのコードもこの後すぐに差し替えます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問