Arcpy create composite images from several single band tifs

2503
11
02-05-2014 11:56 PM
JoshuaAhmed
New Contributor II
Hi,

I have a folder containing 7 tif rasters that I would like to combine into one composite tif. I have to do this for many images so I have written a python script to speed up to process. However, I'm having some trouble collecting all of the bands from the folder and creating a composite. Any help would be much appreciated.

import arcpy, sys, os
from arcpy import env
from arcpy.sa import *
arcpy.env.overwriteOutput = True #set the script to overwrite files
#the path to where the images are stored - will need to change for each set of images as the end folders are different
path_images = "J:/Proj/Annual_time_series/Landsat Images/1987/1_001_070/"
for root, dirs, files in os.walk(path_images):
    for name in files:
        beni87 = os.path.join(root,name)
        if beni87.endswith[('B10.TIF', 'B20.TIF', 'B30.TIF', 'B40.TIF', 'B50.TIF', 'B60.TIF', 'B70.TIF')] == True: #collect band 1,2 and 3 image
            tilename = name[0:-7] #remove the band number and .tif from the end of each image to be renamed
            print tilename + "being processed."
            #the list of banded images need to be put here, or the file containing the list needs to be put here
            in_rasters = path_images + name #input the bands from the file
            out_raster = path_images + tilename + "composite.tif" #insert the name of the image between the quotation marks
            #start composite bands processing
            arcpy.CompositeBands_management(in_rasters, out_raster)
11 Replies
JakeSkinner
Esri Esteemed Contributor
Hi Josh,

Try passing a list of the rasters to the Composite Bands tool.  Try the following:

import arcpy, sys, os
from arcpy import env
from arcpy.sa import *
arcpy.env.overwriteOutput = True 
path_images = "J:/Proj/Annual_time_series/Landsat Images/1987/1_001_070/"

rasterList = []

for root, dirs, files in os.walk(path_images):
    for name in files:
        beni87 = os.path.join(root,name)
        if beni87.endswith(('B10.TIF', 'B20.TIF', 'B30.TIF', 'B40.TIF', 'B50.TIF', 'B60.TIF', 'B70.TIF')):
            rasterList.append(beni87)
            tilename = name[0:-7]
            print tilename + "being processed."
            

out_raster = path_images + "\\" + "composite.tif"
arcpy.CompositeBands_management(rasterList, out_raster)


Also, when posting code, be sure to enclose it with CODE tags using the # symbol above.
0 Kudos
JoshuaAhmed
New Contributor II
Hi Josh,

Try passing a list of the rasters to the Composite Bands tool.  Try the following:

import arcpy, sys, os
from arcpy import env
from arcpy.sa import *
arcpy.env.overwriteOutput = True 
path_images = "J:/Proj/Annual_time_series/Landsat Images/1987/1_001_070/"

rasterList = []

for root, dirs, files in os.walk(path_images):
    for name in files:
        beni87 = os.path.join(root,name)
        if beni87.endswith(('B10.TIF', 'B20.TIF', 'B30.TIF', 'B40.TIF', 'B50.TIF', 'B60.TIF', 'B70.TIF')):
            rasterList.append(beni87)
            tilename = name[0:-7]
            print tilename + "being processed."
            

out_raster = path_images + "\\" + "composite.tif"
arcpy.CompositeBands_management(rasterList, out_raster)


Also, when posting code, be sure to enclose it with CODE tags using the # symbol above.


Thanks, that was perfect! Been bugging me all day.

Josh
0 Kudos
AshleyNewby
New Contributor II
Hi,

I am doing something similar, but I have a directory with 11 folders each containing 7 .tif layers to be combined. I tried using os.walk to go through all the folders in the directory and was able to append each folder's content into a rasterList (I emptied the list between each folder). I'm having trouble getting the tool to run on all 7 .tif files in the list. I am posting what I started with before I found this post, and then the after what I tried. In the first code I was trying to get the rasterList into the in_rasters format ex.("band1.tif; band2.tif; band3.tif") in case that was causing the tool not to run. Any help would be awesome!

import arcpy, os
#arcpy.env.workspace = "C:/Test"
arcpy.env.overwriteOutput = True

myDir = arcpy.GetParameterAsText(0)
bands = []
#?myDownloads = os.listdir(myDir) 
try:
    
    #Walk through directories
    for root, dirs, files in os.walk(myDir):
        arcpy.env.workspace = root
        for f in files:
            if f.endswith(".TIF"):
                bands.append(f)
                            #print bands
            a = ','.join(bands)
            b = a.replace(",",";")
                #[f.replace(",", ";") for f in bands]
            arcpy.CompositeBands_management(b, f[:-7] + ".img")
        print bands
        bands=[]
        print b   
   
except:
    print "Tool did not run"
    print arcpy.GetMessages()


and after:
import arcpy, sys, os
from arcpy import env
from arcpy.sa import *
arcpy.env.overwriteOutput = True 
path_images = "C:/test" #arcpy.GetParameterAsText(0) 

rasterList = []

for root, dirs, files in os.walk(path_images):
    for name in files:
        bands = os.path.join(root,name)
        #print bands
        if bands.endswith(".TIF"):
            rasterList.append(bands)
            tilename = name[0:-7]
            #print tilename + " is being processed."
        print rasterList    
        out_raster = path_images + "\\" + tilename + ".img"
        print out_raster
    #arcpy.CompositeBands_management(rasterList, out_raster)
    rasterList = []
print rasterList
0 Kudos
JakeSkinner
Esri Esteemed Contributor
Hi Ashley,

What is the error you are receiving when you attempt to run your code?
0 Kudos
AshleyNewby
New Contributor II
oops, here is the error. And when I working on the first code, it would create a .img file with only the 1st raster. I'm having trouble with the getting the input correct for the tool to run on 7 .tif's in the one directory. Thanks a bunch!

Traceback (most recent call last):
  File "C:\Python27\ArcGIS10.1\Lib\site-packages\pythonwin\pywin\framework\scriptutils.py", line 323, in RunScript
    debugger.run(codeObject, __main__.__dict__, start_stepping=0)
  File "C:\Python27\ArcGIS10.1\Lib\site-packages\pythonwin\pywin\debugger\__init__.py", line 60, in run
    _GetCurrentDebugger().run(cmd, globals,locals, start_stepping)
  File "C:\Python27\ArcGIS10.1\Lib\site-packages\pythonwin\pywin\debugger\debugger.py", line 655, in run
    exec cmd in globals, locals
  File "C:\Temp\landsatLayerStk.py", line 4, in <module>
    import arcpy, sys, os
  File "C:\Program Files (x86)\ArcGIS\Desktop10.1\arcpy\arcpy\management.py", line 12073, in CompositeBands
    raise e
ExecuteError: Failed to execute. Parameters are not valid.
ERROR 000735: Input Rasters: Value is required
Failed to execute (CompositeBands).
0 Kudos
JakeSkinner
Esri Esteemed Contributor
Hi Ashley,

I would check your TIFF files.  Do they end with '.TIF' or '.tif'?  I would try changing the following line:

if f.endswith(".TIF"):


to:

if f.endswith(".TIF") or f.endswith(".tif"):
0 Kudos
AshleyNewby
New Contributor II
I got the same error :( Is there something with the format of the rasterList making the parameters not valid? I noticed in the ArcGIS resource example (http://resources.arcgis.com/en/help/main/10.1/index.html#//00170000009p000000) that a semi-colon separates the .tif files, while the list in rasterList is separated by commas.
0 Kudos
JakeSkinner
Esri Esteemed Contributor
For some reason that I'm not sure of the first raster list was coming out empty. So, I made sure to only execute the composite when the length of the rasterList was greater than 0.  I was able to get the following to work:

import arcpy, sys, os
from arcpy import env
arcpy.env.overwriteOutput = True
path_images = "C:/temp/python/raster"

rasterList = []
x = 1

for root, dirs, files in os.walk(path_images):
    for name in files:    
        bands = os.path.join(root,name)
        if bands.endswith(".TIF") or bands.endswith(".tif"):
            rasterList.append(bands)
    if len(rasterList) > 0:
        out_raster = path_images + "/" + 'raster' + str(x) + ".img"
        arcpy.CompositeBands_management(rasterList, out_raster)
        rasterList = []
        x += 1
Guðjón_FjeldstedÓlafsson
New Contributor

This one!

0 Kudos