图片批处理介绍:
由于在进行实验时,我们的图片没有resize到固定大小,或者想要将一个特别大的图片切分成若干个相同大小的自图片,常规做法是进来一张图,在算法预处理的环节就resize或者crop掉。这里,利用python+OpenCV进行了输入一个图片目录,然后对该目录下制定格式的图片按照指定大小进行裁剪输出;有的时候,我们接触到tif或者geotif图像,自己就带有地理坐标,如果只用OpenCV的话,可能会将地理坐标抹掉,造成信息的丢失,这里也借鉴了大神的部分工作《python中用GDAL实现矢量对栅格的切割》,利用GDAL的python版本可以实现和OpenCV一样的批量裁剪功能,但是保存的结果是带有地理坐标的tif影像。
OpenCV版本:
代码如下:
# -*- coding: utf-8 -*-
"""
Created on Thu Aug 24 13:30:31 2017
@author: AmosHawk WHU LIESMARS
"""
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
import sys
import os
#import threading
import cv2
#from PIL import Image
print (("shell name:"), sys.argv[0])
print ('params list:', str(sys.argv))
if (len(sys.argv)!=5):
print('the input params should be equal to 4, namely the content, the picture format(eg jpg),the susbsize image height, the subsize image width')
sys.exit(1)
for i in range(1, len(sys.argv)):
print ("param", i, sys.argv[i])
rootContent = sys.argv[1];
suffixFile = sys.argv[2];
heightsubImage = int(sys.argv[3]);
widthsubImage = int(sys.argv[4]);
def resize(dirFile,suffix):
#for rootpath, topdown, files in os.walk(dirFile):
for file in os.listdir(dirFile):
#singlefileName = os.path.join(rootpath,file)
singlefileName = dirFile+"\\"+file
singlefileForm = os.path.splitext(singlefileName)[1][1:]
if(singlefileForm == suffix):
print('loading................ : ',singlefileName)
# oriImage = Image.open(singlefileName)
# oriHei = oriImage.size[0]
# oriWid = oriImage.size[1]
oriImage = cv2.imread(singlefileName)
oriHei = oriImage.shape[0]
oriWid = oriImage.shape[1]
if (oriHei <= heightsubImage|oriWid <= widthsubImage):
print('image :', singlefileName, 'is smaller than the specified shape')
sys.exit(1)
#creat a new subcontent to store the subimages and place it to the upper content
newSubContent = os.path.splitext(singlefileName)[0][0:]
if(os.path.exists(newSubContent) == False):
os.mkdir(newSubContent)
#calculate the numbers by row and coloum by the specific width and heigh
nRowNums = oriHei//heightsubImage
nColNums = oriHei//widthsubImage
#build a list to store the subimage data for the moment
subImages = []
#begin to crop the image
for i in range(0,nRowNums):
for j in range(0,nColNums):
subImage = oriImage[i*heightsubImage:(i+1)*heightsubImage,j*widthsubImage:(j+1)*widthsubImage]
subImages.append(subImage)
#wirte the image to the new created subcontent
for j in range(1,len(subImages)+1):
print('begin to write :', j ,'th subimage of',file)
savefile = newSubContent+ "//" +os.path.splitext(file)[0][0:]+'_'+str(i+j)+'.'+suffix
cv2.imwrite(savefile,subImages[j-1])
print('finish writting')
resize(rootContent,suffixFile)
结果 假如目录下有.jpg图像,定义上述脚本文件名称为batchimagesCV,并且确定机器中有opencv的库,运行命令行 python batchimagesCV.py J:\DATA\CD_EXP\DeepChange\code jpg 300 300:
GDAL版本:
代码如下:
# -*- coding: utf-8 -*-
"""
Created on Thu Aug 24 13:30:31 2017
@author: AmosHawk,WHU,LIESMARS
"""
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
import sys
import os
#import threading
from osgeo import gdal, gdalnumeric,gdal_array
from PIL import Image
from functools import reduce
from numpy import *
gdal.UseExceptions()
print (("shell name:"), sys.argv[0])
print ('params list:', str(sys.argv))
if (len(sys.argv)!=5):
print('the input params should be equal to 4, namely the content, the picture format(eg jpg),the susbsize image height, the subsize image width')
sys.exit(1)
for i in range(1, len(sys.argv)):
print ("param", i, sys.argv[i])
rootContent = sys.argv[1];
suffixFile = sys.argv[2];
heightsubImage = int(sys.argv[3]);
widthsubImage = int(sys.argv[4]);
# EDIT: this is basically an overloaded
# version of the gdal_array.OpenArray passing in xoff, yoff explicitly
# so we can pass these params off to CopyDatasetInfo
#
def OpenArray( array, prototype_ds = None, xoff=0, yoff=0 ):
ds = gdal_array.OpenArray((array) )
if ds is not None and prototype_ds is not None:
if type(prototype_ds).__name__ == 'str':
prototype_ds = gdal.Open( prototype_ds )
if prototype_ds is not None:
gdalnumeric.CopyDatasetInfo( prototype_ds, ds, xoff=xoff, yoff=yoff )
return ds
def resize(dirFile,suffix):
#for rootpath, topdown, files in os.walk(dirFile):
for file in os.listdir(dirFile):
#singlefileName = os.path.join(rootpath,file)
singlefileName = dirFile+"\\"+file
singlefileForm = os.path.splitext(singlefileName)[1][1:]
if(singlefileForm == suffix):
print('loading................ : ',singlefileName)
# Load the source data as a gdalnumeric array
srcArray = gdalnumeric.LoadFile(singlefileName)
# Also load as a gdal image to get geotransform
# (world file) info
srcImage = gdal.Open(singlefileName)
#geoTrans = srcImage.GetGeoTransform()
if srcImage is None:
print('can not open',singlefileName,'with gdal')
sys.exit(1)
oriHei = srcImage.RasterYSize
oriWid = srcImage.RasterXSize
oriBandNum = srcImage.RasterCount
if (oriHei <= heightsubImage|oriWid <= widthsubImage):
print('image :', singlefileName, 'is smaller than the specified shape')
sys.exit(1)
#creat a new subcontent to store the subimages and place it to the upper content
newSubContent = os.path.splitext(singlefileName)[0][0:]
if(os.path.exists(newSubContent) == False):
os.mkdir(newSubContent)
#calculate the numbers by row and coloum by the specific width and heigh
nRowNums = oriHei//heightsubImage
nColNums = oriHei//widthsubImage
#build a list to store the subimage data for the moment
subImages = []
subImagesPos = []
#begin to crop the image
if oriBandNum == 1:
for i in range(0,nRowNums):
for j in range(0,nColNums):
#subImage = oriImage[i*heightsubImage:(i+1)*heightsubImage,j*widthsubImage:(j+1)*widthsubImage]
clip = srcArray[i*heightsubImage:(i+1)*heightsubImage,j*widthsubImage:(j+1)*widthsubImage]
subImages.append(clip)
subImagesPos.append([i*heightsubImage,j*widthsubImage])
else:
for i in range(0,nRowNums):
for j in range(0,nColNums):
#subImage = oriImage[i*heightsubImage:(i+1)*heightsubImage,j*widthsubImage:(j+1)*widthsubImage]
clip = srcArray[:,i*heightsubImage:(i+1)*heightsubImage,j*widthsubImage:(j+1)*widthsubImage]
subImages.append(clip)
subImagesPos.append([i*heightsubImage,j*widthsubImage])
#wirte the image to the new created subcontent
for j in range(1,len(subImages)+1):
print('begin to write :', j ,'th subimage of',file)
print(type(subImages[j-1]))
savefile = newSubContent+ "//" +os.path.splitext(file)[0][0:]+'_'+str(j)+'.'+suffix
gtiffDriver = gdal.GetDriverByName( 'GTiff' )
if gtiffDriver is None:
raise ValueError("Can't find GeoTiff Driver")
gtiffDriver.CreateCopy(savefile,OpenArray(subImages[j-1], prototype_ds=singlefileName,xoff=subImagesPos[j-1][1],yoff=subImagesPos[j-1][0]))
print('finish writting')
resize(rootContent,suffixFile)