利用Python+OpenCV与GDAL批量裁剪图像

来源:互联网 发布:网络犯罪调查分集剧情 编辑:程序博客网 时间:2024/06/05 19:21

图片批处理介绍:

       由于在进行实验时,我们的图片没有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_functionfrom __future__ import absolute_importfrom __future__ import divisionimport sysimport os#import threadingimport cv2#from PIL import Imageprint (("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_functionfrom __future__ import absolute_importfrom __future__ import divisionimport sysimport os#import threadingfrom osgeo import gdal, gdalnumeric,gdal_arrayfrom PIL import Imagefrom functools import reducefrom 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)


结果,如果机器中某个目录下有tif图像,并且有安装GDAL的话,运行结果如下: