Skip to content

Commit 94a7b45

Browse files
author
Shoukun Sun
committed
Update version to 1.0.2 and enhance CHANGELOG with recent changes
1 parent 3cc75d2 commit 94a7b45

File tree

3 files changed

+33
-20
lines changed

3 files changed

+33
-20
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
1+
- 2025-04-30 v1.0.2
2+
* Use urljoin to construct URLs for correct path handling on Windows.
3+
- 2025-04-30 v1.0.1
4+
* UPdates QGIS Version compatibility to 3.0.0 - 3.40.99.
15
- 2025-04-26 v1.0.0
26
* Initial release of the project.

segmap/iscontroller.py

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from typing import List, Dict, Any, Optional, Tuple, TypedDict, Union
22
import os
3+
from urllib.parse import urljoin
34
import requests
45
from qgis.core import (
56
QgsVectorLayer,
@@ -19,20 +20,23 @@
1920
from qgis.utils import iface
2021
from PyQt5.QtCore import QMetaType
2122
from helper_func import (
22-
read_displayed_raster_data, encode_image,
23+
read_displayed_raster_data,
24+
encode_image,
2325
)
2426
from collections import deque
2527

2628

2729
class ModelInfo(TypedDict):
2830
"""Type definition for model info returned from API"""
31+
2932
id: str
3033
name: str
3134
description: Optional[str]
3235

3336

3437
class FeatureState(TypedDict):
3538
"""Type definition for layer state in undo/redo stacks"""
39+
3640
click_layer: List[QgsFeature]
3741
segm_layer: List[QgsFeature]
3842

@@ -98,8 +102,7 @@ def __init__(
98102
"click_type",
99103
[
100104
QgsRendererCategory(
101-
0, QgsMarkerSymbol.createSimple({"color": "red"}),
102-
"Negative Click"
105+
0, QgsMarkerSymbol.createSimple({"color": "red"}), "Negative Click"
103106
),
104107
QgsRendererCategory(
105108
1,
@@ -145,7 +148,9 @@ def _headers(self) -> Dict[str, str]:
145148

146149
def get_models(self) -> List[ModelInfo]:
147150
"""Retrieve a list of available models for segmentation."""
148-
response = requests.get(os.path.join(self.api_url, "v1/models"), headers=self._headers())
151+
response = requests.get(
152+
urljoin(self.api_url, "v1/models"), headers=self._headers()
153+
)
149154
response.raise_for_status()
150155
return response.json()
151156

@@ -155,7 +160,12 @@ def add_click(self, feature: QgsFeature) -> None:
155160
self.click_layer.updateExtents()
156161
self.click_layer.triggerRepaint()
157162

158-
def segment(self, model_id: str, raster_layer: QgsRasterLayer, new_click: Optional[QgsFeature] = None) -> Dict[str, Any]:
163+
def segment(
164+
self,
165+
model_id: str,
166+
raster_layer: QgsRasterLayer,
167+
new_click: Optional[QgsFeature] = None,
168+
) -> Dict[str, Any]:
159169
"""Perform image segmentation using the current model and manage clicks/mask."""
160170
self._save_state_for_undo() # Save current state before modification
161171
self.redo_stack.clear() # Clear redo stack on new action
@@ -183,20 +193,20 @@ def segment(self, model_id: str, raster_layer: QgsRasterLayer, new_click: Option
183193

184194
# if self.segm_layer has feature, convert it to previous_mask in the payload
185195
if False:
186-
# if self.segm_layer.featureCount() > 0:
196+
# if self.segm_layer.featureCount() > 0:
187197
payload["previous_mask"] = self._segm_layer_to_geojson()
188198
else:
189199
payload["previous_mask"] = []
190200

191201
response = requests.post(
192-
os.path.join(self.api_url, "v1/segment"), json=payload, headers=self._headers()
202+
urljoin(self.api_url, "v1/segment"), json=payload, headers=self._headers()
193203
)
194204
response.raise_for_status()
195205
result = response.json()
196206

197207
# Save segmentation result to the segmentation layer
198208
self._geojson_to_segm_layer(result["segmentation"])
199-
209+
200210
return result
201211

202212
def _geojson_to_segm_layer(self, segm: List[Dict[str, Any]]) -> None:
@@ -241,14 +251,13 @@ def _segm_layer_to_geojson(self) -> List[Dict[str, Any]]:
241251
ring_points = []
242252
for point in ring:
243253
# Convert geo coordinates to pixel coordinates
244-
pixel_x, pixel_y = self._geo2pixel_coords(point, self.segm_layer.crs())
254+
pixel_x, pixel_y = self._geo2pixel_coords(
255+
point, self.segm_layer.crs()
256+
)
245257
ring_points.append([pixel_x, pixel_y])
246258
polygon.append(ring_points)
247259

248-
geojson_features.append({
249-
"type": "Polygon",
250-
"coordinates": polygon
251-
})
260+
geojson_features.append({"type": "Polygon", "coordinates": polygon})
252261

253262
return geojson_features
254263

@@ -270,9 +279,8 @@ def _get_click_list(self) -> List[List[Union[float, int]]]:
270279
return clicks
271280

272281
def _geo2pixel_coords(
273-
self, point: QgsPointXY,
274-
point_crs: QgsCoordinateReferenceSystem
275-
) -> Tuple[float, float]:
282+
self, point: QgsPointXY, point_crs: QgsCoordinateReferenceSystem
283+
) -> Tuple[float, float]:
276284
"""Convert geo coordinates to pixel coordinates."""
277285
# if point crs is not the same as the canvas crs, transform it to canvas crs
278286
canvas_crs = self.canvas.mapSettings().destinationCrs()
@@ -286,13 +294,14 @@ def _geo2pixel_coords(
286294

287295
# Convert to pixel coordinates
288296
pixel_x = (point.x() - extent.xMinimum()) / extent.width() * self.canvas.width()
289-
pixel_y = (extent.yMaximum() - point.y()) / extent.height() * self.canvas.height()
297+
pixel_y = (
298+
(extent.yMaximum() - point.y()) / extent.height() * self.canvas.height()
299+
)
290300

291301
return pixel_x, pixel_y
292302

293303
def _pixel2geo_coords(
294-
self, pixel_x: float, pixel_y: float,
295-
target_crs: QgsCoordinateReferenceSystem
304+
self, pixel_x: float, pixel_y: float, target_crs: QgsCoordinateReferenceSystem
296305
) -> Tuple[float, float]:
297306
"""Convert pixel coordinates to geo coordinates."""
298307
extent = self.canvas.extent()

segmap/metadata.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ description=AI-powered interactive image segmentation for rapid map digitization
66
about=SegMap using deep learning to extract vector features from imagery with just a few clicks, reducing traditional digitization effort by 90%%. Ideal for rapid land cover mapping and environmental analysis.
77
tracker=https://github.com/TitorX/SegMap-QGIS/issues
88
repository=https://github.com/TitorX/SegMap-QGIS
9-
version=1.0.1
9+
version=1.0.2
1010
author=Shoukun Sun, Zhe Wang
1111
1212
# End of mandatory metadata

0 commit comments

Comments
 (0)