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

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

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

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

Q&A

解決済

1回答

1656閲覧

画像の分割プログラムが複雑

ques346

総合スコア47

Python

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

0グッド

0クリップ

投稿2021/06/05 04:45

編集2021/06/07 03:41

python

1img = Image.open("drive/My Drive/mnist_dataset/file.jpeg") 2img = img.resize((30, 30)) 3img = np.asarray(img) 4 5size = 5 6 7v_size = img.shape[0] // size * size 8h_size = img.shape[1] // size * size 9img = img[:v_size, :h_size] 10 11v_split = img.shape[0] // size 12h_split = img.shape[1] // size 13out_img = [] 14[out_img.extend(np.hsplit(h_img, h_split)) 15 for h_img in np.vsplit(img, v_split)]

拾ってきたこのプログラムでfile.jpegを等分割できると知ったのですが、よく分からないので良ければプログラムの意味を上から説明して頂きたいのですが。。
ざっと見た感じの疑問として、ます初めになぜ
v_size = img.shape[0] // size * size
ここでsizeの2乗、つまり25で36を割って切り捨てているのか...?
後半のように縦横を5で割るだけではだめなのか...?

また、
[out_img.extend(np.hsplit(h_img, h_split))
for h_img in np.vsplit(img, v_split)]
これは、式 for リスト変数 in 変数の形??
ならリスト変数に数が格納されるのではと思ったがそうでもない...?
また、複雑すぎて何をやっているのか分からない。。

全体のコードは以下

python

1from google.colab import drive 2drive.mount('/content/drive') 3 4import sys 5import numpy as np 6import matplotlib.pyplot as plt 7 8sys.path.append('/content/drive/My Drive') 9 10import ActivationFunction as AF 11 12from PIL import Image 13from IPython.display import display 14 15img = Image.open("drive/My Drive/mnist_dataset/rei.jpeg") 16img = img.resize((100, 100)) 17img = np.asarray(img) 18 19size = 5 20 21v_split = img.shape[0] // size 22h_split = img.shape[1] // size 23out_img = [] 24[out_img.extend(np.hsplit(h_img, h_split)) 25 for h_img in np.vsplit(img, v_split)] 26 27plt.subplot(161).imshow(out_img[0]) 28plt.subplot(162).imshow(out_img[1]) 29plt.subplot(163).imshow(out_img[2]) 30plt.subplot(164).imshow(out_img[3]) 31plt.subplot(165).imshow(out_img[4]) 32plt.subplot(166).imshow(out_img[5]) 33plt.subplot(167).imshow(out_img[6]) 34plt.subplot(168).imshow(out_img[7]) 35plt.subplot(169).imshow(out_img[8]) 36 37# PILで開いたうえでデータをNumpy形式にする 38# (例えばJPEGは圧縮されていてNumpyな配列になっていないので、 39# そこからNumpyのデータ空間(?)に持ってくる必要がある) 40tefilename = "test2.png" 41teimg = Image.open("drive/My Drive/mnist_dataset/" + tefilename) 42teimg = teimg.resize((10, 10)) 43teimg = np.asarray(teimg) 44 45def extract(x, y): 46 # カラー画像の時Gだけ抜き取りたい 47 if len(x.shape) == 3: 48 h, w, ch = x.shape 49 50 # RGBのGだけ抜き取りたい 51 return x[:,:,y] 52 53v_max, v_min = 300, 200 54 55def diff(x): 56 imgrows, lenrows, imgcolumns, lencolumns = [], [], [], [] 57 for (img, imgt) in zip(x, x.T): 58 rows = img[(v_min<img)&(v_max>img)] 59 columns = imgt[(v_min<imgt)&(v_max>imgt)] 60 imgrows.append(rows) 61 lenrows.append(len(rows)) 62 imgcolumns.append(columns) 63 lencolumns.append(len(columns)) 64 return lenrows + lencolumns 65 66test_data_list = [] 67 68test_data_list.append([0] + diff(extract(teimg, 1)) + diff(extract(teimg, 2)) + diff(extract(teimg, 0))) # 略 69 70out_data_list0 = [] 71 72out_data_list0.append([0] + diff(extract(out_img[0], 1)) + diff(extract(out_img[0], 2)) + diff(extract(out_img[0], 0))) 73 74out_data_list1 = [] 75 76out_data_list1.append([0] + diff(extract(out_img[1], 1)) + diff(extract(out_img[1], 2)) + diff(extract(out_img[1], 0))) 77 78# 見本データに対しても同様に 79# exについて同様に 80training_data_list = [] 81 82for i in range(10): 83 for e in range(1): 84 trad = Image.open("drive/My Drive/mnist_dataset/" + str(10*i+e) + ".png") 85 trad = trad.resize((10, 10)) 86 trad = np.asarray(trad) 87 #g #b #r 抽出後diffしてappend 88 training_data_list.append([i] + diff(extract(trad, 1)) + diff(extract(trad, 2)) + diff(extract(trad, 0))) # 略 89 90print("training_data_list" ,training_data_list) 91print("training_data_list[1:]" ,training_data_list[1:]) 92 93# 3層ニューラルネットワーク 94class ThreeLayerNetwork: 95 # コンストラクタ 96 def __init__(self, inodes, hnodes, onodes, lr): 97 # 各レイヤーのノード数 98 self.inodes = inodes 99 self.hnodes = hnodes 100 self.onodes = onodes 101 102 # 学習率 103 self.lr = lr 104 105 # 重みの初期化 106 self.w_ih = np.random.normal(0.0, 1.0, (self.hnodes, self.inodes)) 107 self.w_ho = np.random.normal(0.0, 1.0, (self.onodes, self.hnodes)) 108 109 # 活性化関数 110 self.af = AF.sigmoid 111 self.daf = AF.derivative_sigmoid 112 113 # 誤差逆伝搬 114 def backprop(self, idata, tdata): 115 116 # 縦ベクトルに変換 117 o_i = np.array(idata, ndmin=2).T 118 t = np.array(tdata, ndmin=2).T 119 120 # 隠れ層 121 np.set_printoptions(threshold=10000) 122 x_h = np.dot(self.w_ih, o_i) 123 o_h = self.af(x_h) 124 125 # 出力層 126 x_o = np.dot(self.w_ho, o_h) 127 o_o = self.af(x_o) 128 129 # 誤差計算 130 e_o = (t - o_o) 131 e_h = np.dot(self.w_ho.T, e_o) 132 133 # 重みの更新 134 self.w_ho += self.lr * np.dot((e_o * self.daf(o_o)), o_h.T) 135 self.w_ih += self.lr * np.dot((e_h * self.daf(o_h)), o_i.T) 136 137 138 # 順伝搬 139 def feedforward(self, idata): 140 # 入力のリストを縦ベクトルに変換 141 o_i = np.array(idata, ndmin=2).T 142 143 # 隠れ層 144 x_h = np.dot(self.w_ih, o_i) 145 o_h = self.af(x_h) 146 147 # 出力層 148 x_o = np.dot(self.w_ho, o_h) 149 o_o = self.af(x_o) 150 151 return o_o 152 153if __name__=='__main__': 154 # パラメータ 155 #inodes=784から30に変更 156 inodes = 31 157 hnodes = 100 158 onodes = 10 159 lr = 0.3 160 161 # ニューラルネットワークの初期化 162 nn = ThreeLayerNetwork(inodes, hnodes, onodes, lr) 163 164 # 学習 165 epoch = 50 166 # 50000 167 for e in range(epoch): 168 print('#epoch ', e) 169 data_size = len(training_data_list) 170 for i in range(data_size): 171 if i % 1000 == 0: 172 print(' train: {0:>5d} / {1:>5d}'.format(i, data_size)) 173 idata = (np.array(out_data_list1) / 255.0 * 0.99) + 0.01 174 # 変更の余地あり 175 tdata = np.zeros(onodes) + 0.01 176 tdata[out_data_list1[0]] = 0.99 177 nn.backprop(idata, tdata) 178 pass 179 pass 180 181 # テスト 182 scoreboard = [] 183 for record in test_data_list: 184 idata = (np.array(out_data_list0) / 255.0 * 0.99) + 0.01 185 predict = nn.feedforward(idata) 186 plabel = np.argmax(predict) 187 print("predict" ,predict) 188 print("plabel" ,plabel) 189 pass 190 191 scoreboard_array = np.asarray(scoreboard) 192 print('performance: ', scoreboard_array.sum() / scoreboard_array.size)

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

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

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

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

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

meg_

2021/06/05 04:59

> 拾ってきたこのプログラムで 無断転載は止めましょう。引用元を書いてください。
ques346

2021/06/05 08:54

引用元は↑です。
meg_

2021/06/05 14:53

> 引用元は↑です。 ? 他の人の質問からコードを借用したという意味でしょうか?ここに書いても皆さんに伝わりませんので質問本文に追記された方が良いかと思います。
guest

回答1

0

ベストアンサー

v_size = img.shape[0] // size * size
ここでsizeの2乗、つまり25で36を割って切り捨てているのか...?

ここが勘違い。
左結合ですから、img.shape[0] // size * size(img.shape[0] // size) * sizeであって、sizeで割って切り捨ててからsizeを掛けています。

元の数を超えない最大のsizeの倍数を取得するイディオムです。
そもそも30が5で割り切れるので、~~質問では無駄になってるコードですね。わかってない人が書いたんでしょう。~~念のため残してある程度のコードなのかもしれません。そのあたりは書いた人に聞かないと分からないですね。


python

1[out_img.extend(np.hsplit(h_img, h_split)) 2 for h_img in np.vsplit(img, v_split)]

このコードはよくないです。
リスト内包の結果を捨てているだけ無駄なので、

python

1for h_img in np.vsplit(img, v_split): 2 out_img.extend(np.hsplit(h_img, h_split))

の方が意図に沿っているでしょう。


リスト内包で書くのだったら

python

1out_img = [np.hsplit(h_img, h_split) for h_img in np.vsplit(img, v_split)]

の1行でよいです。

投稿2021/06/05 05:06

編集2021/06/05 11:31
quickquip

総合スコア11235

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

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

ques346

2021/06/05 10:37 編集

なるほど img.shape[0] // size * size にはそんな意味があったんですね、で、これ丸々必要がないと。 for h_img in np.vsplit(img, v_split): out_img.extend(np.hsplit(h_img, h_split)) これでもなかなか複雑ですね・・・ 単純に読み解いていくと、 まずfor文の条件について、 imgをv_splitという数でvsplitして、その要素を順番にh_imgに入れていく・・・ そしてそのh_imgを使い、どのような処理をしていくか?がfor文の中身で、 h_imgをh_splitという数でhsplitして、リストout_imgに入力、 これを全ての要素について行っていく・・・ といった感じですかね。 で、これで何ができているのか、いまいち掴めない・・・。
quickquip

2021/06/05 11:11

> imgをv_splitという数でvsplitして、その要素を順番にh_imgに入れていく・・・ > そしてそのh_imgを使い、どのような処理をしていくか?がfor文の中身で、 > h_imgをh_splitという数でhsplitして、リストout_imgに入力、 > これを全ての要素について行っていく・・・ 何をやっているかがちゃんと説明できてますよね。
ques346

2021/06/05 14:55

結局これはなにをやってるんでしょうか・・・意味としては。
quickquip

2021/06/05 15:08

imgを等分割してそれぞれを等分割しているので、imgが等分割されるんですよ。
ques346

2021/06/07 03:43 編集

縦分割のあと横分割とかしてる感じですか? このプログラムはそれだけなんでしょうか? extendはリスト内包と等価なんですね、内包の方が小さくまとまってて良いですね。 全体のコードを質問に追記したのですが、 提示いただいた out_img = [np.hsplit(h_img, h_split) for h_img in np.vsplit(img, v_split)] だとエラーが出ます、なぜでしょう(初めに提示頂いたコードではエラーは出ません。)
jbpb0

2021/06/08 02:25

quickquipさん > そもそも30が5で割り切れるので、 > 念のため残してある程度のコードなのかもしれません。そのあたりは書いた人に聞かないと分からないですね。 https://teratail.com/questions/338466 から辿って、 https://qiita.com/ka10ryu1/items/015c6a6a5fa287a47828 を見ると、もともとのコードにはimg.resize()はありません 割り切れない組み合わせで使ってもエラーにならないようにしてあるのだと思います
quickquip

2021/06/08 02:29 編集

つまりterataillerさんに聞いてください、ということです。
ques346

2021/06/08 04:18

terataillerさんはもういないみたいです。
quickquip

2021/06/08 07:42 編集

おお。退会と凍結で見え方が違うんですね。知りませんでした……(まあ言葉が通じなかったしね…)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問