source: grass/trunk/scripts/i.pansharpen/i.pansharpen.py

Last change on this file was 74381, checked in by cmbarton, 5 years ago

added new channel stretch option and updated manual

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:mime-type set to text/x-python
File size: 24.7 KB
Line 
1#!/usr/bin/env python
2
3############################################################################
4#
5# MODULE: i.pansharpen
6#
7# AUTHOR(S): Overall script by Michael Barton (ASU)
8# Brovey transformation in i.fusion.brovey by Markus Neteler <<neteler at osgeo org>>
9# i.fusion brovey converted to Python by Glynn Clements
10# IHS and PCA transformation added by Michael Barton (ASU)
11# histogram matching algorithm by Michael Barton and Luca Delucchi, Fondazione E. Mach (Italy)
12# Thanks to Markus Metz for help with PCA inversion
13# Thanks to Hamish Bowman for parallel processing algorithm
14#
15# PURPOSE: Sharpening of 3 RGB channels using a high-resolution panchromatic channel
16#
17# COPYRIGHT: (C) 2002-2019 by the GRASS Development Team
18#
19# This program is free software under the GNU General Public
20# License (>=v2). Read the file COPYING that comes with GRASS
21# for details.
22#
23# REFERENCES:
24# Roller, N.E.G. and Cox, S., 1980. Comparison of Landsat MSS and merged MSS/RBV
25# data for analysis of natural vegetation. Proc. of the 14th International
26# Symposium on Remote Sensing of Environment, San Jose, Costa Rica, 23-30 April, pp. 1001-1007.
27#
28# Amarsaikhan, D., & Douglas, T. (2004). Data fusion and multisource image classification.
29# International Journal of Remote Sensing, 25(17), 3529-3539.
30#
31# Behnia, P. (2005). Comparison between four methods for data fusion of ETM+
32# multispectral and pan images. Geo-spatial Information Science, 8(2), 98-103
33#
34# for LANDSAT 5: see Pohl, C 1996 and others
35#
36#############################################################################
37
38#%Module
39#% description: Image fusion algorithms to sharpen multispectral with high-res panchromatic channels
40#% keyword: imagery
41#% keyword: fusion
42#% keyword: sharpen
43#% keyword: Brovey
44#% keyword: IHS
45#% keyword: HIS
46#% keyword: PCA
47#% overwrite: yes
48#%End
49#%option G_OPT_R_INPUT
50#% key: red
51#% description: Name of raster map to be used for <red>
52#%end
53#%option G_OPT_R_INPUT
54#% key: green
55#% description: Name of raster map to be used for <green>
56#%end
57#%option G_OPT_R_INPUT
58#% key: blue
59#% description: Name of raster map to be used for <blue>
60#%end
61#% option G_OPT_R_INPUT
62#% key: pan
63#% description: Name of raster map to be used for high resolution panchromatic channel
64#%end
65#%option G_OPT_R_BASENAME_OUTPUT
66#%end
67#%option
68#% key: method
69#% description: Method for pan sharpening
70#% options: brovey,ihs,pca
71#% answer: ihs
72#% required: yes
73#%end
74#%option
75#% key: bitdepth
76#% type: integer
77#% description: Bit depth of image (must be in range of 2-30)
78#% options: 2-32
79#% answer: 8
80#% required: yes
81#%end
82#%flag
83#% key: s
84#% description: Serial processing rather than parallel processing
85#%end
86#%flag
87#% key: l
88#% description: Rebalance blue channel for LANDSAT
89#%end
90#%flag
91#% key: r
92#% description: Rescale (stretch) the range of pixel values in each channel to the entire 0-255 8-bit range for processing (see notes)
93#%end
94
95import os
96
97try:
98 import numpy as np
99 hasNumPy = True
100except ImportError:
101 hasNumPy = False
102
103import grass.script as grass
104
105
106def main():
107 if not hasNumPy:
108 grass.fatal(_("Required dependency NumPy not found. Exiting."))
109
110 sharpen = options['method'] # sharpening algorithm
111 ms1_orig = options['blue'] # blue channel
112 ms2_orig = options['green'] # green channel
113 ms3_orig = options['red'] # red channel
114 pan_orig = options['pan'] # high res pan channel
115 out = options['output'] # prefix for output RGB maps
116 bits = options['bitdepth'] # bit depth of image channels
117 bladjust = flags['l'] # adjust blue channel
118 sproc = flags['s'] # serial processing
119 rescale = flags['r'] # rescale to spread pixel values to entire 0-255 range
120
121 # Checking bit depth
122 bits = float(bits)
123 if bits < 2 or bits > 30:
124 grass.warning(_("Bit depth is outside acceptable range"))
125 return
126
127 outb = grass.core.find_file('%s_blue' % out)
128 outg = grass.core.find_file('%s_green' % out)
129 outr = grass.core.find_file('%s_red' % out)
130
131 if (outb['name'] != '' or outg['name'] != '' or outr['name'] != '') and not grass.overwrite():
132 grass.warning(_('Maps with selected output prefix names already exist.'
133 ' Delete them or use overwrite flag'))
134 return
135
136 pid = str(os.getpid())
137
138 # convert input image channels to 8 bit for processing
139 ms1 = 'tmp%s_ms1' % pid
140 ms2 = 'tmp%s_ms2' % pid
141 ms3 = 'tmp%s_ms3' % pid
142 pan = 'tmp%s_pan' % pid
143
144 if rescale == False:
145 if bits == 8:
146 grass.message(_("Using 8bit image channels"))
147 if sproc:
148 # serial processing
149 grass.run_command('g.copy', raster='%s,%s' % (ms1_orig, ms1),
150 quiet=True, overwrite=True)
151 grass.run_command('g.copy', raster='%s,%s' % (ms2_orig, ms2),
152 quiet=True, overwrite=True)
153 grass.run_command('g.copy', raster='%s,%s' % (ms3_orig, ms3),
154 quiet=True, overwrite=True)
155 grass.run_command('g.copy', raster='%s,%s' % (pan_orig, pan),
156 quiet=True, overwrite=True)
157 else:
158 # parallel processing
159 pb = grass.start_command('g.copy', raster='%s,%s' % (ms1_orig, ms1),
160 quiet=True, overwrite=True)
161 pg = grass.start_command('g.copy', raster='%s,%s' % (ms2_orig, ms2),
162 quiet=True, overwrite=True)
163 pr = grass.start_command('g.copy', raster='%s,%s' % (ms3_orig, ms3),
164 quiet=True, overwrite=True)
165 pp = grass.start_command('g.copy', raster='%s,%s' % (pan_orig, pan),
166 quiet=True, overwrite=True)
167
168 pb.wait()
169 pg.wait()
170 pr.wait()
171 pp.wait()
172
173 else:
174 grass.message(_("Converting image chanels to 8bit for processing"))
175 maxval = pow(2, bits) - 1
176 if sproc:
177 # serial processing
178 grass.run_command('r.rescale', input=ms1_orig, from_='0,%f' % maxval,
179 output=ms1, to='0,255', quiet=True, overwrite=True)
180 grass.run_command('r.rescale', input=ms2_orig, from_='0,%f' % maxval,
181 output=ms2, to='0,255', quiet=True, overwrite=True)
182 grass.run_command('r.rescale', input=ms3_orig, from_='0,%f' % maxval,
183 output=ms3, to='0,255', quiet=True, overwrite=True)
184 grass.run_command('r.rescale', input=pan_orig, from_='0,%f' % maxval,
185 output=pan, to='0,255', quiet=True, overwrite=True)
186
187 else:
188 # parallel processing
189 pb = grass.start_command('r.rescale', input=ms1_orig, from_='0,%f' % maxval,
190 output=ms1, to='0,255', quiet=True, overwrite=True)
191 pg = grass.start_command('r.rescale', input=ms2_orig, from_='0,%f' % maxval,
192 output=ms2, to='0,255', quiet=True, overwrite=True)
193 pr = grass.start_command('r.rescale', input=ms3_orig, from_='0,%f' % maxval,
194 output=ms3, to='0,255', quiet=True, overwrite=True)
195 pp = grass.start_command('r.rescale', input=pan_orig, from_='0,%f' % maxval,
196 output=pan, to='0,255', quiet=True, overwrite=True)
197
198 pb.wait()
199 pg.wait()
200 pr.wait()
201 pp.wait()
202
203 else:
204 grass.message(_("Rescaling image chanels to 8bit for processing"))
205
206 min_ms1 = int(grass.raster_info(ms1_orig)['min'])
207 max_ms1 = int(grass.raster_info(ms1_orig)['max'])
208 min_ms2 = int(grass.raster_info(ms2_orig)['min'])
209 max_ms2 = int(grass.raster_info(ms2_orig)['max'])
210 min_ms3 = int(grass.raster_info(ms3_orig)['min'])
211 max_ms3 = int(grass.raster_info(ms3_orig)['max'])
212 min_pan = int(grass.raster_info(pan_orig)['min'])
213 max_pan = int(grass.raster_info(pan_orig)['max'])
214
215 maxval = pow(2, bits) - 1
216 if sproc:
217 # serial processing
218 grass.run_command('r.rescale', input=ms1_orig, from_='%f,%f' % (min_ms1, max_ms1),
219 output=ms1, to='0,255', quiet=True, overwrite=True)
220 grass.run_command('r.rescale', input=ms2_orig, from_='%f,%f' % (min_ms2, max_ms2),
221 output=ms2, to='0,255', quiet=True, overwrite=True)
222 grass.run_command('r.rescale', input=ms3_orig, from_='%f,%f' % (min_ms3, max_ms3),
223 output=ms3, to='0,255', quiet=True, overwrite=True)
224 grass.run_command('r.rescale', input=pan_orig, from_='%f,%f' % (min_pan, max_pan),
225 output=pan, to='0,255', quiet=True, overwrite=True)
226
227 else:
228 # parallel processing
229 pb = grass.start_command('r.rescale', input=ms1_orig, from_='%f,%f' % (min_ms1, max_ms1),
230 output=ms1, to='0,255', quiet=True, overwrite=True)
231 pg = grass.start_command('r.rescale', input=ms2_orig, from_='%f,%f' % (min_ms2, max_ms2),
232 output=ms2, to='0,255', quiet=True, overwrite=True)
233 pr = grass.start_command('r.rescale', input=ms3_orig, from_='%f,%f' % (min_ms3, max_ms3),
234 output=ms3, to='0,255', quiet=True, overwrite=True)
235 pp = grass.start_command('r.rescale', input=pan_orig, from_='%f,%f' % (min_pan, max_pan),
236 output=pan, to='0,255', quiet=True, overwrite=True)
237
238 pb.wait()
239 pg.wait()
240 pr.wait()
241 pp.wait()
242
243
244 # get PAN resolution:
245 kv = grass.raster_info(map=pan)
246 nsres = kv['nsres']
247 ewres = kv['ewres']
248 panres = (nsres + ewres) / 2
249
250 # clone current region
251 grass.use_temp_region()
252 grass.run_command('g.region', res=panres, align=pan)
253
254 # Select sharpening method
255 grass.message(_("Performing pan sharpening with hi res pan image: %f" % panres))
256 if sharpen == "brovey":
257 brovey(pan, ms1, ms2, ms3, out, pid, sproc)
258 elif sharpen == "ihs":
259 ihs(pan, ms1, ms2, ms3, out, pid, sproc)
260 elif sharpen == "pca":
261 pca(pan, ms1, ms2, ms3, out, pid, sproc)
262 # Could add other sharpening algorithms here, e.g. wavelet transformation
263
264 grass.message(_("Assigning grey equalized color tables to output images..."))
265
266 # equalized grey scales give best contrast
267 grass.message(_("setting pan-sharpened channels to equalized grey scale"))
268 for ch in ['red', 'green', 'blue']:
269 grass.run_command('r.colors', quiet=True, map="%s_%s" % (out, ch),
270 flags="e", color='grey')
271
272 # Landsat too blue-ish because panchromatic band less sensitive to blue
273 # light, so output blue channed can be modified
274 if bladjust:
275 grass.message(_("Adjusting blue channel color table..."))
276 blue_colors = ['0 0 0 0\n5% 0 0 0\n67% 255 255 255\n100% 255 255 255']
277 # these previous colors are way too blue for landsat
278 # blue_colors = ['0 0 0 0\n10% 0 0 0\n20% 200 200 200\n40% 230 230 230\n67% 255 255 255\n100% 255 255 255']
279 bc = grass.feed_command('r.colors', quiet = True, map = "%s_blue" % out, rules = "-")
280 bc.stdin.write('\n'.join(blue_colors))
281 bc.stdin.close()
282
283 # output notice
284 grass.verbose(_("The following pan-sharpened output maps have been generated:"))
285 for ch in ['red', 'green', 'blue']:
286 grass.verbose(_("%s_%s") % (out, ch))
287
288 grass.verbose(_("To visualize output, run: g.region -p raster=%s_red" % out))
289 grass.verbose(_("d.rgb r=%s_red g=%s_green b=%s_blue" % (out, out, out)))
290 grass.verbose(_("If desired, combine channels into a single RGB map with 'r.composite'."))
291 grass.verbose(_("Channel colors can be rebalanced using i.colors.enhance."))
292
293 # write cmd history:
294 for ch in ['red', 'green', 'blue']:
295 grass.raster_history("%s_%s" % (out, ch))
296
297 # create a group with the three outputs
298 #grass.run_command('i.group', group=out,
299 # input="{n}_red,{n}_blue,{n}_green".format(n=out))
300
301 # Cleanup
302 grass.message(_("cleaning up temp files"))
303 try:
304 grass.run_command('g.remove', flags="f", type="raster",
305 pattern="tmp%s*" % pid, quiet=True)
306 except:
307 ""
308
309def brovey(pan, ms1, ms2, ms3, out, pid, sproc):
310 grass.verbose(_("Using Brovey algorithm"))
311
312 # pan/intensity histogram matching using linear regression
313 grass.message(_("Pan channel/intensity histogram matching using linear regression"))
314 outname = 'tmp%s_pan1' % pid
315 panmatch1 = matchhist(pan, ms1, outname)
316
317 outname = 'tmp%s_pan2' % pid
318 panmatch2 = matchhist(pan, ms2, outname)
319
320 outname = 'tmp%s_pan3' % pid
321 panmatch3 = matchhist(pan, ms3, outname)
322
323 outr = '%s_red' % out
324 outg = '%s_green' % out
325 outb = '%s_blue' % out
326
327 # calculate brovey transformation
328 grass.message(_("Calculating Brovey transformation..."))
329
330 if sproc:
331 # serial processing
332 e = '''eval(k = "$ms1" + "$ms2" + "$ms3")
333 "$outr" = 1 * round("$ms3" * "$panmatch3" / k)
334 "$outg" = 1 * round("$ms2" * "$panmatch2" / k)
335 "$outb" = 1 * round("$ms1" * "$panmatch1" / k)'''
336 grass.mapcalc(e, outr=outr, outg=outg, outb=outb,
337 panmatch1=panmatch1, panmatch2=panmatch2,
338 panmatch3=panmatch3, ms1=ms1, ms2=ms2, ms3=ms3,
339 overwrite=True)
340 else:
341 # parallel processing
342 pb = grass.mapcalc_start('%s_blue = 1 * round((%s * %s) / (%s + %s + %s))' %
343 (out, ms1, panmatch1, ms1, ms2, ms3),
344 overwrite=True)
345 pg = grass.mapcalc_start('%s_green = 1 * round((%s * %s) / (%s + %s + %s))' %
346 (out, ms2, panmatch2, ms1, ms2, ms3),
347 overwrite=True)
348 pr = grass.mapcalc_start('%s_red = 1 * round((%s * %s) / (%s + %s + %s))' %
349 (out, ms3, panmatch3, ms1, ms2, ms3),
350 overwrite=True)
351
352 pb.wait(), pg.wait(), pr.wait()
353 try:
354 pb.terminate(), pg.terminate(), pr.terminate()
355 except:
356 ""
357
358 # Cleanup
359 try:
360 grass.run_command('g.remove', flags='f', quiet=True, type='raster',
361 name='%s,%s,%s' % (panmatch1, panmatch2, panmatch3))
362 except:
363 ""
364
365def ihs(pan, ms1, ms2, ms3, out, pid, sproc):
366 grass.verbose(_("Using IHS<->RGB algorithm"))
367 # transform RGB channels into IHS color space
368 grass.message(_("Transforming to IHS color space..."))
369 grass.run_command('i.rgb.his', overwrite=True,
370 red=ms3,
371 green=ms2,
372 blue=ms1,
373 hue="tmp%s_hue" % pid,
374 intensity="tmp%s_int" % pid,
375 saturation="tmp%s_sat" % pid)
376
377 # pan/intensity histogram matching using linear regression
378 target = "tmp%s_int" % pid
379 outname = "tmp%s_pan_int" % pid
380 panmatch = matchhist(pan, target, outname)
381
382 # substitute pan for intensity channel and transform back to RGB color space
383 grass.message(_("Transforming back to RGB color space and sharpening..."))
384 grass.run_command('i.his.rgb', overwrite=True,
385 hue="tmp%s_hue" % pid,
386 intensity="%s" % panmatch,
387 saturation="tmp%s_sat" % pid,
388 red="%s_red" % out,
389 green="%s_green" % out,
390 blue="%s_blue" % out)
391
392 # Cleanup
393 try:
394 grass.run_command('g.remove', flags='f', quiet=True, type='raster',
395 name=panmatch)
396 except:
397 ""
398
399def pca(pan, ms1, ms2, ms3, out, pid, sproc):
400
401 grass.verbose(_("Using PCA/inverse PCA algorithm"))
402 grass.message(_("Creating PCA images and calculating eigenvectors..."))
403
404 # initial PCA with RGB channels
405 pca_out = grass.read_command('i.pca', quiet=True, rescale='0,0',
406 input='%s,%s,%s' % (ms1, ms2, ms3),
407 output='tmp%s.pca' % pid)
408 if len(pca_out) < 1:
409 grass.fatal(_("Input has no data. Check region settings."))
410
411 b1evect = []
412 b2evect = []
413 b3evect = []
414 for l in pca_out.replace('(', ',').replace(')', ',').splitlines():
415 b1evect.append(float(l.split(',')[1]))
416 b2evect.append(float(l.split(',')[2]))
417 b3evect.append(float(l.split(',')[3]))
418
419 # inverse PCA with hi res pan channel substituted for principal component 1
420 pca1 = 'tmp%s.pca.1' % pid
421 pca2 = 'tmp%s.pca.2' % pid
422 pca3 = 'tmp%s.pca.3' % pid
423 b1evect1 = b1evect[0]
424 b1evect2 = b1evect[1]
425 b1evect3 = b1evect[2]
426 b2evect1 = b2evect[0]
427 b2evect2 = b2evect[1]
428 b2evect3 = b2evect[2]
429 b3evect1 = b3evect[0]
430 b3evect2 = b3evect[1]
431 b3evect3 = b3evect[2]
432
433 # Histogram matching
434 outname = 'tmp%s_pan1' % pid
435 panmatch1 = matchhist(pan, ms1, outname)
436
437 outname = 'tmp%s_pan2' % pid
438 panmatch2 = matchhist(pan, ms2, outname)
439
440 outname = 'tmp%s_pan3' % pid
441 panmatch3 = matchhist(pan, ms3, outname)
442
443 grass.message(_("Performing inverse PCA ..."))
444
445 # Get mean value of each channel
446 stats1 = grass.parse_command("r.univar", map=ms1, flags='g',
447 parse=(grass.parse_key_val,
448 {'sep': '='}))
449 stats2 = grass.parse_command("r.univar", map=ms2, flags='g',
450 parse=(grass.parse_key_val,
451 {'sep': '='}))
452 stats3 = grass.parse_command("r.univar", map=ms3, flags='g',
453 parse=(grass.parse_key_val,
454 {'sep': '='}))
455
456 b1mean = float(stats1['mean'])
457 b2mean = float(stats2['mean'])
458 b3mean = float(stats3['mean'])
459
460 if sproc:
461 # serial processing
462 outr = '%s_red' % out
463 outg = '%s_green' % out
464 outb = '%s_blue' % out
465
466 cmd1 = "$outb = 1 * round(($panmatch1 * $b1evect1) + ($pca2 * $b1evect2) + ($pca3 * $b1evect3) + $b1mean)"
467 cmd2 = "$outg = 1 * round(($panmatch2 * $b2evect1) + ($pca2 * $b2evect2) + ($pca3 * $b2evect3) + $b2mean)"
468 cmd3 = "$outr = 1 * round(($panmatch3 * $b3evect1) + ($pca2 * $b3evect2) + ($pca3 * $b3evect3) + $b3mean)"
469
470 cmd = '\n'.join([cmd1, cmd2, cmd3])
471
472 grass.mapcalc(cmd, outb=outb, outg=outg, outr=outr,
473 panmatch1=panmatch1,
474 panmatch2=panmatch2,
475 panmatch3=panmatch3,
476 pca2=pca2,
477 pca3=pca3,
478 b1evect1=b1evect1,
479 b2evect1=b2evect1,
480 b3evect1=b3evect1,
481 b1evect2=b1evect2,
482 b2evect2=b2evect2,
483 b3evect2=b3evect2,
484 b1evect3=b1evect3,
485 b2evect3=b2evect3,
486 b3evect3=b3evect3,
487 b1mean=b1mean,
488 b2mean=b2mean,
489 b3mean=b3mean,
490 overwrite=True)
491 else:
492 # parallel processing
493 pb = grass.mapcalc_start('%s_blue = 1 * round((%s * %f) + (%s * %f) + (%s * %f) + %f)'
494 % (out,
495 panmatch1,
496 b1evect1,
497 pca2,
498 b1evect2,
499 pca3,
500 b1evect3,
501 b1mean),
502 overwrite=True)
503
504 pg = grass.mapcalc_start('%s_green = 1 * round((%s * %f) + (%s * %f) + (%s * %f) + %f)'
505 % (out,
506 panmatch2,
507 b2evect1,
508 pca2,
509 b2evect2,
510 pca3,
511 b2evect3,
512 b2mean),
513 overwrite=True)
514
515 pr = grass.mapcalc_start('%s_red = 1 * round((%s * %f) + (%s * %f) + (%s * %f) + %f)'
516 % (out,
517 panmatch3,
518 b3evect1,
519 pca2,
520 b3evect2,
521 pca3,
522 b3evect3,
523 b3mean),
524 overwrite=True)
525
526 pb.wait(), pg.wait(), pr.wait()
527 try:
528 pb.terminate(), pg.terminate(), pr.terminate()
529 except:
530 ""
531
532 # Cleanup
533 grass.run_command('g.remove', flags='f', quiet=True, type='raster',
534 name='%s,%s,%s' % (panmatch1, panmatch2, panmatch3))
535
536def matchhist(original, target, matched):
537 # pan/intensity histogram matching using numpy arrays
538 grass.message(_("Histogram matching..."))
539
540 # input images
541 original = original.split('@')[0]
542 target = target.split('@')[0]
543 images = [original, target]
544
545 # create a dictionary to hold arrays for each image
546 arrays = {}
547
548 for img in images:
549 # calculate number of cells for each grey value for for each image
550 stats_out = grass.pipe_command('r.stats', flags='cin', input=img,
551 sep=':')
552 stats = stats_out.communicate()[0].split('\n')[:-1]
553 stats_dict = dict(s.split(':', 1) for s in stats)
554 total_cells = 0 # total non-null cells
555 for j in stats_dict:
556 stats_dict[j] = int(stats_dict[j])
557 if j != '*':
558 total_cells += stats_dict[j]
559
560 if total_cells < 1:
561 grass.fatal(_("Input has no data. Check region settings."))
562
563 # Make a 2x256 structured array for each image with a
564 # cumulative distribution function (CDF) for each grey value.
565 # Grey value is the integer (i4) and cdf is float (f4).
566
567 arrays[img] = np.zeros((256, ), dtype=('i4,f4'))
568 cum_cells = 0 # cumulative total of cells for sum of current and all lower grey values
569
570 for n in range(0, 256):
571 if str(n) in stats_dict:
572 num_cells = stats_dict[str(n)]
573 else:
574 num_cells = 0
575
576 cum_cells += num_cells
577
578 # cdf is the the number of cells at or below a given grey value
579 # divided by the total number of cells
580 cdf = float(cum_cells) / float(total_cells)
581
582 # insert values into array
583 arrays[img][n] = (n, cdf)
584
585 # open file for reclass rules
586 outfile = open(grass.tempfile(), 'w')
587
588 for i in arrays[original]:
589 # for each grey value and corresponding cdf value in original, find the
590 # cdf value in target that is closest to the target cdf value
591 difference_list = []
592 for j in arrays[target]:
593 # make a list of the difference between each original cdf value and
594 # the target cdf value
595 difference_list.append(abs(i[1] - j[1]))
596
597 # get the smallest difference in the list
598 min_difference = min(difference_list)
599
600 for j in arrays[target]:
601 # find the grey value in target that corresponds to the cdf
602 # closest to the original cdf
603 if j[1] <= i[1] + min_difference and j[1] >= i[1] - min_difference:
604 # build a reclass rules file from the original grey value and
605 # corresponding grey value from target
606 out_line = "%d = %d\n" % (i[0], j[0])
607 outfile.write(out_line)
608 break
609
610 outfile.close()
611
612 # create reclass of target from reclass rules file
613 result = grass.core.find_file(matched, element='cell')
614 if result['fullname']:
615 grass.run_command('g.remove', flags='f', quiet=True, type='raster',
616 name=matched)
617 grass.run_command('r.reclass', input=original, out=matched,
618 rules=outfile.name)
619 else:
620 grass.run_command('r.reclass', input=original, out=matched,
621 rules=outfile.name)
622
623 # Cleanup
624 # remove the rules file
625 grass.try_remove(outfile.name)
626
627 # return reclass of target with histogram that matches original
628 return matched
629
630if __name__ == "__main__":
631 options, flags = grass.parser()
632 main()
Note: See TracBrowser for help on using the repository browser.