好的,我将您的图像保存为"shape.png"
,将包围矩形的GeoJSON保存为"boundaries.json"
。然后我的方法如下:
- 以纬度和经度为单位获取北、东、南和西的限制
- 加载并修剪形状图像以摆脱所有黑色边框,阈值为纯黑色和白色
- 通过查看像素和度数的图像宽度和高度来计算从像素到度数的X和Y缩放比例
- 使用OpenCV的
findContours()
在形状图像中找到顶点
- 将我找到的所有顶点从图像坐标翻译成纬度和经度
- 将这些点写入JSON结果文件。
import cv2
import json
import geojson
import numpy as np
from geojson import Feature, Point, FeatureCollection, Polygon, dump
def getNESWextents(GeoJSONfile):
with open('boundaries.json','r') as datafile:
data = json.load(datafile)
feature_collection = FeatureCollection(data['features'])
lats = []
lons = []
for feature in data['features']:
coords = feature['geometry']['coordinates']
lons.append(coords[0])
lats.append(coords[1])
Nextent = max(lats)
Sextent = min(lats)
Wextent = min(lons)
Eextent = max(lons)
return Nextent, Eextent, Sextent, Wextent
def loadAndTrimImage(imagefilename):
"""Loads the named image and trims it to the extent of its content"""
im = cv2.imread(imagefilename,cv2.IMREAD_UNCHANGED)
alpha = im[...,3]
y_nonzero, x_nonzero = np.nonzero(alpha)
res = alpha[np.min(y_nonzero):np.max(y_nonzero), np.min(x_nonzero):np.max(x_nonzero)]
_, res = cv2.threshold(res, 64, 255, cv2.THRESH_BINARY)
return res
def getVertices(im):
"""Gets the vertices of the shape in im"""
_, contours, *_ = cv2.findContours(im, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
perim = cv2.arcLength(contours[0], True)
approx = cv2.approxPolyDP(contours[0], 0.01 * perim, True)
print(f'DEBUG: Found shape with {approx.shape[0]} vertices')
return approx
if __name__ == "__main__":
Nextent, Eextent, Sextent, Wextent = getNESWextents('boundaries.json')
print(f'DEBUG: Nextent={Nextent}, Eextent={Eextent}, Sextent={Sextent}, Wextent={Wextent}')
im = loadAndTrimImage('shape.png')
print('DEBUG: Trimmed image is "trimmed.png"')
cv2.imwrite('trimmed.png', im)
Hpx, Wpx = im.shape
Hdeg, Wdeg = Nextent-Sextent, Eextent-Wextent
degppEW = Wdeg/Wpx
degppNS = Hdeg/Hpx
print(f'DEBUG: degppEW={degppEW}, degppNS={degppNS}')
features = []
vertices = getVertices(im)
for i in range(vertices.shape[0]):
x, y = vertices[i,0]
lon = Wextent + x*degppEW
lat = Nextent - y*degppNS
print(f'DEBUG: Vertex {i}: imageX={x}, imageY={y}, lon={lon}, lat={lat}')
point = Point((lon,lat))
features.append(Feature(geometry=point, properties={"key":"value"}))
featureCol = FeatureCollection(features)
with open ('result.json', 'w') as f:
dump(featureCol, f)
这里是裁剪后的图片:
![图片描述在此输入](https://istack.dev59.com/2mxos.webp)
这里是调试输出:
DEBUG: Nextent=44.66828662253787, Eextent=8.348579406738281, Sextent=44.63507036301143, Wextent=8.305320739746094
DEBUG: Trimmed image is "trimmed.png"
DEBUG: degppEW=8.634464469498503e-05, degppNS=6.0503204966194347e-05
DEBUG: Found shape with 6 vertices
DEBUG: Vertex 0: imageX=211, imageY=2, lon=8.323539459776736, lat=44.668165616127936
DEBUG: Vertex 1: imageX=2, imageY=224, lon=8.305493429035483, lat=44.654733904625445
DEBUG: Vertex 2: imageX=81, imageY=472, lon=8.312314655966388, lat=44.63972910979383
DEBUG: Vertex 3: imageX=374, imageY=548, lon=8.337613636862018, lat=44.63513086621639
DEBUG: Vertex 4: imageX=500, imageY=392, lon=8.348493062093587, lat=44.64456936619112
DEBUG: Vertex 5: imageX=484, imageY=155, lon=8.347111547778466, lat=44.65890862576811