使用Python Image Library进行抗锯齿时,使用透明度去除边缘处的细边框

时间:2011-05-13 01:08:31

标签: python image image-processing image-manipulation 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)

任何想法如何使边框不存在,没有在图像编辑器中打开相关生成的平铺图像文件并将相关像素设置为透明?

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

更新:它可能不会因为优雅或性能而赢得任何奖项,但我认为我的大部分都在那里。当然,最后几码也是最难的。

如果我将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)

1 个答案:

答案 0 :(得分:1)

答案是将重新采样更改为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)

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