如何将JPG格式地图转为适配geom_polygon/geom_sf的data.frame并提取瓦片边界?
绝对可以用R搞定这个需求!我来一步步给你拆解怎么做:
一、先给你吃颗定心丸:R完全适合做这件事
R有一堆专门处理图像、空间数据和可视化的包——比如magick处理图片、sf/sp处理空间多边形、ggplot2用来画你需要的choropleth map,整套流程完全能在R里闭环完成,不用切换其他工具。
二、具体操作步骤
1. 准备工作:安装并加载所需包
先把要用的包装上:
install.packages(c("magick", "sf", "ggplot2", "tesseract")) library(magick) library(sf) library(ggplot2) library(tesseract)
2. 图片预处理:突出瓦片边界
首先读取你的JPG,然后做灰度转换、二值化,让瓦片的边界更清晰,方便后续识别:
# 读取你的瓦片地图 img <- image_read("你的瓦片地图.jpg") # 预处理:转灰度+二值化,把边界和瓦片区域区分开 # 阈值可以根据你的图片调整,直到边界清晰 img_processed <- img %>% image_convert(colorspace = "gray") %>% image_threshold(type = "white", threshold = "50%")
3. 提取瓦片的多边形边界
用magick识别图片里的连通区域(每个瓦片就是一个独立的连通区域),然后转成sf格式的多边形:
# 识别所有连通区域(每个区域对应一个瓦片) components <- image_connected_components(img_processed) # 把识别到的形状转成sf多边形对象 tile_polygons <- components$shapes %>% st_as_sf(coords = c("x", "y"), crs = 4326) %>% # 先设临时坐标系,后续可调整 st_cast("POLYGON") # 注意:magick的坐标原点在左上角,ggplot的原点在左下角,需要翻转y轴匹配 img_height <- image_info(img)$height tile_polygons <- tile_polygons %>% mutate(y = img_height - y) %>% st_set_geometry(st_sfc(lapply(st_geometry(tile_polygons), function(poly) { poly_coords <- poly[[1]] poly_coords[,2] <- img_height - poly_coords[,2] st_polygon(list(poly_coords)) })))
4. 匹配瓦片编号
如果图片里的编号是可识别的文字,用tesseract做OCR提取;如果编号是你已知的,也可以手动赋值:
# OCR提取每个瓦片的编号 tile_polygons$tile_id <- sapply(components$bbox, function(bbox) { # 裁剪出单个瓦片区域 tile_crop <- image_crop(img, paste0(bbox$width, "x", bbox$height, "+", bbox$x, "+", bbox$y)) # 识别编号并去除多余空格 ocr(tile_crop) %>% trimws() })
5. 转成geom_polygon/geom_sf可用的格式
- 给
geom_sf用:直接用上面生成的tile_polygons这个sf对象就行,画图时直接调用:ggplot() + geom_sf(data = tile_polygons, aes(fill = tile_id)) + # 这里fill可以换成你的数据列 theme_minimal() - 给
geom_polygon用:需要把sf对象转成长格式的data.frame,包含x、y、分组(每个瓦片的id):tile_df <- tile_polygons %>% st_coordinates() %>% as.data.frame() %>% rename(x = X, y = Y, group = L1) %>% left_join(tile_polygons %>% st_drop_geometry(), by = c("group" = "tile_id")) # 画图示例 ggplot(tile_df, aes(x = x, y = y, group = group, fill = tile_id)) + geom_polygon(color = "black") + theme_minimal()
三、一些小Tips
- 如果瓦片边界识别不准,可以试试
image_morphology做膨胀/腐蚀操作,优化预处理后的图片; - 坐标系如果不需要地理信息,用平面坐标系(比如3857)就行,不用纠结真实地理CRS;
- OCR识别率低的话,可以先对裁剪后的瓦片图做对比度增强,或者指定tesseract的语言包(比如
tesseract_download("eng"))。
内容的提问来源于stack exchange,提问作者Deen24ID
相关产品推荐
相关产品推荐

