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

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

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

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

Q&A

解決済

1回答

2231閲覧

python PIL 画像処理

fia

総合スコア57

Python

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

0グッド

0クリップ

投稿2018/11/10 12:15

編集2018/11/10 13:51

やりたいこと

pythonでの画像処理で読み込んだ画像の色情報を変更して描画する。

発生している問題

matplotlibで画像をプロットしてクリックした地点の色を別の色に変更しようとした際、中途半端に変更される。
また、クリックした地点から数ピクセル離れたところの色情報が取得される。

ソースコード

Python

1from PIL import Image 2import numpy as np 3import matplotlib.pyplot as plt 4import sys 5 6class im: 7 def __init__(self,image): 8 self.image=image 9 def onclick(self,event): 10 plist=self.image[int(event.ydata)][int(event.xdata)] 11 print(plist) 12 h, w, c = self.image.shape 13 for i in range(h): 14 for j in range(w): 15 if (self.image[i][j] == plist).all(): 16 self.image[i][j] = [255, 255, 255] 17 fig = plt.figure() 18 ax = fig.add_subplot(111) 19 ax.imshow(self.image) 20 plt.show() 21 22# 画像を読み込む 23img = Image.open( "./test.png") 24img=np.array(img) 25c_event=im(img) 26fig=plt.figure() 27ax=fig.add_subplot(111) 28ax.imshow(img) 29cid = fig.canvas.mpl_connect('button_press_event', c_event.onclick) 30plt.show() 31

試したこと

plistの色情報を手動指定
変更したいところの色が[255,0,0]の場合に、クリックしたときに取得した色情報が[255,0,0]であること、画像の変更がおかしいことを確認し、plist=[255,0,0]の固定情報になるよう書き換えて再実行したところ、うまく変更がされた。

###追記
元画像
イメージ説明
変更後
イメージ説明

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

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

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

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

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

guest

回答1

0

ベストアンサー

クリックしたピクセルと同色のピクセルを白く塗りつぶすプログラムのようですね。

matplotlibで画像をプロットしてクリックした地点の色を別の色に変更しようとした際、中途半端に変更される。

中途半端というのがよく分からないのですが、クリックのたびに新しいウインドウが表示されました。
これは意図した動作ではないと思われるので、最後に示すように、ウインドウ内の画像更新するようにコード修正しました。

原因を追記

現象再現できました。plistは実際には画像のクリックされたセル値を指しているだけです。
よってforループ中にクリックされたピクセル値の値を更新するとplistの値も更新され、それ以降の判定がおかしくなってしまっています。
回避するにはplistに対して実値を(深い)コピー代入する必要があります。

ついでに

forループからnumpyで一括操作する手法に修正してみました。
ディープコピーなどを心配せずにかつ高速で処理できます。
参考:python,OpenCV,numpyによる色抽出・変換

また、クリックした地点から数ピクセル離れたところの色情報が取得される。

再現できませんでした。
ウインドウを拡大、移動などしてクリックしてみましたが、問題なくクリックされたピクセルが更新されました。
厳密にいえば、intで切り捨てしているので、クリック点の左上に1ピクセルずれた位置が塗りつぶされますが。

Python

1 2from PIL import Image 3import numpy as np 4import matplotlib.pyplot as plt 5import sys 6 7class im: 8 def __init__(self,image,fig,ax): 9 self.image=image 10 self.fig = fig # 追加 11 self.ax = ax # 追加 12 13 def onclick(self,event): 14 15 """ forループする手法 16 plist = np.copy(self.image[int(event.ydata)][int(event.xdata)]) # 自身のピクセル値がかわらないようにディープコピーする! 17 print(plist) 18 h, w, c = self.image.shape 19 for i in range(h): 20 for j in range(w): 21 if (self.image[i][j] == plist).all(): 22 self.image[i][j] = [255, 255, 255] 23 """ 24 25 # numpy一括操作する手法 26 # python,OpenCV,numpyによる色抽出・変換 27 # https://teratail.com/questions/100301 28 plist = self.image[int(event.ydata)][int(event.xdata)] 29 self.image[np.logical_and.reduce(self.image == plist, axis=2)] = [255,255,255] 30 31 # 修正 32 self.ax.imshow(self.image) 33 fig.canvas.draw() 34 #fig = plt.figure() 35 #ax = fig.add_subplot(111) 36 #ax.imshow(self.image) 37 #plt.show() 38 39# 画像を読み込む 40img = Image.open( "./test.png") # 41img=np.array(img) 42 43# pngのアルファチャンネルを除去する 44if img.shape[2] == 4: 45 img = img[:,:,0:3] 46 47fig=plt.figure() 48ax=fig.add_subplot(111) 49c_event=im(img,fig,ax) # データと描画更新のためにfig,axを渡す 50 51ax.imshow(img) 52cid = fig.canvas.mpl_connect('button_press_event', c_event.onclick) 53plt.show()

イメージ説明

投稿2018/11/10 12:58

編集2018/11/10 17:16
can110

総合スコア38262

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

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

fia

2018/11/10 13:48

ウインドウの更新ができるようにしていただきありがとうございます。 中途半端という表現はあまり良くなかったですね。申し訳ありません。 追加で変更後の画像を投稿したいと思います。
fia

2018/11/10 23:22

追記への対応ありがとうございます。 単純な代入だと参照渡しになっていたのが原因だったのですね。 一括操作する手法も回答いただきありがとうございました。
can110

2018/11/10 23:31

そうですね、他言語での参照と同じ動作です。 pythonでは、わりとひっかかりやすい罠です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問