ATrISys 建立於 Cytomine 之上,提供一組 HTTP API,讓使用者可以透過程式自動化操作平台,包括:
以下提供 api 基本操作,詳細操作請至 Cytomine 官方文件。
使用 API 前,至少需要下列四個資訊:
curl 測試curl -X GET \
"{HOST}/api/currentuser.json" \
-H "X-Auth-Token: {PUBLIC_KEY}" \
-H "X-Auth-Secret: {PRIVATE_KEY}"
請替換成:
{HOST}:https://www.asynapse.xyz/{PUBLIC_KEY}:你的公鑰 public key{PRIVATE_KEY}:你的私鑰 private key 若成功,會回傳一個 JSON,內容包含:
curl -X GET \
"{HOST}/api/project.json" \
-H "X-Auth-Token: {PUBLIC_KEY}" \
-H "X-Auth-Secret: {PRIVATE_KEY}"
回傳會是一個 JSON 陣列,裡面每個物件代表一個專案:
{"id": 123, "name": "Breast Cancer Project", ...}
你可以從這裡找到 專案 ID。
程式使用 Cytomine 官方 Python client:
pip install cytomine
from cytomine import Cytomine
HOST = "https://www.asynapse.xyz"
PUBLIC_KEY = "YOUR_PUBLIC_KEY"
PRIVATE_KEY = "YOUR_PRIVATE_KEY"
with Cytomine(HOST, PUBLIC_KEY, PRIVATE_KEY) as cyto:
print("Connected")
from cytomine.models import Project
project = Project().fetch(PROJECT_ID)
print(project.name, project.ontology)
內容包含:
from cytomine.models import Ontology, TermCollection
ontology = Ontology().fetch(project.ontology)
terms = TermCollection().fetch_with_filter("ontology", ontology.id)
for t in terms:
print(t.id, t.name)
每個 term 就是一個標註類別,例如:
from cytomine.models import ImageInstanceCollection
images = ImageInstanceCollection().fetch_with_filter("project", PROJECT_ID)
print("Number of images:", len(images))
for img in images:
print(img.id, img.filename, img.width, img.height)
from cytomine.models import AnnotationCollection
image_id = 12345
W, H = img.width, img.height
MSK_DIR = "" # 輸出地址
GEO_DIR = "" # 輸出地址
SAVE_WHOLE_MASK = True # 是否輸出整張 mask
SAVE_PER_IMAGE_GEOJSON = True # 是否輸出 GeoJSON
anns = AnnotationCollection(image=image_id, showWKT=True, showTerm=True)
anns.fetch()
mask_img = None
if SAVE_WHOLE_MASK:
mask_img = Image.new("L", (W, H), 0)
drawer = ImageDraw.Draw(mask_img, "L")
if SAVE_PER_IMAGE_GEOJSON:
geo = {
"type": "FeatureCollection",
"features": []
}
for a in anns:
print(a.id, a.location, a.term)
wkt_str = a.location
try:
poly = wkt.loads(wkt_str)
except Exception:
continue
term_names = []
if getattr(a, "term", None):
term_id = a.term[0]
tname = next((t.name for t in terms if t.id == term_id), "Unlabeled")
term_names.append(tname)
else:
tname = "Unlabeled"
class_id = class_name_to_id.get(tname, 255)
if SAVE_PER_IMAGE_GEOJSON:
feature = {
"type": "Feature",
"properties": {
"image_id": image_id,
"annotation_id": a.id,
"class_id": class_id,
"class_name": tname,
},
"geometry": mapping(poly)
}
geo["features"].append(feature)
if SAVE_WHOLE_MASK:
def draw_polygon(geom):
if geom.geom_type == "Polygon":
exterior = [(x, y) for x, y in np.array(geom.exterior.coords)]
interiors = [
[(x, y) for x, y in np.array(ring.coords)]
for ring in geom.interiors
]
drawer.polygon(exterior, fill=int(class_id))
for hole in interiors:
drawer.polygon(hole, fill=0)
elif geom.geom_type == "MultiPolygon":
for g in geom.geoms:
draw_polygon(g)
draw_polygon(poly)
# === 輸出區 ===
if SAVE_PER_IMAGE_GEOJSON:
with open(os.path.join(GEO_DIR, f"{image_id}.geojson"), "w", encoding="utf-8") as jf:
json.dump(geo, jf, ensure_ascii=False)
if SAVE_WHOLE_MASK:
mask_img.save(os.path.join(MSK_DIR, f"{image_id}_mask.png"))
win_url = f"{HOST}/api/imageinstance/{image_id}/window-{W}-{H}-0-0.jpg?zoom=0"
r = cyto._session.get(win_url)
open("image.jpg","wb").write(r.content)
使用 ATrIn/Cytomine API 時,所有權限皆依使用者帳號在平台上的原有權限。
API 無法存取使用者在網頁介面無權瀏覽或操作之資料。
API key 與 Private key 僅能由個人帳號取得,請勿公開或分享。