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

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

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

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

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Python

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

2回答

1607閲覧

pythonでfor文を使わずに任意の値でconvolutionを行いたい.

masaosa

総合スコア18

NumPy

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

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Python

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

1クリップ

投稿2021/04/11 09:42

pythonにおいてfor文を使わずにconvolutionをしたいと考えています.

画像サイズを64*64としています.

行いたい処理として,3*3の注目画素範囲に対して,
その中心画素(convolution[4])と
周辺8近傍(convolution[4]-convolution[0~8]: 中心画素同士の減算はしない)
との差を2乗したものを,
その中心画素からの画素の距離に基づいた重みづけをして加算したものを新たな画素値になる処理です.
(中心画素に対して上下左右なら重みは1,斜め方向なら√2となります.)
scipyなど調べましたが,何を使用したらよいかわかりませんでした.
ご教授のほどよろしくお願いいたします.

python

1 2import numpy as np 3 4y_size=64 5x_size=64 6x=np.empty(3) 7y=np.empty(3) 8 9original_image=np.arange(64*64) 10convolution=np.empty(9) 11last_image=np.empty(64*64,dtype="double") 12 13for i in range(y_size): 14 15 for j in range(x_size): 16 17 x[0]=(j+x_size-1) % x_size 18 x[1]=j 19 x[2]=(j+1) % x_size 20 21 y[0]=(i+y_size-1) % y_size 22 y[1]=i 23 y[2]=(i+1) % y_size 24 25 for m in range(9): 26 #配列convolutionに3*3の画素値を代入 27 A=x[int(np.floor(m%3))] 28 B=y[int(np.floor((m/3)))]*x_size 29 convolution[m]=original_image[int(B)+int(A)] 30 #中心画素とその8近傍の画素値の差を2乗して,画素間の距離の重みづけ #改行 31 value=np.power((convolution[4]-convolution[0]),2.0)/np.sqrt(2.0) \ 32 + np.power((convolution[4]-convolution[1]),2.0) \ 33 + np.power((convolution[4]-convolution[2]),2.0)/np.sqrt(2.0) \ 34 + np.power((convolution[4]-convolution[3]),2.0) \ 35 + np.power((convolution[4]-convolution[5]),2.0) \ 36 + np.power((convolution[4]-convolution[6]),2.0)/np.sqrt(2.0) \ 37 + np.power((convolution[4]-convolution[7]),2.0) \ 38 + np.power((convolution[4]-convolution[8]),2.0)/np.sqrt(2.0) \ 39 40 last_image[i*x_size+j]=value 41 42print(last_image) 43#後で64*64にreshapeをする

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

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

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

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

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

guest

回答2

0

ベストアンサー

以下でどうでしょう

python

1original_image = np.arange(64*64).reshape(64, 64) 2 3pad_image = np.pad(original_image, (1, 1), 'wrap') 4 5f = np.array([[1/2**0.5, 1, 1/2**0.5], 6 [1, 0, 1], 7 [1/2**0.5, 1, 1/2**0.5]]) 8arr_for_conv = np.lib.stride_tricks.sliding_window_view(pad_image, (3, 3)) 9last_image = np.sum((arr_for_conv - original_image[:, :, None, None])**2*f, (-2, -1))

手順

配列の端の値を畳み込み演算するため、まずnp.pad()で外周を埋めます。質問文のコードを見る限り'wrap'モードでのパディングと思われます。

python

1original_image = np.arange(64*64).reshape(64, 64) # オリジナル画像、形は64*64 2# array([[ 0, 1, 2, ..., 61, 62, 63], 3# [ 64, 65, 66, ..., 125, 126, 127], 4# [ 128, 129, 130, ..., 189, 190, 191], 5# ..., 6# [3904, 3905, 3906, ..., 3965, 3966, 3967], 7# [3968, 3969, 3970, ..., 4029, 4030, 4031], 8# [4032, 4033, 4034, ..., 4093, 4094, 4095]]) 9 10pad_image = np.pad(original_image, (1, 1), 'wrap') # 形は66*66 11# array([[4095, 4032, 4033, ..., 4094, 4095, 4032], 12# [ 63, 0, 1, ..., 62, 63, 0], 13# [ 127, 64, 65, ..., 126, 127, 64], 14# ..., 15# [4031, 3968, 3969, ..., 4030, 4031, 3968], 16# [4095, 4032, 4033, ..., 4094, 4095, 4032], 17# [ 63, 0, 1, ..., 62, 63, 0]])

np.lib.stride_tricks.sliding_window_view()を使って3*3のブロックに変換します。

python

1arr_for_conv = np.lib.stride_tricks.sliding_window_view(pad_image, (3, 3)) # 形は64*64*3*3 2# array([[[[4095, 4032, 4033], 3# [ 63, 0, 1], 4# [ 127, 64, 65]], # この3*3それぞれが質問文のコードのconvolutionに相当 5# 6# [[4032, 4033, 4034], 7# [ 0, 1, 2], 8# [ 64, 65, 66]], 9# 10# [[4033, 4034, 4035], 11# [ 1, 2, 3], 12# [ 65, 66, 67]], 13# 14# ...,

ブロードキャストを用いて、中心との差を計算し、

python

1arr_for_conv - original_image[:, :, None, None]

それを2乗、

python

1(arr_for_conv - original_image[:, :, None, None]) ** 2

さらに重み付け

python

1# 重み付け用のフィルター 2f = np.array([[1/2**0.5, 1, 1/2**0.5], 3 [1, 0, 1], 4 [1/2**0.5, 1, 1/2**0.5]]) 5(arr_for_conv - original_image[:, :, None, None]) ** 2 * f # 形は64*64*3*3

その3*3の部分をnp.sum()で合計

python

1last_image = np.sum((arr_for_conv - original_image[:, :, None, None])**2*f, (-2, -1)) # 形は64*64 2 3# array([[3.96381285e+07, 3.92578213e+07, 3.92578213e+07, ..., 4# 3.92578213e+07, 3.92578213e+07, 3.88966733e+07], 5# [2.93616653e+04, 1.97820659e+04, 1.97820659e+04, ..., 6# 1.97820659e+04, 1.97820659e+04, 2.93616653e+04], 7# [2.93616653e+04, 1.97820659e+04, 1.97820659e+04, ..., 8# 1.97820659e+04, 1.97820659e+04, 2.93616653e+04], 9# ..., 10# [2.93616653e+04, 1.97820659e+04, 1.97820659e+04, ..., 11# 1.97820659e+04, 1.97820659e+04, 2.93616653e+04], 12# [2.93616653e+04, 1.97820659e+04, 1.97820659e+04, ..., 13# 1.97820659e+04, 1.97820659e+04, 2.93616653e+04], 14# [3.88966733e+07, 3.92578213e+07, 3.92578213e+07, ..., 15# 3.92578213e+07, 3.92578213e+07, 3.96381285e+07]])

投稿2021/04/14 01:33

kirara0048

総合スコア1399

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

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

masaosa

2021/04/14 09:16

非常にわかりやすい説明ありがとうございます! ちなみにsliding_window_viewはnumpy1.20の最新のバージョンからの関数でしょうか? 上記のコードで行い,値としてはほぼ間違いなかったのですが,私のコードのnp.sqrt(2.0)で除算する場合と,kirara0048様の1/2**0.5で乗算するところで誤差(非常に小さい値なのですが,,,)が出る箇所がありました.これはやはり,小数点の乗算と除算での誤差によるものということでしょうか?
kirara0048

2021/04/14 09:26

>sliding_window_viewはnumpy1.20の最新のバージョンからの関数でしょうか? そうです。なお、scikit-imageをインストールしていればskimage.util.view_as_windows()という関数で同じことができます。 >小数点の乗算と除算での誤差によるものということでしょうか? まあそうですね。 `np.allclose(配列1, 配列2)`で小数点の誤差を気にせず2つの配列が同じかどうか比較することができます。
masaosa

2021/04/15 01:15

ありがとうございました!非常に処理が速くなりました!
guest

0

ネットで調べると、

scipy.signal.correlateが使えると書いてありました。
5年前の記事絵古いかもしれませんが、ご参考まで。

Pythonのconvolve2dについて

投稿2021/04/11 11:32

ppaul

総合スコア24670

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

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

masaosa

2021/04/11 22:54

ご回答ありがとうございます! 任意のフィルター係数のコンボリューションのやり方は上記の記事で理解しました. フィルターの係数を決める際,中心画素とその8近傍の画素値の差を係数にしたい場合,for文なしで書くことはできますでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問