AI、Python與手工業,我們如何處理台灣+日本超過400張共軍軌跡圖?

報導者 The Reporter
報導者開放實驗室
20 min readOct 27, 2023

--

文/《報導者》Data小組記者柯皓翔、簡毅慧

國慶連假結束之際,《報導者》推出「中國虎視下的島鏈」系列專題,其中多媒體篇是由Data小組(皓翔、毅慧)、記者許詩愷、PM洪琴宣、設計師江世民共同製作。我們綜合國防部、日本防衛省資料,整併自2022年8月以來的共軍活動軌跡圖,觀察2022年美國眾議院議長裴洛西訪台後,共軍如何以「切香腸戰術」日益進逼台灣。

過去3年來,國內新聞同業如《天下雜誌》、《公視》皆曾製作相關專題,此次《報導者》的〈【圖解】解放軍如何進逼第一島鏈:台海衝突下牽動的美日軍事布局〉,除了更新最近一年的共軍動向,也進一步呈現日方數據及第一島鏈上的變化。

製作的首要困難點在於自動化批量處理,原因是台灣上百張軌跡圖存在細節差異,圖片之間的標題欄資訊不同、地圖範圍不同、浮水印和經緯度標示也不同,再加上軌跡線段與其他資訊交錯,很難只透過顏色辨識就把軌跡自動取出。

我們最後採用半自動化的方式,手工繪製共軍飛行軌跡,並結合Python、ChatGPT的Code Interpreter、Figma、QGIS等工具完成作品。

本文將分為5大部分,並針對台、日資料處理分別說明:

  • PART1、透過爬蟲抓取上百份新聞稿
  • PART2、資料前處理:透過影像辨識切除邊界
  • PART3、有溫度的資料集:終究要面對的手工業,以Figma描圖、將軌跡轉為地理圖資
  • PART4、資料視覺化,從中尋找洞見
  • PART5、用AE製作軌跡動畫

我們分享反覆試錯後歸納出的完整流程及心得,讓未來想整理國防部、日本防衛省軌跡圖資的朋友參考。

本篇數位專題的製作,橫跨爬蟲、影像辨識、人工描圖、GIS分析、動畫製作、腳本撰寫等環節

PART1、透過爬蟲抓取上百份新聞稿

Data小組透過Python批量收集2022年8月1日至2023年8月31日,台灣及日本官方所公開的解放軍活動軌跡,觀察其樣態變化。

不過我們須先留意資料限制:軌跡部分,台灣國防部僅發布進入西南空域或逾越海峽中線的共機資料,船艦軌跡則未例行公布;日本防衛省資料則包含共艦與共機,不過觸及範圍以日本相關海域為準,因此如台灣海峽的船艦活動軌跡,團隊未能取得完整資料集。

具體來說,本次報導中使用的解放軍活動軌跡來自台灣國防部日本防衛省統合幕僚監部,以下將分別敘述兩者資料收集方法。

台灣國防部:

首先,國防部公布的資料可在「即時軍事動態」頁面找到,該頁面最早一筆公開的資料可回溯至2020年9月17日。

經觀察,我們判斷頁面資料需透過下列步驟獲取:

1. 點擊各日連結後,可查看具體活動動態;若想取得「當天共機、共艦總架次」,可從此處獲取。

2. 該頁面的「下載專區」通常提供兩張圖檔,分別是將上述描述「圖片化」的版本,以及「地圖軌跡檔」;後者包含共機類型、數量、地理位置等訊息。

3. 不過2020年至今,地圖圖檔格式也曾歷經變化:

a. 2022年8月6日後公布的資料,國防部直接提供地圖的JPG圖檔,下載檔案相對直接單純。

b. 但此前的資料,則是打包在官方的PDF檔中(第1頁為文字;若有第2頁則為地圖;第3頁以後可能有機型照片)。我們因此後續還要把PDF檔內容轉存為JPG。

4. 我們的思路是透過Python進行批量操作:先從索引頁點擊各日連結,接著在各日頁面中下載文字檔及多媒體檔案;然而,我們可以注意到各日頁面網址不變,如果直接訪問該網址,只會得到一種結果。

將滑鼠游標移到連結上,可以看到左下角的連結網址為一段javascript的語法;也就是說,各日資料的呈現其實是透過點擊行為觸發javascript腳本後生成。對於這樣網站邏輯,我們使用Selenium進行爬蟲,並透過Beautifulsoup將網頁標題、內容結構化。

5. 經結構化的資料,除了方便製作團隊進行資訊查證外,也能比對不同時間是否出現寫法的變化。

6. 多媒體檔案下載下來後,可能有JPG、PDF各種檔案格式,由於部分軌跡藏身PDF中,我們因此要進行檔案轉換。

a. 我們設定以下邏輯:「先確認檔案是否為PDF檔 → PDF檔至少有兩頁 → 將第二頁內容儲存為JPG檔」。

b. 上述邏輯,可使用PyPDF2函式庫的PDFReader模組讀取PDF檔;pdf2image函式庫的convert_from_path模組則讓我們將其轉存為圖片

到這一步為止,我們已經備妥所有的軌跡JPG圖檔,可以進行後續細緻處理。

日本防衛省:

日本方面,資料可以在防衛省統合幕僚監部的新聞稿專區取得。(註:亦可自活動情報 > 國內情報下載)以下分述詳細步驟:

1. 進行資料篩選:從新聞稿頁中,我們可以發現日方公布資料包含中國及俄國的機、艦活動資料,不過同時也有許多與本次主題較無關的資訊。

為方便篩選,我們首先將所有的資料複製起來,貼至Google Sheet,接著偵測各篇標題是否包含以下日文關鍵字:中国、ロシア(即俄國)、米(意即美國)、機、艦,我們即可透過篩選器收斂範圍。

同時,我們也取出每個連結的url,這些網址都將直接導向活動報告(PDF檔),裡頭詳載活動資訊、地圖及機型照片。

透過標題偵測關鍵字,記者可以快速篩選出共機、共艦報告

2. 抓取地圖圖檔:由於是PDF格式,我們同樣參考台灣的方法論,將PDF統一轉換為PNG圖檔。觀察每份PDF的邏輯,我們可發現第1頁是動向簡介,但是軌跡地圖與機型照片的出現位置不定,有時在最後一頁、有時在第二頁。

但是其中仍有規則可循 — — 出現地圖的頁面,一定會出現標題「行動概要」四字,這也成為我們的定位依據,只要PDF頁面出現該詞,我們就把該頁另存為PNG檔。

我們同時還在PNG圖檔上壓上日期,以便後續資料查證與對應。

3. 資料補全:專題製作過程中,我們注意到少數活動事件並未公布在上述新聞稿專區中,例如2023年6月8日中國測量艦曾進入日本領海,這類資訊公布在「お知らせ」頁面中,這部分則需人工補全資料。

至此,日本軌跡圖檔也已備妥。

PART2、資料前處理:透過影像辨識切除邊界

觀察我們已下載的JPG/PNG圖檔,會發現各檔案可能存在長、寬尺寸不一,甚至比例不一致的情形,另外因為部分資料是從PDF轉來,也包含了許多「白邊」。

為了方便後續批量處理,我們須進一步將檔案格式標準化,當務之急是找到不同圖檔間的共通性。以下同樣分別從台、日兩份資料集說明。

台灣:底圖範圍一致,但圖片尺寸、白邊不一

各日軌跡圖的製圖規則可能存在差異

觀察國防部歷年公布的軌跡資料,我們可注意到以下特徵:地圖的四個邊界基本上是相同的;地圖上方的標題區字級大小不一,高度也不一,應予以切除。具體處理步驟如下:

1. 找到圖檔中最大矩形:我們由大到小進行圖片的收斂,只先留下包含標題及地圖的部分,其餘白邊通通切除。

但程式碼該怎麼寫呢?由於製作期間正值ChatGPT興起,我們使用code interpreter功能上傳圖片,逐步形容偵測條件、最後調試出最佳方法 — — 「我想要取出這張圖片的最大矩形,他們是由黑色的邊框所構成」。

ChatGPT也提供我們相當好用的程式碼,大致分為以下步驟:

(1) 導入圖片處理函式庫Pillow(PIL Fork)的Image、ImageDraw、ImageFont等模組,我們可以對圖片進行裁切(cropping)、比例調整(resizing)、壓字等功能。

(2) 導入openCV函式庫的cv2模組,進行影像特徵的檢測

(3) 先將影像轉換為灰階,接著以灰度低於50者,判定為黑色

(4) 分別找到圖片X、Y兩軸方向,黑色坐標出現的最大值與最小值,這四個位置即是我們目標的最大矩形,只保留此範圍資料。

至此,我們已經有切除白邊的圖檔。

2. 切除標題:我們最原始的想法,是希望可以透過影像辨識,找到畫面中由上而下的「第二條水平線」,不過經過測試後才意識到,由於黑框存在粗度,實際電腦在判斷時,線條不只是兩條、而可能存在10幾條之多。

經過反覆測試,我們採用的方法是 — — 鎖定圖片右上角(右側為15%範圍、上方20%範圍)範圍,找出最低的一條黑色水平線,以保留該線下方的內容;如此一來可避開圖片中其他黑框的干擾。

技術面則會用到cv2中的霍夫變換(Hough Transform)偵測直線及Canny邊緣檢測法

3. 重新調整圖片尺寸及比例:當我們將圖片裁切完成時,由於原始圖片長寬像素並不一致,我們觀察多張圖片後,決定將圖片大小統一調整為1080*715px,這樣的長寬比例與原始圖片相當。

4. 壓上日期:由於切除標題後,也順帶把地圖的時間戳記也捨棄了,為方便檔案管理及查核,我們重新在地圖上標示日期。

以上步驟完成後,所有地圖圖檔基本上皆已標準化。我們2023年7月漢光演習報導中,即以國防部圖片為基底,簡單後製出一支影片,不同影格切換時,也不至於因為尺寸差異出現嚴重「抖動」現象。

日本:幅員相對廣,須細分地圖範圍

切除邊界、將多張圖片標準化的主要目的是為了讓後續「萃取軌跡經緯度」這件事可以批次處理。不過觀察日本資料後,較具「批次處理」潛力的資料圍繞在共艦資料,有相當比例都採用同種投影。

這類地圖的特徵是:上方有較粗的黑色框線包裹著「行動概要」文字,下方則為黑色細框包裹的地圖。

經反覆測試,由於圖片複雜度高,部分圖片還可能出現一塊塊的矩形註解,我們最終採用的邏輯,是分別取得四條邊界範圍:

1. 左側邊界:在圖片左側50%範圍,從左到右開始偵測垂直黑線,該黑線的長度必須超過圖片高度的一半。如此可確保我們不會抓到「行動概要」的邊框。

2. 右側邊界:同上,在圖片右側50%範圍,從右到左開始偵測垂直黑線,該黑線的長度必須超過圖片高度的一半。

3. 上方邊界:在圖片上方50%範圍,從上而下偵測前20條水平黑線,將這20條黑線進行分群,第一群即第二群即屬於「行動概要」的框線,應予以排除,故選擇第三群的第一條水平線為基準。

4. 下方邊界:在圖片下方50%範圍,從下而上偵測水平黑線,該黑線的長度必須超過圖片寬度的一半。

5. 保留上述邊界內圖片範圍、將圖片尺寸比例統一為1333*1300px,即已將這些圖片標準化。

PART3、有溫度的資料集:終究要面對的手工業,以Figma描圖、將軌跡轉為地理圖資

在獲得邊界一致的軌跡圖資料集後,接下來就是要萃取出所有圖片中的軌跡,並將這些軌跡的資訊同步做紀錄,包含日期、機型、架次等。我們試過用Python做顏色辨識、形狀辨識或縮小範圍萃取軌跡,但因為難以找到所有圖片間的規律,最後都以失敗告終。

我們想到近年《天下雜誌》數位敘事小組曾以共機軌跡為數據基底製作專題並對外分享製作心法、軍事分析師Damien Symon也會定期發布共機軌跡圖,因此我們分別諮詢《天下》工程師Steven和Symon,了解他們的製作流程,並依照我們自己的需求進行調整:

1. 描圖:我們參考《天下》做法,將圖片批量放上設計軟體Figma,一個Frame放一張圖,再使用鋼筆工具描繪所有軌跡(為維持方向性,應由箭頭底部描向頭部)。我們希望這些軌跡檔案都能有相對應的機型資訊,因此將一個機型設定為一個圖層,圖層中可能有多條軌跡,並以機型、架次作為該圖層的名稱。

這邊要注意,如果是批量處理圖片的話,可以先在所有圖檔名稱都加上「~visibility」的後綴,在稍晚的處理流程會大有用處。

建議圖層以英文命名,下載後才不會面臨編碼轉換問題

2. 隱藏原始圖、下載為SVG:畫好軌跡後,接下來要做的就是批量下載鋼筆軌跡。如果要隱藏所有Frame的底圖,可以啟動Figma套件「Visiblity」的Hide All功能,一鍵隱藏所有原始圖檔,否則就要一張一張隱藏再下載。

下載SVG時,要記得勾選「Include “id” attribute」,這樣載下來的檔案才會有我們製作的圖層名稱資訊。

做完這步後,基本上就能用Python將SVG裡的機型資訊提取出來做資料清洗了,我們命名圖層時使用的是繁體中文,因此輸出成SVG時會面臨編碼轉換的問題,雖然還是可以找尋規則對照回去,但還是建議圖層命名時以英文名稱為主。

如果只是單一呈現某單位發布的機型軌跡資料,那到這步已經很夠用。只是我們希望結合國防部、日本防衛省、美軍基地等相當多來源的圖資,若每種圖資的投影系統不同,直接合併可能會出現偏移、不夠準確的問題,因此需要進一步將SVG向量檔轉為帶有地理資訊的GeoJSON檔。

3. 原始圖檔空間對位(Georeferencing):圖檔做過前處理,因此每張圖檔的邊界都是一樣的,我們要先讓程式知道每張圖檔四個角,對應到地圖中的哪個經緯度。《天下》先前對此做了詳細說明,可以參考:共機軌跡怎麼處理?地理圖資後製小祕技:空間對位(Georeferencing)

我們先把一張圖丟進QGIS做空間對位,獲得圖片的Bounding Box(邊界框),獲得邊界資訊後,就可以此為基準,請ChatGPT撰寫程式計算出SVG的每個線段點位對應的經緯度坐標,並將日期、機型資料寫入GeoJSON檔中。

SVG之所以可以轉換成GeoJSON,是因為他們同樣採用「向量圖」的邏輯來繪製圖案。例如一段箭頭的SVG code包含一段<path>的路徑,在透過 “d” 屬性指定參數下、便可建立各種路徑形狀,而我們想做的,正是將這些路徑轉換為坐標值。

此外,這裡有個細節值得留意,我們是依照EPSG:3857坐標系統(Web Mercator)還原軌跡坐標值,並以EPSG:4326(WGS84)儲存經緯度。經測試,這樣的設置所復刻出來的軌跡可與原圖妥善對應。

日本資料的客製化處理

日本方面,我們延續上述方法論,同樣透過Figma進行描圖。然而,日本的資料須進行更多客製化調整,可分為下列三方面。

1. 因應多元的紀錄形式:

台灣是一個圖層對應一個「機型」及「軌跡」;不過日本可能多個機艦共用同一軌跡,我們因此建議以「註解文字框」為圖層基本單位,其下再包含一條或多條軌跡或形狀作為子圖層,在圖層命名上可注意:

  • 同時包含中國、俄國資料:大部分情況下,防衛省是分別公布中國、俄國報告,但也有同時標記的可能 — — 如果今天出現聯合軍演狀況,就可能在同份報告中標示。我們因此在圖層命名時,需要註記是China或Russia。
  • 同時包含新、舊軌跡:防衛省公布船艦位置時,除了最新資料外,也可能包含過去時間點的位置。團隊在人工描繪軌跡時,仍處理所有的資料,但會在圖層標記new、old,以便去除重複資料,亦保留查核彈性。
  • 包含多種圖形:我們在報告中最常見的是「箭頭」,不過日方資料還可能出現「圓點」、「多邊形」、「雙箭頭」等多種可能,亦有可能彼此排列組合,我們因此細分arrow、ellipse、polygon、bidirectional-arrow等標籤,若圖形僅有邊框(未填滿),也給予其-stroke的註記。

這裡為什麼要區分得這麼細?原因是因為我們要將SVG轉換為GeoJSON,而SVG儲存這些圖案的寫法也各不相同,需要分別客製化轉換程式。

2. 因應多種地圖範圍及畫法:上文曾提到,日本由於幅員廣大,各份報告涵蓋的範圍不一,我們在復刻軌跡時,便將資料區分為以下4類:

A. 共艦(地圖邊界一致,可批量處理)

對於此類資料,我們比照台灣方法論,在QGIS中進行空間對位(Georeferencing)後,取得四個頂點的坐標作為參考點,將SVG轉換為GeoJSON。

B. 共艦(地圖範圍不一,但具備經緯度網格,能找到參考點)

此類則須在描繪軌跡之餘,另外再繪製一「參考矩形」(紅框範圍),使矩形的四個端點對齊圖中的經緯度交點,並在圖層名稱中加入經緯度數值。如此一來,我們便可在下載SVG檔後,透過資料清洗篩選出參考點坐標,以進行空間對位。

我們會先根據紅框與Frame(藍框)之間的位置差異,推算出藍框的具體坐標,再由此推算畫布範圍內的軌跡坐標。為什麼不直接只以紅框作為參考點?如果軌跡確實落在紅框內倒不是問題,但如果軌跡落在紅框之外,下載下來的SVG範圍可能跑掉,導致Georeferencing出來的軌跡偏移,故用藍框為範圍是最保險的做法。

C. 共艦(無經緯度網格)

共艦活動範圍可能在日本南方太平洋海域上,防衛省針對此類活動提供的地圖,往往缺少經緯度網格,只有島嶼的輪廓、日本200海浬經濟海域等多邊形界線可作為參考點。我們透過QGIS記錄若干特徵點的坐標值,並用英文字母A、B、C⋯⋯作為代號,加入圖層命名,在最後清資料階段才以數值取代。

處理這類資料時,我們先建立了一份參考點清單,並以英文字母作為代號,方便在Figma的圖層中標示。圖中的坐標是以EPSG:3857坐標系統(Web Mercator)為基準,最終會再轉換為WGS84的經緯度

D. 共機(地圖範圍不一,但具備經緯度網格)

可比照上述B類共艦操作方法處理。

3. 保留資料清洗彈性:為避免上文所提到的SVG下載亂碼問題,我們建議在圖層改以$1$、$2$、$3$等序號id命名,同時在Google Sheet建立對照表及翻譯表,在後續的資料清洗階段,才將文字資訊與軌跡勾稽串連。

PART4、資料視覺化,從中尋找洞見

對我們來說,資料視覺化是內部溝通時非常重要的環節,數據記者要從這些軌跡資料中萃取出重要的洞察,讓文字記者可以藉此與專家學者討論、延伸看到數據背後更關鍵的政策或趨勢。同時,這也是內部團隊凝聚多媒體想像的重要素材。

例如我們在分析台灣資料時,就將國防部軌跡直接放進QGIS,用漸層色呈現趨勢、用線條粗細呈現重點等,以團隊方便討論的形式呈現。

初步梳理資料後,Data小組用於內部溝通時使用的簡報截圖

而在日本方面,這次我們嘗試透過「儀表板」探索資料。當我們想要觀察某個艦型的歷史軌跡時,QGIS雖然有篩選器,但總要重新輸入語法,方便度不如勾選框(checkbox)來得直觀。

考量日方資料複雜度高,我們因此直接透過html網頁建立一簡易儀表板,透過各欄位的勾選來觀察資料。大家可能會好奇,這麼做不會花很多時間嗎?其實這個動作,我們同樣是透過ChatGPT來實現,大幅降低開發成本。

儀表板的好處有二:第一是「分享」,不僅能提供線路記者操作、共同觀察資料,與專家討論時也能即時進行demo;第二則是「查證」,當我們滑鼠hover軌跡,或是點擊軌跡時,便可透過提示框查看資料細節、原始出處。

PART5、用AE製作軌跡動畫

當軌跡圖資檔就位,而團隊也已收斂出新聞內容重點、撰寫好腳本分鏡後,最後便交由設計師製作動畫。

過去3年以來,《報導者》善用內部開發的「捲動式影片」工具產製數位專題,這個工具能實現滿版的滾動敘事(ScrollyTelling),強化讀者閱讀沉浸感;我們此次亦仰賴此工法。

我們延續2023年4月盜砂多媒體報導的工法,以動畫軟體After Effect作為操作工具,並結合GEOlayers3插件,讓AE得以匯入地理圖資檔,也能串接已經在Mapbox做好的風格化的底圖,最終輸出一個MP4影片檔。

不過本次專題更有「資料視覺化」色彩,當我們想讓每條軌跡按時序出現時,其實得要在AE介面中進行繁複設定,這也讓設計師不禁開玩笑「後悔用這樣的工法」。我們也在思考,未來可能要改變製作方法論,對於仰賴資料視覺化的題目,仍建議直接以前端網頁進行開發。

若在After Effect製作資料視覺化動畫,將會產生高達900多個圖層,操作相對不友善

結語

這次的多媒體專題橫跨爬蟲、AI協作、人工描圖、GIS分析等多種環節,工序可謂繁複,如何把力氣花在刀口上更顯重要。

作為資料記者,我們強烈感受到AI的引入正改變工作方法,影像辨識、空間對位、儀表板開發等,都協助團隊克服技術門檻及時間壓力。

其實多媒體專案啟動前,團隊對於軌跡的數位化仍有掙扎,思考「頭要不要洗下去」?我們在與同業交流、小規模測試、思考長期效益後,仍決定投注資源、建立資料集。

感謝看到這裡的你,若你也喜歡這則報導的技術筆記,歡迎給我們鼓掌鼓勵,或留言與我們交流。

若對資料有任何建議或疑問,或想交流任何資料新聞(data journalism)想法,可寄信至報導者Data小組信箱:data@twreporter.org

我們也將這次的報導的資料整理在《報導者》Data小組Github,提供各界參考。

📣有你,才有《報導者》

《報導者》秉持深度、開放、非營利的精神,透過讀者的贊助支持來營運,不仰賴商業廣告置入。
如果您認同我們的理念,歡迎與我們一起前進,共同推動這場媒體小革命。

☛贊助我們:https://bit.ly/3ylK401

官方網站:https://bit.ly/3rTeR1V
粉絲專頁:https://bit.ly/37jjGYD
Instagram:https://bit.ly/3rWFQJV

--

--

報導者 The Reporter
報導者開放實驗室

台灣第一個由公益基金會成立的網路媒體,秉持深度、開放、非營利的精神,致力於公共領域調查報導,與社會共同打造多元進步的媒體環境。