Select to view content in your preferred language

Followup to unanswered question - how to convert rasters to 1-band grayscale?

1490
4
Jump to solution
03-26-2013 12:32 PM
StavrosC
Occasional Contributor
Hi everyone, I'm asking this again in hopes that someone can help.  Please don't hold the repost against me! 

I have hundreds of multi-band, georeferenced JPGs that I need to convert to single band geotiffs. All images are black and white, so I only want one band to minimize file size. 

Does anyone know tool that I can use to do this in a batch process? I've tried copy raster, mosaic to new raster, and composite bands. None of them will give me a single band raster, although copy raster produces a nice 3-band geotiff. Inserting a grayscale function through the image analysis window worked well but only for a single image at a time. 

Thanks so much for any thoughts! I know there is a way to do this....
0 Kudos
1 Solution

Accepted Solutions
StavrosC
Occasional Contributor
I found a solution through modifying python script that was designed to calculate NDVI by performing calculations over raster bands.  My script is rudimentary, and it creates a temporary raster file for each of the three bands, then averages them and creates a new raster.  If you are trying to do the same thing, this script may help.  You will have to modify it to reflect your file names.


[INDENT]#Code is adapted from http://esriaustraliatechblog.wordpress.com/2012/03/14/using-python-to-calculate-ndvi-with-multiband-...
#Code is being modified to convert 3-band, georeferenced jpegs to single band geotiffs raster.

import arcpy, string

#import the environment settings and spatial analyst extension.  Import time so you can clock the geoprocessing speed.  Import glob to list file names. 

from arcpy import env
from arcpy.sa import *
import time             #Let's see how long this takes
import glob

# Overwrite pre-existing files so that temporary rasters can be copied over one another. 
arcpy.env.overwriteOutput = True

#Check out the Spatial Analyst extension.

arcpy.CheckOutExtension("spatial")

#Add your workspace here

env.workspace = r"I:\alb_aerials\1957"

#Create list of input and output file names
jpg_files=[]
for line in glob.glob("I:/alb_aerials/1957/*.jpg"):
  arcpy.env.overwriteOutput = True
  jpg_files.append(line)                                   #Add jpg file name to jpg file list
  input = line[20:]                                        #For my directory/file names, the file name starts after the 20th character.
  print input


#Create raster directory and specify inputs. It references the input you specified above
  result = input[:-4] + ".tif"
  B1 = input + "\Band_1"
  B2 = input + "\Band_2"
  B3 = input + "\Band_3"

#Define outputs ??? Note:  These will need to be deleted if you need to run this script again
  B1_out = "B1.tif"
  B2_out = "B2.tif"
  B3_out = "B3.tif"

#Copy raster and map algebra ??? makes new rasters of Red and NearIR
  arcpy.CopyRaster_management(B1, B1_out,"","0","0","","","8_BIT_UNSIGNED")
  print "Copied Band1 band as raster"
  arcpy.CopyRaster_management(B2, B2_out,"","0","0","","","8_BIT_UNSIGNED")
  print "Copied Band2 band as raster"
  arcpy.CopyRaster_management(B3, B3_out,"","0","0","","","8_BIT_UNSIGNED")
  print "Copied Band3 band as raster"

 
#Create Numerator and Denominator rasters as variables and NDVI output (note that arcpy.sa.Float returns a floating point raster)

  Num = arcpy.sa.Int(Raster(B1_out) + Raster(B2_out) + Raster(B3_out))
  Avg_band = arcpy.sa.Divide(Num, 3)
  print "Averaging"

#Saving output to result output you specified above.   Avg_band.save(result)
  print "Successful"
  print "Image number ", glob.glob("I:/alb_aerials/1957/*.jpg").index(line)
  print "Total elapsed time (hours): ", time.clock()/3600[/INDENT]

View solution in original post

0 Kudos
4 Replies
JeffreySwain
Esri Regular Contributor
Have you considered using the mosaic dataset and then applying the Gray Scale Function?  Once you have the grayscale, you can then export it.
0 Kudos
StavrosC
Occasional Contributor
Thanks for the response.  I've also looked into the grayscale function but have not been able to batch process the transformation of individual jpg grids to grayscale geotiffs. 

I created a sample mosaic of 5 of the 400 jpgs and inserted a grayscale function through the image analysis window.  I then used right click -> export data.  This successfully created a 1-band geotiff.  The problem is that this merges the images into a single raster, but I want the result to be a collection of 400 1-band geotiffs with the same extents as the initial 3-band jpgs, not one huge geotiff. Can you advise?  Maybe I need a Python script to average the three bands?
0 Kudos
StavrosC
Occasional Contributor
I found a solution through modifying python script that was designed to calculate NDVI by performing calculations over raster bands.  My script is rudimentary, and it creates a temporary raster file for each of the three bands, then averages them and creates a new raster.  If you are trying to do the same thing, this script may help.  You will have to modify it to reflect your file names.


[INDENT]#Code is adapted from http://esriaustraliatechblog.wordpress.com/2012/03/14/using-python-to-calculate-ndvi-with-multiband-...
#Code is being modified to convert 3-band, georeferenced jpegs to single band geotiffs raster.

import arcpy, string

#import the environment settings and spatial analyst extension.  Import time so you can clock the geoprocessing speed.  Import glob to list file names. 

from arcpy import env
from arcpy.sa import *
import time             #Let's see how long this takes
import glob

# Overwrite pre-existing files so that temporary rasters can be copied over one another. 
arcpy.env.overwriteOutput = True

#Check out the Spatial Analyst extension.

arcpy.CheckOutExtension("spatial")

#Add your workspace here

env.workspace = r"I:\alb_aerials\1957"

#Create list of input and output file names
jpg_files=[]
for line in glob.glob("I:/alb_aerials/1957/*.jpg"):
  arcpy.env.overwriteOutput = True
  jpg_files.append(line)                                   #Add jpg file name to jpg file list
  input = line[20:]                                        #For my directory/file names, the file name starts after the 20th character.
  print input


#Create raster directory and specify inputs. It references the input you specified above
  result = input[:-4] + ".tif"
  B1 = input + "\Band_1"
  B2 = input + "\Band_2"
  B3 = input + "\Band_3"

#Define outputs ??? Note:  These will need to be deleted if you need to run this script again
  B1_out = "B1.tif"
  B2_out = "B2.tif"
  B3_out = "B3.tif"

#Copy raster and map algebra ??? makes new rasters of Red and NearIR
  arcpy.CopyRaster_management(B1, B1_out,"","0","0","","","8_BIT_UNSIGNED")
  print "Copied Band1 band as raster"
  arcpy.CopyRaster_management(B2, B2_out,"","0","0","","","8_BIT_UNSIGNED")
  print "Copied Band2 band as raster"
  arcpy.CopyRaster_management(B3, B3_out,"","0","0","","","8_BIT_UNSIGNED")
  print "Copied Band3 band as raster"

 
#Create Numerator and Denominator rasters as variables and NDVI output (note that arcpy.sa.Float returns a floating point raster)

  Num = arcpy.sa.Int(Raster(B1_out) + Raster(B2_out) + Raster(B3_out))
  Avg_band = arcpy.sa.Divide(Num, 3)
  print "Averaging"

#Saving output to result output you specified above.   Avg_band.save(result)
  print "Successful"
  print "Image number ", glob.glob("I:/alb_aerials/1957/*.jpg").index(line)
  print "Total elapsed time (hours): ", time.clock()/3600[/INDENT]
0 Kudos
ColinMurray
Emerging Contributor
Hello
I've been wondering about this for a while. To make a colour image greyscale without only saving 1 band (which I find reduces image quality).

Thanks. It looks like applying the Greyscale raster function and then exporting as a new raster will work.

For batch processing I'm going to try:
Using the edit raster function tool in a batch process for all the rasters.
Then perform another batch process with the export tool.
0 Kudos