使用 Python 图像库进行抗锯齿时,使用透明度去除边缘的细边框

Tro*_*ott 6 python image-manipulation image image-processing python-imaging-library

我有一个高分辨率图像,我想使用 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)
Run Code Online (Sandbox Code Playgroud)

知道如何使它不存在边框,而不是在图像编辑器中打开相关生成的平铺图像文件并将相关像素设置为透明吗?

我怀疑答案涉及找到某种方法来表示透明像素,以便抗锯齿出于采样目的而忽略它们。

更新:它可能不会因优雅或性能而获得任何奖项,但我认为我已经做到了。当然,最后几码也是最艰难的。

如果我将 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)
Run Code Online (Sandbox Code Playgroud)

Tro*_*ott 2

答案是将重采样更改为 BILINEAR(而不是 BICUBIC,这是我在发布到问题的更新中尝试的),然后确保将任何半透明像素更改为完全透明像素。

正如我在更新中所说,我在这里所做的代码修改可能不会赢得任何优雅或性能奖项,但它确实有效。以下是 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.BILINEAR)
            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)
Run Code Online (Sandbox Code Playgroud)

另请注意,仅当您传递 gdal2tiles.py 标志时,上述代码才会执行-r antialias​​。是的,没错:我们更改了-r antialias代码,使其不具有抗锯齿功能。但如果您遇到了我所遇到的问题并且只是想要一个解决方案,那就是。