我更新了heatmap.py
脚本,以便您可以为每个点指定密度。我将更改上传到我的博客。不确定它是否会完全满足您的要求!
干杯,亚历克斯
更新 [2020 年 11 月 13 日]
我不久前归档了我的博客,因此链接不再有效,因此以下是更改以供参考:
差异文件:
--- __init__.py 2010-09-14 08:40:35.829079482 +0100
+++ __init__.py.mynew 2010-09-06 14:50:10.394447647 +0100
@@ -1,5 +1,5 @@
#heatmap.py v1.0 20091004
-from PIL import Image,ImageChops
+from PIL import Image,ImageChops,ImageDraw
import os
import random
import math
@@ -43,10 +43,13 @@
Most of the magic starts in heatmap(), see below for description of that function.
"""
def __init__(self):
+ self.minIntensity = 0
+ self.maxIntensity = 0
self.minXY = ()
self.maxXY = ()
+
- def heatmap(self, points, fout, dotsize=150, opacity=128, size=(1024,1024), scheme="classic"):
+ def heatmap(self, points, fout, dotsize=150, opacity=128, size=(4048,1024), scheme="classic", area=(-180,180,-90,90)):
"""
points -> an iterable list of tuples, where the contents are the
x,y coordinates to plot. e.g., [(1, 1), (2, 2), (3, 3)]
@@ -59,33 +62,41 @@
size -> tuple with the width, height in pixels of the output PNG
scheme -> Name of color scheme to use to color the output image.
Use schemes() to get list. (images are in source distro)
+ area -> specify the coordinates covered by the resulting image
+ (could create an image to cover area larger than the max/
+ min values given in the points list)
"""
-
+ print("Starting heatmap")
self.dotsize = dotsize
self.opacity = opacity
self.size = size
self.imageFile = fout
-
+
if scheme not in self.schemes():
tmp = "Unknown color scheme: %s. Available schemes: %s" % (scheme, self.schemes())
raise Exception(tmp)
- self.minXY, self.maxXY = self._ranges(points)
- dot = self._buildDot(self.dotsize)
+ self.minXY = (area[0],area[2])
+ self.maxXY = (area[1],area[3])
+ self.minIntensity, self.maxIntensity = self._intensityRange(points)
+
img = Image.new('RGBA', self.size, 'white')
- for x,y in points:
+ for x,y,z in points:
+ dot = self._buildDot(self.dotsize,z)
tmp = Image.new('RGBA', self.size, 'white')
tmp.paste( dot, self._translate([x,y]) )
img = ImageChops.multiply(img, tmp)
-
+ print("All dots built")
colors = colorschemes.schemes[scheme]
img.save("bw.png", "PNG")
+ print("Saved temp b/w image")
+ print("Colourising")
self._colorize(img, colors)
img.save(fout, "PNG")
-
+ print("Completed colourising and saved final image %s" % fout)
def saveKML(self, kmlFile):
"""
Saves a KML template to use with google earth. Assumes x/y coordinates
@@ -110,17 +121,19 @@
"""
return colorschemes.schemes.keys()
- def _buildDot(self, size):
+ def _buildDot(self, size,intensity):
""" builds a temporary image that is plotted for
each point in the dataset"""
+
+ intsty = self._calcIntensity(intensity)
+ print("building dot... %d: %f" % (intensity,intsty))
+
img = Image.new("RGB", (size,size), 'white')
- md = 0.5*math.sqrt( (size/2.0)**2 + (size/2.0)**2 )
- for x in range(size):
- for y in range(size):
- d = math.sqrt( (x - size/2.0)**2 + (y - size/2.0)**2 )
- rgbVal = int(200*d/md + 50)
- rgb = (rgbVal, rgbVal, rgbVal)
- img.putpixel((x,y), rgb)
+ draw = ImageDraw.Draw(img)
+ shade = 256/(size/2)
+ for x in range (int(size/2)):
+ colour = int(256-(x*shade*intsty))
+ draw.ellipse((x,x,size-x,size-x),(colour,colour,colour))
return img
def _colorize(self, img, colors):
@@ -139,7 +152,7 @@
rgba.append(alpha)
img.putpixel((x,y), tuple(rgba))
-
+
def _ranges(self, points):
""" walks the list of points and finds the
max/min x & y values in the set """
@@ -153,6 +166,23 @@
return ((minX, minY), (maxX, maxY))
+ def _calcIntensity(self,z):
+ return (z/self.maxIntensity)
+
+ def _intensityRange(self, points):
+ """ walks the list of points and finds the
+ max/min points of intensity
+ """
+ minZ = points[0][2]
+ maxZ = minZ
+
+ for x,y,z in points:
+ minZ = min(z, minZ)
+ maxZ = max(z, maxZ)
+
+ print("(minZ, maxZ):(%d, %d)" % (minZ,maxZ))
+ return (minZ, maxZ)
+
def _translate(self, point):
""" translates x,y coordinates from data set into
pixel offsets."""
和一个演示脚本:
import heatmap
import random
import MySQLdb
import math
print "starting script..."
db = MySQLdb.connect(host="localhost", # your host, usually localhost
user="username", # your username
passwd="password", # your password
db="database") # name of the data base
cur = db.cursor()
minLng = -180
maxLng = 180
minLat = -90
maxLat = 90
# create and execute the query
query = "SELECT lat, lng, intensity FROM mytable \
WHERE %f<=tllat AND tllat<=%f \
AND %f<=tllng AND tllng<=%f" % (minLat,maxLat,minLng,maxLng)
cur.execute(query)
pts = []
# print all the first cell of all the rows
for row in cur.fetchall() :
print (row[1],row[0],row[2])
# work out the mercator projection for latitute x = asinh(tan(x1))
proj = math.degrees(math.asinh(math.tan(math.radians(row[0]))))
print (row[1],proj,row[2])
print "-"*15
if (minLat < proj and proj < maxLat):
pts.append((row[1],proj,row[2]))
print "Processing %d points..." % len(pts)
hm = heatmap.Heatmap()
hm.heatmap(pts, "bandwidth2.png",30,155,(1024,512),'fire',(minLng,maxLng,minLat,maxLat))