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

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

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

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

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

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

PyCharm

エディター・開発ツール

Q&A

解決済

2回答

2720閲覧

Pythonで画像を一定のサイズに分割させ、端部の処理をしたい

masa_jl033

総合スコア12

NumPy

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

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

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

PyCharm

エディター・開発ツール

0グッド

0クリップ

投稿2019/08/07 02:28

編集2019/08/08 06:39

Pythonの初心者です。
前回の質問で、おかげさまで以下のようにPythonを使った画像分割のコードを書けるようになりました。

Python

1from skimage import io 2import os 3import skimage 4 5tile_size = 50 6filename = 'pic.png' 7 8new_dir = 'data/' 9os.mkdir(new_dir) 10 11im = io.imread(filename) 12 13print(im) 14for i in range(10): 15 ii = tile_size * i + 50 16for j in range(10): 17 jj = tile_size * j + 50 18tmp = im[ii:ii+tile_size, jj:jj+tile_size] 19print(tmp) 20 21io.imsave(new_dir + str(i)+ "_" + str(j) + ".tif", tmp)

上のコードではrange(10)、すなわち横方向に10分割、縦方向に10分割となっていますが、
これを
・左端から右端まで
・上端から下端まで
と分割し、端部の処理については
・一番端がちょうど分割後の各セルのサイズだった場合は、分割した画像を出力する
・端部が分割後の各セルのサイズに満たない場合は分割した画像を切り捨てる
としたいと考えています。

1番目の方法(解決済み)---
前回のアドバイスを参考に、分割数を算出するコードを記述し、
出力する範囲を1番目から(分割数-1)までとした下記のコードでは
きちんと出力されました。
しかし、これではもし一番端の画像サイズがちょうど分割後の各セルのサイズに足りている場合も
トリミングされることになってしまい、少し困ってしまいます。

Python

1from skimage import io 2import os 3import numpy as np 4 5tile_size = 50 6filename = 'pic.png' 7 8new_dir = 'data/' 9os.mkdir(new_dir) 10 11im = io.imread(filename) 12 13vsize, hsize = 50, 50 # 分割後の各セルのサイズ 14h, w = im.shape[:2] # 画像の大きさ 15num_vsplits, num_hsplits = np.floor_divide([h, w], [vsize, hsize]) # 分割数 16 17print(im) 18for i in range(num_vsplits-1): 19 ii = tile_size * i + 50 20 for j in range(num_hsplits-1): 21 jj = tile_size * j + 50 22 tmp = im[ii:ii+tile_size, jj:jj+tile_size] 23 print(tmp) 24 25 io.imsave(new_dir + str(i)+ "_" + str(j) + ".tif", tmp)

2番目の方法(未解決)---
もう一つの方法として、出力する範囲を
1から(「画像の縦or横の長さ/分割後の各セルのサイズ」の整数部分)まで
とすれば、もし一番端の画像サイズがちょうど分割後の各セルのサイズに足りている場合は
出力されることになり、今回の目的に合う方法だと考えました。

記述したコードは次のようになります。

Python

1from skimage import io 2import os 3import numpy as np 4 5tile_size = 50 6filename = 'pic.png' 7 8new_dir = 'data2/' 9os.mkdir(new_dir) 10 11im = io.imread(filename) 12 13print(im) 14for i in range(int(width // 50)): 15 ii = tile_size * i + 50 16 for j in range(int(width // 50)): 17 jj = tile_size * j + 50 18 tmp = im[ii:ii+tile_size, jj:jj+tile_size] 19 print(tmp) 20 21 io.imsave(new_dir + str(i)+ "_" + str(j) + ".tif", tmp)

しかし、data2というファイルはきちんと生成されるものの、画像が1つも出力されません。
エラーは出ていませんが、どこがいけないのかご教示いただけませんか?

また、これよりもエレガントな方法があれば、ご教示いただけますと助かります。

どうぞよろしくお願いします。

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

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

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

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

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

t_obara

2019/08/07 05:11

質問をする前に、「質問する前のヒント」をよくお読みになることをお勧めいたします。
tiitoi

2019/08/07 06:27

前回回答したコードで端部は切り捨てるようになっていませんでしたか?
masa_jl033

2019/08/08 06:36

当方の進捗状況に合わせ、より具体的に本文を修正しました。ご教示のほどよろしくお願いします。
guest

回答2

0

以下の式で分割を実行する前に余りが出ないように画像をクリップして、その後に分割の処理を行えばよいと思います。

クロップするサイズ: (h, w) 元の画像のサイズ: (H, W) クリップ後の画像のサイズ (new_H, new_W) new_H = H - H mod h = h * floor(H / h) new_W = W - W mod w = w * floor(W / w)

簡単な例で考えると、
10 を 3 で割りきれるような値にする場合

10 - 10 % 3 = 10 - 1 = 9
もしくは
3 * 10 // 3 = 3 * 3 = 9
とすると、余りを切り捨てられます。

python

1import numpy as np 2 3img = np.zeros((521, 531, 3)) # 元の画像 4 5orig_hw = img.shape[:2] # 元の画像サイズ (高さ, 幅) 6cell_hw = 50, 50 # 分割後の画像サイズ (高さ, 幅) 7new_hw = np.array(orig_hw) - np.mod(orig_hw, cell_hw) # クロップするサイズ 8 9# 新しいサイズでクロップする。 10crop_img = img[: new_hw[0], : new_hw[1]] # クロップした画像 11print(f"{img.shape} --> {crop_img.shape}")

または

python

1import numpy as np 2 3img = np.zeros((500, 500, 3)) 4 5orig_hw = img.shape[:2] # 元の画像サイズ (高さ, 幅) 6cell_hw = 50, 50 # 分割後の画像サイズ (高さ, 幅) 7new_hw = np.array(cell_hw) * np.floor_divide(orig_hw, cell_hw) # クロップするサイズ 8 9# 新しいサイズでクロップする。 10crop_img = img[: new_hw[0], : new_hw[1]] # クロップした画像 11print(f"{img.shape} --> {crop_img.shape}")

投稿2019/08/08 06:54

編集2019/08/08 06:55
tiitoi

総合スコア21956

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

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

masa_jl033

2019/08/13 08:22

大いに参考にさせていただきました。こちらの自己解決方法も記入しましたので参考にしていただけましたら幸いです。
guest

0

自己解決

なるべく短く記述したいと思い、
「画像のサイズ/セルのサイズ の整数部分」と記述しました。
im.shape[n]と記述することで、スカラーとベクトルの混在も解決できました。

Python

1from skimage import io 2import os 3 4tile_size = 50 5filename = 'pic.png' 6 7new_dir = 'data/' 8os.mkdir(new_dir) 9 10im = io.imread(filename) 11 12print(im) 13for i in range(int(im.shape[0] // tile_size)): 14 ii = tile_size * i 15 for j in range(int(im.shape[1] // tile_size)): 16 jj = tile_size * j 17 tmp = im[ii:ii+tile_size, jj:jj+tile_size] 18 print(tmp) 19 io.imsave(new_dir + str(i)+ "_" + str(j) + ".tif", tmp)

投稿2019/08/13 08:19

masa_jl033

総合スコア12

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問