Избавление от тонкой границы на краю с прозрачностью при сглаживании с помощью библиотеки изображений Python - PullRequest
4 голосов
/ 13 мая 2011

У меня есть изображение с высоким разрешением, которое я хочу использовать в качестве наложения мозаичной карты с помощью Google Maps API v3.

Я использовал MapTiler, чтобы разбить его на соответствующие плитки с желаемым уровнем масштабирования. Это сработало хорошо, за исключением того, что на плитках, которые были краями исходного изображения, была тонкая серо-черная рамка.

Следуя предложению второго поста на http://groups.google.com/group/maptiler/browse_thread/thread/70a4c5610538332a/42fefedb4a0bc6d2, Я попытался использовать вместо него gdal2tiles.py, передав ему параметр -r antialias, но тонкая граница сохранилась.

Если я открою фактические сгенерированные фрагменты изображения, то тонкая граница действительно будет являться частью сгенерированного фрагмента, но она не является частью исходного изображения.

Я подозреваю, что происходит то, что части плитки Google Maps, для которых у меня нет данных, обрабатываются как черные пиксели, когда программа генерирует файлы изображений плитки, и в результате получается серая рамка.

Вот то, что я считаю соответствующим кодом из 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, а затем обработаю альфа-канал так, что любые полупрозрачные пиксели будут полностью прозрачными, я избавлюсь от большинства границ на большинстве плиток. Однако некоторые светлые границы сохраняются. Я не уверен, что с этим делать. Стоит также отметить, что я полагаю, что эта стратегия могла бы работать не так хорошо, если бы на изображении были прозрачные или полупрозрачные пиксели, которые не выходили за границы реальной области изображения.

Вот код с этими модификациями:

                # 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 Ответ

1 голос
/ 14 мая 2011

Ответ состоит в том, чтобы изменить ресемплинг на 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, чтобы он не сгорал.Но если у вас есть проблема, с которой я столкнулся, и вы просто хотите решить ее, вот она.

...