Re: [Numpy-discussion] scipy image processing memory leak in python 2.7?
Hi numpy list! I am trying to do some image processing on a number of images, 72 to be specific. I am seeing the python memory usage continually increase. I will say this is being done also using arcpy so that COULD be an issue, but want to rule out scipy first since I am only using arcpy to grab a set of polygons and convert them to a binary image, and to save images to disk. I pass the raster to my numpy/scipy processing. The code is organized as: 1) Main loop iterating over features 2) Function which does image processing using scipy 3) Class which implements some of the image processing features I placed 2 sleep calls in the code.. one at the end of the image processing function and one at the end of each iteration in the main loop. I am seeing a 20MB memory increase each iteration while looking at my processes in Task Manager: Iteration 1: 204,312K and 209,908K, respectively Iteration 2: 233,728K and 230,192K, respectively Iteration 3: 255,676K and 250,600K, respectively Any ideas? Thanks so much! Joe 1) Main loop #for each feature class, convert to raster by "Value" and reclass to 1 and 0 temp_raster = os.path.join(scratchWorkspace,"temp_1.tif") temp_raster_elev = os.path.join(scratchWorkspace,"temp_elev.tif") temp_reclass = os.path.join(scratchWorkspace,"temp_reclass.tif") remap = arcpy.sa.RemapValue([[1,1], ["NoData",0]]) for i,fc in enumerate(potWaterFeatNames): #try to delete the temp rasters in case they exist try: #delete temp rasters arcpy.Delete_management(temp_raster) arcpy.Delete_management(temp_raster_elev) arcpy.Delete_management(temp_reclass) except e: arcpy.AddMessage(e.message()) #clear in memory workspace" arcpy.Delete_management("in_memory/temp_table") #print "on feature {} of {}".format(i+1, len(potWaterFeatNames)) arcpy.AddMessage("on feature {} of {}".format(i+1, len(potWaterFeatNames))) arcpy.AddMessage("fc = {}".format(fc)) arcpy.PolygonToRaster_conversion(fc, "Value", temp_raster, "", "", 1) outReclass = arcpy.sa.Reclassify(temp_raster,"Value",remap) outReclass.save(temp_reclass) del outReclass #call function to process connected components try: proc_im = processBinaryImage(temp_reclass, scratchWorkspace, sm_pixels) except Exception as e: print "FAILED! scipy image processing" arcpy.AddMessage(e.message()) #convert processed raster to polygons try: out_fc = os.path.join(outWorkspace,fc + "_cleaned") arcpy.RasterToPolygon_conversion(proc_im, out_fc) arcpy.Delete_management(proc_im) except Exception as e: print "FAILED! converting cleaned binary raster to polygon" arcpy.AddMessage(e.message()) #delete zero value polyons, gridcode = 0 try: uc = arcpy.UpdateCursor(out_fc, "gridcode=0",arcpy.Describe(out_fc).spatialReference) #loop through 0 rows and delete for row in uc: uc.deleteRow(row) del uc except Exception as e: print "FAILED! deleting rows from table" arcpy.AddMessage(e.message()) #check that number of polygons with gridcode = 1 is greater than 0 count = arcpy.GetCount_management(out_fc) #add elevation field back in if (count > 0): arcpy.PolygonToRaster_conversion(fc, "z_val", temp_raster_elev, "", "", 1) arcpy.sa.ZonalStatisticsAsTable(out_fc, "Id", temp_raster_elev, "in_memory/temp_table","#","MEAN") arcpy.JoinField_management(out_fc, "Id", "in_memory/temp_table", "Id", ["MEAN"]) else: arcpy.Delete_management(out_fc) #delete temp rasters arcpy.Delete_management(temp_raster) arcpy.Delete_management(temp_raster_elev) arcpy.Delete_management(temp_reclass) #python garbage collection #collected = gc.collect() #print "Garbage collector: collected %d objects." % (collected) print "sleeping for 10 seconds" time.sleep(10) 2) Image processing function def processBinaryImage(imageName, save_dir, sm_pixels): fname = os.path.basename(imageName) imRaster = arcpy.Raster(imageName) #Grab AGS info from image #use describe module to grab info descData = arcpy.Describe(imRaster) cellSize = descData.meanCellHeight extent = descData.Extent spatialReference = descData.spatialReference pnt = arcpy.Point(extent.XMin, extent.YMin) del imRaster converter = ConvertRasterNumpy(); imArray = converter.rasterToNumpyArray(imageName) imMin = np.min(imArray) imMax = np.max(imArray) print imMin, imMax arcpy.AddMessage("image min: " + str(imMin)) arcpy.AddMessage("image max: " + str(imMax)); #other flags show_image = False #verbose save_flag = False #under verbose gray = False #threshold but keep gray levels make_binary = False #flag if grayscale is true, to binarize final image save_AGS_rasters = True #create filter object filter = thresholdMedianFilter() lowValue = 0 tImage = filter.thresholdImage(imArray, lowValue, gray) #median filter image filtImage1 = filter.medianFiltImage(tImage,1) #create structuring element for morphological operations sElem = np.array([[0., 1., 0.], [1., 1., 1.], [0., 1., 0.]]) #open filtered image gray = False mImage = filter.mOpenImage(filtImage1, sElem, gray) #set list to store info change num_its = 100 the_change = np.zeros(num_its) for it in range(100): prev = mImage filtImage = filter.medianFiltImage(mImage,1) mImage = filter.mOpenImage(filtImage, sElem, gray) #calculate difference (m_info, z_info) = filter.calcInfoChange(prev, mImage) the_change[it] = z_info del filtImage del prev #if the change is less than 5% of the initial change, exit cur_perc = the_change[it]/the_change[0]*100 if cur_perc < 5.0: print "exiting filter on iteration " + str(it) print "change is less than 5% (this iteration: " + str(cur_perc) + ")" break ############################################################################ # now we have a binary mask. Let's find and label the connected components # ############################################################################ #clear some space del tImage del filtImage1 del m_info label_im_init, nb_labels = ndimage.label(mImage) #Compute size, mean_value, etc. of each region: label_im = label_im_init.copy() del label_im_init sizes = ndimage.sum(mImage, label_im, range(nb_labels + 1)) mean_vals = ndimage.sum(imArray, label_im, range(1, nb_labels + 1)) #clean up small components mask_size = sizes < sm_pixels remove_pixel = mask_size[label_im] label_im[remove_pixel] = 0; labels = np.unique(label_im) label_im = np.searchsorted(labels, label_im) #make label image to a binary image, and convert to arcgis raster label_im[label_im > 0] = 1 label_im = np.array(label_im, dtype = 'float32') print label_im.dtype saveit = False if ~saveit: outRaster = save_dir + "\\" + fname[:-4] + "_CC_" + str(sm_pixels) + ".tif" temp = arcpy.NumPyArrayToRaster(label_im,pnt,cellSize,cellSize) arcpy.DefineProjection_management(temp, spatialReference) arcpy.CopyRaster_management(temp, outRaster, "DEFAULTS","0","","","","8_BIT_UNSIGNED") #clear more space del mImage del nb_labels del sizes del mean_vals del mask_size del remove_pixel del label_im del labels del temp del the_change del sElem del filter del imArray print 'sleeping' time.sleep(20) return outRaster 3) Image processing class class thresholdMedianFilter(): def thresholdImage(self, imArray, thresh, binary = True): """ threshold the image. values equal or below thresh are 0, above are 1""" tImage = imArray tImage[tImage <= thresh] = 0 if binary: tImage[tImage > thresh] = 1 return tImage def medianFiltImage(self,imArray,n=1): """median filter the image n amount of times. a single time is the default""" for n in range(n): prev = imArray imArray = signal.medfilt2d(prev) del prev return imArray def mOpenImage(self,imArray, sElem, gray = False): """ morphological opening """ #Mnp = np.array(morph.binary_erosion(imArray, sElem)) #Mnp = np.array(morph.binary_dilation(Mnp, sElem)) if gray: imArray1 = np.array(morph.grey_dilation(imArray, structure = sElem)) imArray2 = np.array(morph.grey_erosion(imArray1, structure = sElem), dtype = 'float32') del imArray1 return imArray2 else: Mnp1 = np.array(morph.binary_dilation(imArray, sElem)) Mnp2 = np.array(morph.binary_erosion(Mnp1, sElem), dtype = 'float32') del Mnp1 return Mnp2 def calcInfoChange(self,imArray1, imArray2): """calculate entropy of an image""" diff = imArray1 - imArray2 m_norm = sum(abs(diff)) #Manhattan Norm z_norm = norm(diff.ravel(), 0) #Zero norm del diff return (m_norm, z_norm) Joe McGlinchy | Imagery Scientist Database Services - 3D and Imagery Team ESRI || 380 New York St. || Redlands, CA 92373 || USA T 909-793-2853, ext. 4783
On 28.01.2014 19:44, Joseph McGlinchy wrote:
Hi numpy list!
I am trying to do some image processing on a number of images, 72 to be specific. I am seeing the python memory usage continually increase.
which version of scipy are you using? there is a memory leak in ndimage.label in version 0.13 which will be fixed in 0.13.3 due soon. see https://github.com/scipy/scipy/issues/3148
scipy.version.version '0.11.0b1'
numpy.version.version '1.6.1'
Is that, or any other, memory leaks present in these versions? -----Original Message----- From: numpy-discussion-bounces@scipy.org [mailto:numpy-discussion-bounces@scipy.org] On Behalf Of Julian Taylor Sent: Tuesday, January 28, 2014 10:58 AM To: numpy-discussion@scipy.org Subject: Re: [Numpy-discussion] scipy image processing memory leak in python 2.7? On 28.01.2014 19:44, Joseph McGlinchy wrote:
Hi numpy list!
I am trying to do some image processing on a number of images, 72 to be specific. I am seeing the python memory usage continually increase.
which version of scipy are you using? there is a memory leak in ndimage.label in version 0.13 which will be fixed in 0.13.3 due soon. see https://github.com/scipy/scipy/issues/3148 _______________________________________________ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
On Tue, Jan 28, 2014 at 8:08 PM, Joseph McGlinchy <JMcGlinchy@esri.com>wrote:
scipy.version.version '0.11.0b1'
numpy.version.version '1.6.1'
Is that, or any other, memory leaks present in these versions?
That memory leak isn't, it's only present in 0.13.0-0.13.2. I'm not aware of any other leaks that were fixed since 0.11.0 either, but still it would be worth checking if you see the same issue with current scipy master. Ralf
-----Original Message----- From: numpy-discussion-bounces@scipy.org [mailto: numpy-discussion-bounces@scipy.org] On Behalf Of Julian Taylor Sent: Tuesday, January 28, 2014 10:58 AM To: numpy-discussion@scipy.org Subject: Re: [Numpy-discussion] scipy image processing memory leak in python 2.7?
On 28.01.2014 19:44, Joseph McGlinchy wrote:
Hi numpy list!
I am trying to do some image processing on a number of images, 72 to be specific. I am seeing the python memory usage continually increase.
which version of scipy are you using? there is a memory leak in ndimage.label in version 0.13 which will be fixed in 0.13.3 due soon. see https://github.com/scipy/scipy/issues/3148
_______________________________________________ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
_______________________________________________ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
I have updated to scipy 0.13.2 (specifically scipy-0.13.2-win32-superpack-python2.7.exe (59.1 MB)<http://sourceforge.net/projects/scipy/files/latest/download?source=files>) at http://sourceforge.net/projects/scipy/files/ I am still seeing the memory leak, and it appears to be a little larger (25MB) each iteration. Here are the numbers I am seeing on my python process: Iteration 1, sleep1: 207,716k Iteration 1, sleep2: 212,112k Iteration 2, sleep1: 236,488k Iteration 2, sleep2: 237,160k Iteration 3, sleep1: 261,168k Iteration 3, sleep2: 261,264k Iteration 4, sleep1: 285,044k Iteration 4, sleep2: 285,724k -Joe From: numpy-discussion-bounces@scipy.org [mailto:numpy-discussion-bounces@scipy.org] On Behalf Of Ralf Gommers Sent: Wednesday, January 29, 2014 6:16 AM To: Discussion of Numerical Python Subject: Re: [Numpy-discussion] scipy image processing memory leak in python 2.7? On Tue, Jan 28, 2014 at 8:08 PM, Joseph McGlinchy <JMcGlinchy@esri.com<mailto:JMcGlinchy@esri.com>> wrote:
scipy.version.version '0.11.0b1'
numpy.version.version '1.6.1'
Is that, or any other, memory leaks present in these versions? That memory leak isn't, it's only present in 0.13.0-0.13.2. I'm not aware of any other leaks that were fixed since 0.11.0 either, but still it would be worth checking if you see the same issue with current scipy master. Ralf -----Original Message----- From: numpy-discussion-bounces@scipy.org<mailto:numpy-discussion-bounces@scipy.org> [mailto:numpy-discussion-bounces@scipy.org<mailto:numpy-discussion-bounces@scipy.org>] On Behalf Of Julian Taylor Sent: Tuesday, January 28, 2014 10:58 AM To: numpy-discussion@scipy.org<mailto:numpy-discussion@scipy.org> Subject: Re: [Numpy-discussion] scipy image processing memory leak in python 2.7? On 28.01.2014 19:44, Joseph McGlinchy wrote:
Hi numpy list!
I am trying to do some image processing on a number of images, 72 to be specific. I am seeing the python memory usage continually increase.
which version of scipy are you using? there is a memory leak in ndimage.label in version 0.13 which will be fixed in 0.13.3 due soon. see https://github.com/scipy/scipy/issues/3148 _______________________________________________ NumPy-Discussion mailing list NumPy-Discussion@scipy.org<mailto:NumPy-Discussion@scipy.org> http://mail.scipy.org/mailman/listinfo/numpy-discussion _______________________________________________ NumPy-Discussion mailing list NumPy-Discussion@scipy.org<mailto:NumPy-Discussion@scipy.org> http://mail.scipy.org/mailman/listinfo/numpy-discussion
participants (3)
-
Joseph McGlinchy
-
Julian Taylor
-
Ralf Gommers