首页 > 解决方案 > 如何使用python一次从一个文件夹中裁剪多个图像?

问题描述

我有这个代码

但是我很难以某种模式标记每个图像的补丁,例如我有一个名为 000_train 的图像,现在它的补丁应该命名为 000_train_00...... 000_train_01 等等或对于 671_train 它的补丁应该是 671_train_00.......671_train_01 等等

所以我有 671 张图像,所以每个图像补丁应该具有唯一标识其原始图像的名称,但同时自动将每个图像裁剪图像分别存储在单独的文件夹中,名称分别为 0,1.......

import numpy as np
import cv2
import glob
from os import listdir
from os.path import isfile, join
from PIL import Image
import os

#look_up_table={"Ab":"0","An":"1","Di":"2","He":"3","Is":"4","Ky":"5","Kyr":"6","Me":"7","Pi":"8","Vi":"9"}

path = r"C:/Users/55/.spyder-py3/IAM/Train/"
save_path = "C:/Users/55/.spyder-py3/IAM/train_patches/"

# path = r"C:/Users/55/.spyder-py3/IAM/Test/"
# save_path = "C:/Users/55/.spyder-py3/IAM/test_patches/"

image_files = [f for f in os.listdir(path) if f.endswith('.png')]


def load_labels(path):
  labels=[]
  fileList = glob.glob(os.path.join(path,"*.png"))
  for fname in fileList:
      fileName=os.path.basename(fname)
      curLabel=fileName
      labels.append(curLabel)
      return np.asarray(labels)

def load_data(path):
     fileList=glob.glob(path) 
     x=np.array([np.array(Image.open(fname)).flatten() for fname in fileList])
     x=x/255 #img size grey scale
     return x

def imcrop(img, bbox): 
    x1,y1,x2,y2 = bbox
    if x1 < 0 or y1 < 0 or x2 > img.shape[1] or y2 > img.shape[0]:
        img, x1, x2, y1, y2 = pad_img_to_fit_bbox(img, x1, x2, y1, y2)
    return img[y1:y2, x1:x2, :]

def pad_img_to_fit_bbox(img, x1, x2, y1, y2):
    img = np.pad(img, ((np.abs(np.minimum(0, y1)), np.maximum(y2 - img.shape[0], 0)),
               (np.abs(np.minimum(0, x1)), np.maximum(x2 - img.shape[1], 0)), (0,0)), mode="constant")
    y1 += np.abs(np.minimum(0, y1))
    y2 += np.abs(np.minimum(0, y1))
    x1 += np.abs(np.minimum(0, x1))
    x2 += np.abs(np.minimum(0, x1))
    return img, x1, x2, y1, y2

for file in image_files:
    w=0
    sample_image = cv2.imread(path+str(file))
    # get dimensions of image
    dimensions = sample_image.shape

    # height, width, number of channels in image
    height = sample_image.shape[0]
    width = sample_image.shape[1]
    channels = sample_image.shape[2]

    print('Image Dimension    : ',dimensions)
    print('Image Height       : ',height)
    print('Image Width        : ',width)
    print('Number of Channels : ',channels)

    window_width=500
    window_height=500

    writer = file.split("fileName")[0]
    #writer = load_labels(path)

    for i in range(0,height,window_height):
        for j in range(0,width,window_width): 
#            for temp in writer:
           # if crop_image==window_width && window_height
            crop_image = sample_image[i:i+window_height,j:j+window_width]
            cv2.imwrite(save_path+str(writer)+"_"+str(w)+".png",crop_image)
            w=w+1
            #else
            #

标签: python-3.ximage-processingdeep-learning

解决方案


通过以下更改,您的代码可以实现您想要实现的目标:

[...]

path = 'images/'
save_path = "train_patches/"
image_files = [f for f in os.listdir(path) if f.endswith('.jpg')]
#w=0                                                # <-- Moved w=0 from here...

[...]

for file in image_files:
    w=0                                             # <-- ... to here

    [...]

    writer = file.split('.')[0]                     # <-- Split at . to get rid of the file extension
    #writer = load_labels(path)                     # <-- Why?

    for i in range(0,height,window_height):
        for j in range(0,width,window_width): 
            #for image_files in writer:             # <-- Why?
            crop_image = sample_image[i:i+window_height,j:j+window_width]
            cv2.imwrite(save_path+str(writer)+"_"+str(w)+".png",crop_image)
            w=w+1

所以,既然你正在迭代所有文件

for file in image_files:

您必须w=0在此循环内重置,以便您的补丁计数器从0每个图像开始。剩下的就是在没有文件扩展名的情况下获得正确的文件名。Cave at:肯定有更好的方法可以做到这一点,但上述更改是对现有代码的最小更改。

希望有帮助!


编辑:这是一个包含更改/附加主题的最小示例:

import cv2
import os

path = 'images/'
save_path = 'train_patches/'

if not os.path.isdir(save_path):
    os.mkdir(save_path)

image_files = [f for f in os.listdir(path) if f.endswith('.jpg')]

for file in image_files:
    w = 0

    sample_image = cv2.imread(path + str(file))

    height = sample_image.shape[0]
    width = sample_image.shape[1]

    window_width = 500
    window_height = 500

    writer = file.split('.')[0]

    if not os.path.isdir(save_path + '/' + writer + '/'):
        os.mkdir(save_path + '/' + writer + '/')

    for i in range(0, height, window_height):
        for j in range(0, width, window_width):
            crop_image = sample_image[i:i+window_height, j:j+window_width]
            cv2.imwrite(save_path + '/' + writer + '/' + str(w) + '.png', crop_image)
            w = w + 1

for root, dirs, files in os.walk(save_path):
    path = root.split(os.sep)
    print((len(path) - 1) * '---', os.path.basename(root))
    for file in files:
        print(len(path) * '---', file)

输出:

 another_jpg_image
--- 0.png
--- 1.png
--- 10.png
--- 11.png
--- 2.png
--- 3.png
--- 4.png
--- 5.png
--- 6.png
--- 7.png
--- 8.png
--- 9.png
 a_jpg_image
--- 0.png
--- 1.png
 the_last_jpg_image
--- 0.png
--- 1.png

(最后一部分摘自此问答。)

OpenCV 不能自己imwrite生成文件夹,这必须明确地完成,参见。这个问答


推荐阅读