簡體   English   中英

Geopandas + rasterio:將矢量隔離為png

[英]Geopandas + rasterio : isolate a vector as png

我正在嘗試將城市的邊界隔離為 png 的單個部分。 我的目標是將這個 png 疊加到非常古老的衛星照片上。

為此,我收集了一個復制照片尺寸的光柵文件和一個帶邊界的矢量文件。 然后,我使用了光柵:

import rasterio
from rasterio.plot import show

src = rasterio.open("my_raster.tiff")

和 geopandas 的等價物:

import geopandas as gpd

GDF = gpd.read_file("boundary.shp")

我檢查了 src 和 GDF 之間的坐標參考系是否完全相同,然后我使用 matplotlib 正確放置邊界:

import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(20, 10))
show(src.read(), transform=src.transform, ax=ax)
GDF.plot(ax=ax, color='white')
plt.show()

這表明:

光柵+矢量邊界

效果很好,但我不能用 savefig() 只保存 png 中的邊界。 我試圖將 ax 分開,用 ax1 表示光柵,用 ax2 表示矢量,但它沒有用......

我可以只保存圖的這一部分嗎?

好的,經過一番搜索,我保存了我的 plot 如下:

import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(20, 10))
show(src.read(), transform=src.transform, ax=ax)
GDF.plot(ax=ax, color='#fff')
ax.set_axis_off()
fig.savefig("test.png", dpi=220, bbox_inches = 'tight')
plt.show()

然后,我在一點 function 中使用了 PIL:

from PIL import ImageTk, Image

def only_boundary(image):
    # first, convert picture as RGBA
    with Image.open(image).convert("RGBA") as img:
        pixels = img.load()
        for i in range(img.size[0]):
            for j in range(img.size[1]):
                # if a pixel is not white...
                if pixels[i,j] != (255, 255, 255,255):
                    #it becomes transparent
                    pixels[i,j] = (0, 0, 0, 0)
    # then the loops are over, we save
    im = img.save(image)

only_boundary("test.png") 保存了好結果!

我們可以通過使用 OpenCV 輪廓使方法更清晰。

myfilter='example'
myfilter_raster=os.path.join(raster_path,myfilter+'.tif')
with rasterio.open(myfilter_raster) as src:    
vector_df=gdf_rbb[gdf_rbb.idarpt==myfilter].copy()

out_image, out_transform = rasterio.mask.mask(src, vector_df.geometry.to_list(), crop=False)
out_meta = src.meta        

out_meta.update({"driver": "PNG",
              "height": out_image.shape[1],
              "width": out_image.shape[2],
              "transform": out_transform})

out_file=myfilter+'.png'
out_file=os.path.join(mask_images_path,out_file)
print('Generated' ,out_file)

mask =  out_image[0].astype("uint8")
mask[mask > 0] = 255

border = cv2.copyMakeBorder(mask, 1, 1, 1, 1, cv2.BORDER_CONSTANT, value=0 )
contours, hierarchy = cv2.findContours(border, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE, offset=(-1, -1))

boundary_image=np.zeros(mask.shape)
for contour in contours:
    cv2.drawContours(boundary_image,[contour],0,(255,255,255),3)
plt.imshow(boundary_image)
plt.show()

with rasterio.open(out_file, 'w', **out_meta) as dst:
    dst.write(boundary_image , 1)

# from rasterio.plot import show
# fig, ax = plt.subplots(figsize=(20, 10))
# show(src.read(), transform=src.transform, ax=ax)
# vector_df.plot(ax=ax, color='white')
# plt.show()

使用 opencv 邊緣檢測的另一種簡單方法。

myfilter='example'
myfilter_raster=os.path.join(raster_path,myfilter+'.tif')
with rasterio.open(myfilter_raster) as src:    
    vector_df=gdf_rbb[gdf_rbb.idarpt==myfilter].copy()
    
    out_image, out_transform = rasterio.mask.mask(src, vector_df.geometry.to_list(), crop=False)
    out_meta = src.meta        
   
    out_meta.update({"driver": "PNG",
                  "height": out_image.shape[1],
                  "width": out_image.shape[2],
                  "transform": out_transform})
    
    out_file=myfilter+'2.png'
    out_file=os.path.join(mask_images_path,out_file)
    print('Generated' ,out_file)

    mask =  out_image[0].astype("uint8")
    mask[mask > 0] = 255

    edges = cv2.Canny(mask,100,200)
    plt.subplot(121)
    plt.axis('off')
    plt.imshow(mask,cmap = 'gray')
    plt.title('Original Image')
    plt.subplot(122),
    plt.imshow(edges,cmap = 'gray')
    plt.title('Edge Image')
    plt.show()
    
    with rasterio.open(out_file, 'w', **out_meta) as dst:
        dst.write(edges , 1)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM