99999久久久久久亚洲,欧美人与禽猛交狂配,高清日韩av在线影院,一个人在线高清免费观看,啦啦啦在线视频免费观看www

熱線電話:13121318867

登錄
首頁(yè)大數(shù)據(jù)時(shí)代【CDA干貨】Python 提取 TIF 中地名的完整指南
【CDA干貨】Python 提取 TIF 中地名的完整指南
2025-09-17
收藏

Python 提取 TIF 中地名的完整指南

一、先明確:TIF 中的地名有哪兩種存在形式?

在開(kāi)始提取前,需先判斷 TIF 文件的類型 —— 這直接決定了后續(xù)的技術(shù)方案。兩種核心形式的差異如下:

地名存在形式 適用 TIF 類型 核心特征 提取思路
地理矢量屬性字段 GeoTIFF(帶地理空間信息) 地名存儲(chǔ)在矢量要素的屬性表中(如 Shapefile 關(guān)聯(lián)的 “NAME” 字段),TIF 本身是柵格底圖,地名不直接顯示在圖像上 讀取 TIF 的地理元數(shù)據(jù)→關(guān)聯(lián)矢量圖層→提取屬性字段中的地名
圖像可視化文字 普通 TIF(如掃描地圖、航拍圖) 地名是圖像像素的一部分(如 “北京市朝陽(yáng)區(qū)” 標(biāo)注文字),無(wú)結(jié)構(gòu)化屬性,需識(shí)別圖像內(nèi)容 圖像預(yù)處理(去噪、灰度化)→OCR 文字識(shí)別→篩選地名

二、場(chǎng)景 1:提取 GeoTIFF 中的矢量屬性地名(結(jié)構(gòu)化數(shù)據(jù))

GeoTIFF 是帶有地理空間參考信息的 TIF 文件,常與矢量數(shù)據(jù)(如 Shapefile、GeoJSON)配套使用 —— 地名通常存儲(chǔ)在矢量要素的屬性表中(如居民點(diǎn)要素的 “NAME” 字段、道路要素的 “ROAD_NAME” 字段)。這種場(chǎng)景下,提取本質(zhì)是 “讀取地理數(shù)據(jù)的屬性信息”,核心依賴 GIS 相關(guān)庫(kù)。

1. 核心工具庫(kù)

  • GDAL/OGR:地理數(shù)據(jù)處理的底層庫(kù),支持讀取 GeoTIFF 的元數(shù)據(jù)及關(guān)聯(lián)的矢量文件;

  • Geopandas:基于 Pandas 的 GIS 擴(kuò)展庫(kù),簡(jiǎn)化矢量數(shù)據(jù)的讀取與屬性篩選,適合處理帶地名的矢量圖層;

  • Fiona:輕量級(jí)矢量數(shù)據(jù)讀取庫(kù),常與 Geopandas 配合使用,支持 Shapefile、GeoJSON 等格式。

2. 前提條件

  • 需獲取與 GeoTIFF 配套的矢量文件(如 Shapefile 格式的.shp文件,通常包含.shp/.shx/.dbf/.prj四個(gè)文件);

  • 矢量文件的屬性表中需包含地名字段(如 “NAME”“地名”“CNAME”,可通過(guò) QGIS、ArcGIS 查看字段名);

  • GeoTIFF 與矢量文件需空間參考一致(如均為 WGS84 坐標(biāo)系),避免空間匹配偏差。

3. 實(shí)戰(zhàn)步驟:提取居民點(diǎn)地名

假設(shè)我們有一份 “某區(qū)域 GeoTIFF 底圖”,配套的residential.shp矢量文件包含居民點(diǎn)要素,屬性表中 “NAME” 字段存儲(chǔ)地名。

步驟 1:安裝依賴庫(kù)

GIS 庫(kù)在 Windows 環(huán)境下直接用pip安裝可能報(bào)錯(cuò),建議用conda(Anaconda/Miniconda)安裝:

# 創(chuàng)建conda環(huán)境(可選)

conda create -n gis_env python=3.9

conda activate gis_env

# 安裝核心庫(kù)

conda install -c conda-forge gdal geopandas fiona pandas

步驟 2:讀取矢量文件并提取地名

import geopandas as gpd

import pandas as pd

# 1. 讀取Shapefile矢量文件(包含居民點(diǎn)要素)

# 注意:需確保.shp/.shx/.dbf/.prj文件在同一目錄

gdf = gpd.read_file("residential.shp")

# 2. 查看矢量數(shù)據(jù)的基本信息(確認(rèn)字段名與地名字段

print("矢量數(shù)據(jù)字段名:", gdf.columns.tolist())  # 輸出如['FID', 'NAME', 'POP', 'geometry']

print("n前5條數(shù)據(jù)的地理類型:", gdf.geom_type.head())  # 確認(rèn)是Point(點(diǎn)要素,對(duì)應(yīng)居民點(diǎn))

# 3. 篩選地名字段,去重并保存

# 提取"NAME"字段中的地名,排除空值和重復(fù)值

place_names = gdf["NAME"].dropna().drop_duplicates().tolist()

# 4. 查看結(jié)果并保存為CSV

print("n提取的地名列表(前10個(gè)):")

print(place_names[:10])  # 輸出如['張三村', '李四鎮(zhèn)', '王五社區(qū)', ...]

# 保存為CSV,便于后續(xù)使用

pd.DataFrame({"地名": place_names}).to_csv("extracted_place_names.csv", index=False, encoding="utf-8")

print("n地名已保存至 extracted_place_names.csv")

步驟 3:(可選)關(guān)聯(lián) GeoTIFF 的空間范圍篩選地名

若需提取 “GeoTIFF 底圖覆蓋范圍內(nèi)” 的地名(排除矢量文件中超出底圖的要素),需先獲取 GeoTIFF 的空間范圍,再篩選矢量要素:

from osgeo import gdal

# 1. 讀取GeoTIFF,獲取其空間范圍(邊界框)

def get_geotiff_bbox(tif_path):

   dataset = gdal.Open(tif_path)

   if not dataset:

       raise ValueError("無(wú)法打開(kāi)GeoTIFF文件")

   # 獲取地理變換參數(shù)(左上角坐標(biāo)、分辨率等)

   geotransform = dataset.GetGeoTransform()

   # 計(jì)算邊界框(min_x, min_y, max_x, max_y)

   min_x = geotransform[0]

   max_y = geotransform[3]

   max_x = min_x + dataset.RasterXSize * geotransform[1]

   min_y = max_y + dataset.RasterYSize * geotransform[5]

   dataset = None  # 關(guān)閉文件

   return (min_x, min_y, max_x, max_y)

# 2. 獲取GeoTIFF的邊界框

tif_bbox = get_geotiff_bbox("region.tif")  # 替換為你的GeoTIFF路徑

min_x, min_y, max_x, max_y = tif_bbox

# 3. 篩選矢量要素中在邊界框內(nèi)的地名

# 創(chuàng)建邊界框的Polygon幾何對(duì)象

from shapely.geometry import box

bbox_geometry = box(min_x, min_y, max_x, max_y)

# 篩選與邊界框相交的居民點(diǎn)要素

gdf_in_bbox = gdf[gdf.intersects(bbox_geometry)]

# 提取地名

place_names_in_bbox = gdf_in_bbox["NAME"].dropna().drop_duplicates().tolist()

print("GeoTIFF范圍內(nèi)的地名數(shù)量:", len(place_names_in_bbox))

print("GeoTIFF范圍內(nèi)的地名(前10個(gè)):", place_names_in_bbox[:10])

三、場(chǎng)景 2:提取普通 TIF 圖像中的文字地名(非結(jié)構(gòu)化數(shù)據(jù))

若 TIF 是普通圖像(如掃描的紙質(zhì)地圖、無(wú)人機(jī)航拍圖),地名是圖像上的可視化文字(如印刷體標(biāo)注),則需通過(guò)OCR(光學(xué)字符識(shí)別) 技術(shù)提取。這種場(chǎng)景的核心是 “將圖像文字轉(zhuǎn)化為文本”,再通過(guò)簡(jiǎn)單篩選得到地名。

1. 核心工具庫(kù)

  • PIL/Pillow:Python 圖像處理庫(kù),用于 TIF 圖像的讀取、預(yù)處理(灰度化、二值化、去噪);

  • EasyOCR:輕量級(jí) OCR 庫(kù),支持多語(yǔ)言(含中文),識(shí)別準(zhǔn)確率高于傳統(tǒng)的 Tesseract,且無(wú)需復(fù)雜配置;

  • OpenCV(可選):用于更復(fù)雜的圖像預(yù)處理(如邊緣檢測(cè)、文字區(qū)域定位),提升 OCR 準(zhǔn)確率。

2. 前提條件

  • TIF 圖像中的地名需清晰可辨(避免模糊、傾斜、遮擋,否則 OCR 準(zhǔn)確率會(huì)大幅下降);

  • 若識(shí)別中文地名,需確保 OCR 庫(kù)已下載中文模型(EasyOCR 會(huì)自動(dòng)下載,首次運(yùn)行需聯(lián)網(wǎng))。

3. 實(shí)戰(zhàn)步驟:OCR 識(shí)別 TIF 中的地名

假設(shè)我們有一份掃描的紙質(zhì)地圖 TIF(scan_map.tif),圖像上有 “XX 路”“XX 鎮(zhèn)” 等地名標(biāo)注。

步驟 1:安裝依賴庫(kù)

# 安裝Pillow和EasyOCR

pip install pillow easyocr opencv-python

步驟 2:圖像預(yù)處理(提升 OCR 準(zhǔn)確率

普通 TIF 圖像可能存在噪聲、顏色干擾,需先預(yù)處理:

  • 灰度化:將彩色圖像轉(zhuǎn)為灰度圖像,減少顏色通道干擾;

  • 二值化:將灰度圖像轉(zhuǎn)為黑白二值圖像,突出文字與背景的對(duì)比;

  • 去噪:去除圖像中的小點(diǎn)、雜色,避免 OCR 誤識(shí)別。

from PIL import Image

import numpy as np

import cv2

def preprocess_tif(tif_path):

   # 1. 讀取TIF圖像(支持多頁(yè)TIF,此處取第一頁(yè))

   img = Image.open(tif_path)

   if img.mode == "CMYK":

       img = img.convert("RGB")  # 處理CMYK格式圖像

   # 轉(zhuǎn)為OpenCV格式(BGR通道)

   img_cv = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)


   # 2. 灰度化

   gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY)


   # 3. 二值化(自適應(yīng)閾值,適合光照不均勻的圖像)

   # THRESH_BINARY_INV:文字為白色,背景為黑色

   thresh = cv2.adaptiveThreshold(

       gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2

   )



   # 4. 去噪( morphological opening,先腐蝕再膨脹)

   kernel = np.ones((2, 2), np.uint8)

   denoised = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=1)


   # 轉(zhuǎn)回PIL圖像,便于后續(xù)OCR

   img_preprocessed = Image.fromarray(cv2.cvtColor(denoised, cv2.COLOR_BGR2RGB))

   return img_preprocessed

# 預(yù)處理TIF圖像

preprocessed_img = preprocess_tif("scan_map.tif")

# 保存預(yù)處理后的圖像(可選,用于檢查效果)

preprocessed_img.save("preprocessed_map.png")

print("預(yù)處理完成,圖像已保存至 preprocessed_map.png")

步驟 3:EasyOCR 識(shí)別文字并篩選地名

OCR 會(huì)識(shí)別圖像中的所有文字(如數(shù)字、符號(hào)、無(wú)關(guān)說(shuō)明),需通過(guò) “地名特征” 篩選(如含 “市”“縣”“鎮(zhèn)”“村”“路”“街” 等關(guān)鍵詞):

import easyocr

def extract_place_names_from_ocr(img):

   # 1. 初始化EasyOCR閱讀器(僅加載中文模型,減少內(nèi)存占用)

   # lang_list=["ch_sim"]:中文簡(jiǎn)體,如需英文可加["en"]

   reader = easyocr.Reader(lang_list=["ch_sim"], gpu=False)  # gpu=True需安裝CUDA


   # 2. 識(shí)別圖像文字(返回結(jié)果:[(文字區(qū)域坐標(biāo), 文字內(nèi)容, 置信度)])

   result = reader.readtext(np.array(img))


   # 3. 篩選地名:保留含地名關(guān)鍵詞的文字,且置信度>0.5(過(guò)濾低準(zhǔn)確率結(jié)果)

   place_keywords = ["市""縣""區(qū)""鎮(zhèn)""鄉(xiāng)""村""社區(qū)""路""街""巷""大道"]

   place_names = []

   for bbox, text, confidence in result:

       if confidence > 0.5 and any(keyword in text for keyword in place_keywords):

           # 去除文字中的空格、換行符

           clean_text = text.strip().replace("n""")

           place_names.append(clean_text)


   # 4. 去重并返回

   return list(set(place_names))  # set去重

# 提取地名

place_names_ocr = extract_place_names_from_ocr(preprocessed_img)

# 查看結(jié)果

print("nOCR提取的地名列表:")

for name in place_names_ocr:

   print(name)  # 輸出如['朝陽(yáng)路', '海淀鎮(zhèn)', '中關(guān)村社區(qū)', ...]

# 保存結(jié)果

import pandas as pd

pd.DataFrame({"OCR提取地名": place_names_ocr}).to_csv("ocr_place_names.csv", index=False, encoding="utf-8")

print("nOCR提取的地名已保存至 ocr_place_names.csv")

步驟 4:優(yōu)化 OCR 準(zhǔn)確率的技巧

若識(shí)別結(jié)果中存在大量錯(cuò)誤(如 “朝陽(yáng)路” 識(shí)別為 “朝陽(yáng)鉻”),可嘗試以下優(yōu)化:

  1. 調(diào)整二值化閾值:若文字模糊,可減小adaptiveThresholdblockSize(如從 11 改為 9);

  2. 文字區(qū)域定位:用 OpenCVfindContours找到文字輪廓,僅對(duì)文字區(qū)域進(jìn)行 OCR,減少背景干擾;

  3. 更換 OCR 庫(kù):若 EasyOCR 效果不佳,可嘗試pytesseract(需安裝 Tesseract 引擎,支持自定義訓(xùn)練模型);

  4. 圖像旋轉(zhuǎn)矯正:若 TIF 圖像傾斜,用cv2.getRotationMatrix2D旋轉(zhuǎn)矯正后再識(shí)別。

四、兩種場(chǎng)景的對(duì)比與選擇建議

對(duì)比維度 場(chǎng)景 1:GeoTIFF 矢量屬性地名 場(chǎng)景 2:普通 TIF 圖像文字地名
數(shù)據(jù)結(jié)構(gòu)化程度 高(地名存儲(chǔ)在屬性表,可直接讀?。?/td> 低(需 OCR 識(shí)別,結(jié)果需篩選)
提取準(zhǔn)確率 近 100%(只要矢量數(shù)據(jù)正確) 中等(受圖像質(zhì)量、OCR 模型影響,通常 70%-95%)
依賴文件 需配套矢量文件(如 Shapefile) 僅需 TIF 圖像本身
核心工具庫(kù) GDAL、Geopandas、Fiona Pillow、EasyOCR、OpenCV
適用場(chǎng)景 GIS 項(xiàng)目、專業(yè)地理數(shù)據(jù)處理 掃描地圖、航拍圖、無(wú)矢量的歷史地圖

選擇建議:

  1. 優(yōu)先確認(rèn) TIF 類型:若 TIF 是從 GIS 軟件導(dǎo)出的 GeoTIFF,先檢查是否有配套矢量文件,優(yōu)先用場(chǎng)景 1 的方法(準(zhǔn)確率高、效率快);

  2. 無(wú)矢量數(shù)據(jù)時(shí)用 OCR:若僅能獲取普通 TIF 圖像(如歷史地圖掃描件),則采用場(chǎng)景 2 的 OCR 方案,需做好圖像預(yù)處理;

  3. 混合場(chǎng)景處理:若 GeoTIFF 底圖上有額外的圖像文字地名(如臨時(shí)標(biāo)注),可結(jié)合兩種方法 —— 先提取矢量屬性地名,再用 OCR 補(bǔ)充圖像文字地名。

五、常見(jiàn)問(wèn)題與解決方案

  1. 問(wèn)題 1:GeoTIFF 無(wú)法關(guān)聯(lián)矢量文件

    原因:兩者空間參考不一致(如 GeoTIFF 是 GCJ02 坐標(biāo)系,矢量是 WGS84)。

    解決方案:用 Geopandasto_crs統(tǒng)一坐標(biāo)系,如gdf = gdf.to_crs(epsg=4326)(轉(zhuǎn)為 WGS84)。

  2. 問(wèn)題 2:TIF 圖像太大,OCR 內(nèi)存溢出

    原因:EasyOCR 處理大圖像(如分辨率 > 5000×5000)時(shí)占用內(nèi)存過(guò)高。

    解決方案:將圖像按網(wǎng)格分割為小塊(如 500×500 像素),分別 OCR 后合并結(jié)果。

  3. 問(wèn)題 3:矢量文件中無(wú)明確的地名字段

    原因:字段名非 “NAME”,可能是 “DZM”“MC” 等中文拼音縮寫。

    解決方案:用gdf.head()查看屬性表內(nèi)容,找到包含地名的字段(如 “DZM” 字段值為 “張三村”)。

六、總結(jié)

Python 提取 TIF 中的地名,核心是 “根據(jù) TIF 文件類型選擇對(duì)應(yīng)技術(shù)路徑”—— 對(duì)于結(jié)構(gòu)化的 GeoTIFF 矢量數(shù)據(jù),利用 GIS 庫(kù)直接讀取屬性字段是最優(yōu)解;對(duì)于非結(jié)構(gòu)化的圖像文字,通過(guò) “預(yù)處理 + OCR” 是唯一可行方案。無(wú)論哪種場(chǎng)景,都需關(guān)注數(shù)據(jù)質(zhì)量(矢量數(shù)據(jù)完整性、圖像清晰度)與工具庫(kù)適配(GIS 庫(kù)的空間參考、OCR 庫(kù)的語(yǔ)言模型)。掌握這兩種方法,可覆蓋絕大多數(shù) TIF 地名提取需求,為地理信息分析、地圖數(shù)字化等工作提供數(shù)據(jù)支撐。

推薦學(xué)習(xí)書(shū)籍 《CDA一級(jí)教材》適合CDA一級(jí)考生備考,也適合業(yè)務(wù)及數(shù)據(jù)分析崗位的從業(yè)者提升自我。完整電子版已上線CDA網(wǎng)校,累計(jì)已有10萬(wàn)+在讀~ !

免費(fèi)加入閱讀:https://edu.cda.cn/goods/show/3151?targetId=5147&preview=0

數(shù)據(jù)分析師資訊
更多

OK
客服在線
立即咨詢
客服在線
立即咨詢
') } function initGt() { var handler = function (captchaObj) { captchaObj.appendTo('#captcha'); captchaObj.onReady(function () { $("#wait").hide(); }).onSuccess(function(){ $('.getcheckcode').removeClass('dis'); $('.getcheckcode').trigger('click'); }); window.captchaObj = captchaObj; }; $('#captcha').show(); $.ajax({ url: "/login/gtstart?t=" + (new Date()).getTime(), // 加隨機(jī)數(shù)防止緩存 type: "get", dataType: "json", success: function (data) { $('#text').hide(); $('#wait').show(); // 調(diào)用 initGeetest 進(jìn)行初始化 // 參數(shù)1:配置參數(shù) // 參數(shù)2:回調(diào),回調(diào)的第一個(gè)參數(shù)驗(yàn)證碼對(duì)象,之后可以使用它調(diào)用相應(yīng)的接口 initGeetest({ // 以下 4 個(gè)配置參數(shù)為必須,不能缺少 gt: data.gt, challenge: data.challenge, offline: !data.success, // 表示用戶后臺(tái)檢測(cè)極驗(yàn)服務(wù)器是否宕機(jī) new_captcha: data.new_captcha, // 用于宕機(jī)時(shí)表示是新驗(yàn)證碼的宕機(jī) product: "float", // 產(chǎn)品形式,包括:float,popup width: "280px", https: true // 更多配置參數(shù)說(shuō)明請(qǐng)參見(jiàn):http://docs.geetest.com/install/client/web-front/ }, handler); } }); } function codeCutdown() { if(_wait == 0){ //倒計(jì)時(shí)完成 $(".getcheckcode").removeClass('dis').html("重新獲取"); }else{ $(".getcheckcode").addClass('dis').html("重新獲取("+_wait+"s)"); _wait--; setTimeout(function () { codeCutdown(); },1000); } } function inputValidate(ele,telInput) { var oInput = ele; var inputVal = oInput.val(); var oType = ele.attr('data-type'); var oEtag = $('#etag').val(); var oErr = oInput.closest('.form_box').next('.err_txt'); var empTxt = '請(qǐng)輸入'+oInput.attr('placeholder')+'!'; var errTxt = '請(qǐng)輸入正確的'+oInput.attr('placeholder')+'!'; var pattern; if(inputVal==""){ if(!telInput){ errFun(oErr,empTxt); } return false; }else { switch (oType){ case 'login_mobile': pattern = /^1[3456789]\d{9}$/; if(inputVal.length==11) { $.ajax({ url: '/login/checkmobile', type: "post", dataType: "json", data: { mobile: inputVal, etag: oEtag, page_ur: window.location.href, page_referer: document.referrer }, success: function (data) { } }); } break; case 'login_yzm': pattern = /^\d{6}$/; break; } if(oType=='login_mobile'){ } if(!!validateFun(pattern,inputVal)){ errFun(oErr,'') if(telInput){ $('.getcheckcode').removeClass('dis'); } }else { if(!telInput) { errFun(oErr, errTxt); }else { $('.getcheckcode').addClass('dis'); } return false; } } return true; } function errFun(obj,msg) { obj.html(msg); if(msg==''){ $('.login_submit').removeClass('dis'); }else { $('.login_submit').addClass('dis'); } } function validateFun(pat,val) { return pat.test(val); }