使用 Python 图像库抗锯齿时,通过透明消除边缘的细边框
我有一张高分辨率图像,想使用 Google Maps API v3 将其用作平铺地图叠加层。
我使用 MapTiler 将其分解为所需缩放级别的适当图块。效果很好,只是在作为原始图像边缘的图块上有一条细细的灰黑色边框。
遵循 http://groups.google.com 上的第二篇文章的建议/group/maptiler/browse_thread/thread/70a4c5610538332a/42fefedb4a0bc6d2,我尝试使用 gdal2tiles.py 代替,向其传递 -r antialias
选项,但细边框仍然存在。
如果我打开实际生成的图像图块,细边框确实看起来是生成图块的一部分,但它不是原始图像的一部分。
我怀疑正在发生的事情是,当程序生成图块图像文件时,我没有数据的 Google 地图图块部分被视为黑色像素,结果是灰色边框。
以下是我认为来自 gdal2tiles.py 的相关代码:
# Scaling by PIL (Python Imaging Library) - improved Lanczos
array = numpy.zeros((querysize, querysize, tilebands), numpy.uint8)
for i in range(tilebands):
array[:,:,i] = gdalarray.BandReadAsArray(dsquery.GetRasterBand(i+1), 0, 0, querysize, querysize)
im = Image.fromarray(array, 'RGBA') # Always four bands
im1 = im.resize((tilesize,tilesize), Image.ANTIALIAS)
if os.path.exists(tilefilename):
im0 = Image.open(tilefilename)
im1 = Image.composite(im1, im0, im1)
im1.save(tilefilename,self.tiledriver)
知道如何制作它以使边框不存在,而不是在图像编辑器中打开相关生成的图块图像文件并将相关像素设置为透明吗?
我怀疑答案涉及找到某种方法来表示透明像素,以便抗锯齿功能在采样时忽略它们。
更新:它可能不会赢得任何优雅或性能奖项,但我认为我已经做到了这一点。当然,最后几码也是最艰难的。
如果我将 ANTIALIAS 更改为 BICUBIC,然后处理 alpha 通道,使任何半透明像素呈现完全透明,我就消除了大多数图块上的大部分边框。然而,一些浅色边界仍然存在。我不知道该怎么办。还值得注意的是,我猜想如果图像中存在不在实际图像区域边缘之外的透明或半透明像素,则此策略可能不会那么有效。
以下是经过这些修改的代码:
# Scaling by PIL (Python Imaging Library) - improved Lanczos
array = numpy.zeros((querysize, querysize, tilebands), numpy.uint8)
for i in range(tilebands):
array[:,:,i] = gdalarray.BandReadAsArray(dsquery.GetRasterBand(i+1), 0, 0, querysize, querysize)
im = Image.fromarray(array, 'RGBA') # Always four bands
im1 = im.resize((tilesize,tilesize), Image.BICUBIC)
if os.path.exists(tilefilename):
im0 = Image.open(tilefilename)
im1 = Image.composite(im1, im0, im1)
im1AsArray = numpy.array(im1)
alpha = im1AsArray[:,:,3]
semiTransparentIndices = alpha < 255
alpha[semiTransparentIndices] = 0
im1AsArray[:,:,3] = alpha
im1 = Image.fromarray(im1AsArray, 'RGBA')
im1.save(tilefilename,self.tiledriver)
I have a high-resolution image that I want to use as a tiled map overlay using Google Maps API v3.
I used MapTiler to break it into appropriate tiles at the desired zoom levels. That worked well except that there was a thin grey-black border on the tiles that were the edges of the original image.
Following the suggestion of the second post at http://groups.google.com/group/maptiler/browse_thread/thread/70a4c5610538332a/42fefedb4a0bc6d2, I tried using gdal2tiles.py instead, passing it the -r antialias
option but the thin border persisted.
If I open the actual generated image tiles, the thin border does indeed appear to be part of the generated tile, but it is not part of the original image.
I suspect what is happening is that the portions of the Google Maps tile for which I have no data are being treated as black pixels when the program generates the tile image files and the result is the grey border.
Here's what I believe to be the relevant code from gdal2tiles.py:
# Scaling by PIL (Python Imaging Library) - improved Lanczos
array = numpy.zeros((querysize, querysize, tilebands), numpy.uint8)
for i in range(tilebands):
array[:,:,i] = gdalarray.BandReadAsArray(dsquery.GetRasterBand(i+1), 0, 0, querysize, querysize)
im = Image.fromarray(array, 'RGBA') # Always four bands
im1 = im.resize((tilesize,tilesize), Image.ANTIALIAS)
if os.path.exists(tilefilename):
im0 = Image.open(tilefilename)
im1 = Image.composite(im1, im0, im1)
im1.save(tilefilename,self.tiledriver)
Any idea how to make it so that border isn't there, short of opening the relevant generated tile image files in an image editor and setting the relevant pixels to transparent?
I suspect the answer involves finding some way to represent transparent pixels such that antialiasing ignores them for sampling purposes.
Update: It might not win any awards for elegance or performance, but I'm most of the way there, I think. Of course, the final few yards are also the toughest.
If I change ANTIALIAS to BICUBIC and then process the alpha channel such that any semi-transparent pixels are rendered completely transparent, I get rid of most of the borders on most of the tiles. Some light-colored borderlines persist, however. I'm not sure what to do about that. It's also worth noting that I guess this strategy might not work so well if there were transparent or semi-transparent pixels in the image that were not outside the edges of the actual image area.
Here's the code with these modifications:
# Scaling by PIL (Python Imaging Library) - improved Lanczos
array = numpy.zeros((querysize, querysize, tilebands), numpy.uint8)
for i in range(tilebands):
array[:,:,i] = gdalarray.BandReadAsArray(dsquery.GetRasterBand(i+1), 0, 0, querysize, querysize)
im = Image.fromarray(array, 'RGBA') # Always four bands
im1 = im.resize((tilesize,tilesize), Image.BICUBIC)
if os.path.exists(tilefilename):
im0 = Image.open(tilefilename)
im1 = Image.composite(im1, im0, im1)
im1AsArray = numpy.array(im1)
alpha = im1AsArray[:,:,3]
semiTransparentIndices = alpha < 255
alpha[semiTransparentIndices] = 0
im1AsArray[:,:,3] = alpha
im1 = Image.fromarray(im1AsArray, 'RGBA')
im1.save(tilefilename,self.tiledriver)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
答案是将重采样更改为 BILINEAR(而不是 BICUBIC,这是我在发布到问题的更新中尝试的),然后确保将任何半透明像素更改为完全透明像素。
正如我在更新中所说,我在这里所做的代码修改可能不会赢得任何优雅或性能奖项,但它确实有效。以下是 gdal2tiles.py 中原始发布的代码片段需要更改为:
另请注意,仅当您向 gdal2tiles.py 传递
-r antialias
标志时,上述代码才会执行。是的,没错:我们更改了-r antialias
代码,使其不进行抗锯齿。但如果您遇到了我所遇到的问题并且只是想要一个解决方案,那就是。The answer is to change the resampling to BILINEAR (and not BICUBIC, which is what I tried in the Update posted to the question), and then make sure to change any semitransparent pixels to completely transparent pixels.
As I said in the Update, the code modifications I made here might not win any awards for elegance or performance, but it works. Here's what the original posted snippet from gdal2tiles.py needs to be changed to:
Note also that the above code will only execute if you pass gdal2tiles.py the
-r antialias
flag. Yes, that's right: We changed the-r antialias
code so that it doesn't antialias. But if you're having the problem I was having and just want a solution, there it is.