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

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

ただいまの
回答率

90.04%

Python3.5とOpenCV3を使った画像のcrop処理 出力に関する質問

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 541

checkJ

score 28

概要

皆様、お久しぶりです。以下について困っているので意見をいただけると嬉しいです。
私は現在、「巨大な一枚の画像を細切りにして保存する」コードを作成しています。
一枚の画像を何枚にも区切って保存したいのですが、出力される画像が一枚だけになるなど
期待している出力が得られなくて困っております。

処理の流れ

保存したいディレクトリの作成や読み込むディレクトリの指定部分については割愛し、取り込んだ画像をどのように処理したいかを以下に示します。

1.巨大な画像を読み込む
2.読み込んだ画像のサイズを33で割り切れる形にトリミング (resize_image)
3.resize_imageを33×33の画像サイズでcropし、保存(cropped_img)
4.cropped_imgを中心を基準に21×21にcropし、保存(label_img)

困っているポイント

基本的にエラーは出ていないのですが、出力される画像が一枚だけとなり困っております。
初歩的なミスだとは思うのですが、急ぎ解決する必要があるため質問を投稿しました。

参考させていただいたサイト様
Neural Network Console を用いた超解像処理の実装

コードの該当箇所

おそらく原因であろう箇所を抜粋しています。
最後に全文を載せておきます。

starting_point = [6,8]
end_point = [3834, 2153]
num = 0
n = 0


for i in range(range1):
    ii = i +1
    input_dir_sub = os.path.join(input_dir,str(ii))

    os.chdir(input_dir_sub)
    imgs = os.listdir(input_dir_sub)


    for a in imgs:
        img = cv2.imread(a)
        resize_img = drop_size(img, starting_point,end_point )

        test_dir = os.path.join(dataset_dir,"test",str(ii) ,str(a))
        label_dir = os.path.join(dataset_dir,"label",str(ii) ,str(a))

        if not os.path.exists(test_dir):
            os.makedirs(test_dir)
        if not os.path.exists(label_dir):
            os.makedirs(label_dir)      

        if resize_img is None:
            sys.stdout.write("Failed to load image file.\n")
            sys.exit(1)
        if len(resize_img.shape) == 3:
            height, width, channels = resize_img.shape[:3]
        else:
            height, width = resize_img.shape[:2]
            channels = 1

        numX = width // 33
        numY = height // 33

        for i in range(numX):
            for j in range(numY):
                cropped_img = resize_img[33*j:33*(j+1),33*i:33*(i+1)]
                label_img = cropped_img[6:27,6:27]



                cv2.imwrite(test_dir+"\crop_" + ('%04d'%num) + ".png",cropped_img)
                cv2.imwrite(label_dir+"\label_" + ('%04d'%num) + ".png",label_img)

        num = num + 1
        n = n + 1

補足

上に挙げた参考サイトを見てわかるように、CNNのためのデータセット作成用プログラムとなります。
比較的サイズの大きい画像を超解像度化させるため、処理の都合上、画像を細切れにしたいのです。

コード(全文)

最後に、コードの全文を載せておきます。
エラーが発生しては場当たり的に解決するように記述しているため
見苦しいですが、よろしくお願いします。

import numpy
import cv2
import sys
import os
from pathlib import Path


def drop_size(input_image , start_point ,end_point):
    image =(input_image.shape[0], input_image.shape[1])   
    small_image = input_image[start_point[1]:end_point[1],start_point[0]:end_point[0]]

    return small_image



input_dir = input("input_iamge_directory: ")
range1 = len(os.listdir(input_dir))
print("ファイルの数 : %d" %range1)
dataset_dir = input("dataset directory : ")


os.chdir(dataset_dir)
if not os.path.exists("test"):
    os.mkdir("test")
if not os.path.exists("label"):
    os.mkdir("label") 

------------------------------------------------------------------------------------------------------
#基点の指定
starting_point = [6,8]
end_point = [3834, 2153]
num = 0
n = 0


for i in range(range1):
    ii = i +1
    input_dir_sub = os.path.join(input_dir,str(ii))

    os.chdir(input_dir_sub)
    imgs = os.listdir(input_dir_sub)


    for a in imgs:
        img = cv2.imread(a)
        resize_img = drop_size(img, starting_point,end_point )

        test_dir = os.path.join(dataset_dir,"test",str(ii) ,str(a))
        label_dir = os.path.join(dataset_dir,"label",str(ii) ,str(a))

        if not os.path.exists(test_dir):
            os.makedirs(test_dir)
        if not os.path.exists(label_dir):
            os.makedirs(label_dir)      

        if resize_img is None:
            sys.stdout.write("Failed to load image file.\n")
            sys.exit(1)
        if len(resize_img.shape) == 3:
            height, width, channels = resize_img.shape[:3]
        else:
            height, width = resize_img.shape[:2]
            channels = 1

        numX = width // 33
        numY = height // 33

        for i in range(numX):
            for j in range(numY):
                cropped_img = resize_img[33*j:33*(j+1),33*i:33*(i+1)]
                label_img = cropped_img[6:27,6:27]



                cv2.imwrite(test_dir+"\crop_" + ('%04d'%num) + ".png",cropped_img)
                cv2.imwrite(label_dir+"\label_" + ('%04d'%num) + ".png",label_img)

        num = num + 1
        n = n + 1
---------------------------------------------------------------------------------------------------------- 

print("Finish!!")
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

画像をグリッド上に分割したいということでしょうか

 画像をグリッド上に分割する。

import cv2
import matplotlib.pyplot as plt
import numpy as np

img = cv2.imread('sample.jpg')

vsize, hsize = 33, 33
h, w = img.shape[:2]
num_vsplits = h // vsize  # 垂直方向の分割数
num_hsplits = w // hsize  # 水平方向の分割数

# 均等に分割できないと np.spllt() が使えないので、
# 除算したときに余りがでないように画像の端数を切り捨てる。
crop_img = img[:h // num_vsplits * num_vsplits, :w // num_hsplits * num_hsplits]
print('{} -> {}'.format(img.shape, crop_img.shape))  # (480, 640, 3) -> (476, 627, 3)

# 分割する。
out_imgs = []
for h_img in np.vsplit(crop_img, num_vsplits):  # 垂直方向に分割する。
    for v_img in np.hsplit(h_img, num_hsplits):  # 水平方向に分割する。
        out_imgs.append(v_img)
out_imgs = np.array(out_imgs)
print(out_imgs.shape)  # (266, 34, 33, 3)

 結果を描画する。

# 描画する。
fig, ax_list = plt.subplots(num_vsplits, num_hsplits, figsize=(8, 8))
for sub_img, ax in zip(out_imgs, ax_list.ravel()):
    ax.imshow(sub_img[..., ::-1])
    ax.set_axis_off()

plt.show()

イメージ説明

イメージ説明

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/21 17:58

    迅速な回答ありがとうございます!
    おっしゃる通り、画像をグリット上に分割したいのです。
    冗長な質問投稿でしたが、的確に読み取っていただけて助かりました。

    解答していただいたコードで書き直してみようと思います。

    キャンセル

  • 2018/11/21 18:25

    無事に解決いたしました!
    本当にありがとうございます!

    キャンセル

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

  • ただいまの回答率 90.04%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる