Skip to content

Commit 99dc75b

Browse files
committed
added multipolygon to bitmask conversion
1 parent 21624dd commit 99dc75b

File tree

4 files changed

+92
-5
lines changed

4 files changed

+92
-5
lines changed

api/valor_api/backend/core/annotation.py

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1-
from geoalchemy2.functions import ST_AsGeoJSON
2-
from sqlalchemy import ScalarSelect, and_, delete, insert, select
1+
from geoalchemy2.functions import (
2+
ST_AddBand,
3+
ST_AsGeoJSON,
4+
ST_AsRaster,
5+
ST_GeomFromText,
6+
ST_MakeEmptyRaster,
7+
ST_MapAlgebra,
8+
)
9+
from sqlalchemy import CTE, ScalarSelect, and_, delete, func, insert, select
310
from sqlalchemy.exc import IntegrityError
411
from sqlalchemy.orm import Session
512

@@ -10,6 +17,40 @@
1017
from valor_api.enums import ModelStatus, TableStatus, TaskType
1118

1219

20+
def _create_raster_from_multipolygon(raster: schemas.Raster) -> CTE:
21+
if not raster.geometry:
22+
raise ValueError("Raster must contain a geometry.")
23+
empty_raster = ST_AddBand(
24+
ST_MakeEmptyRaster(
25+
raster.width, # width
26+
raster.height, # height
27+
0, # upperleftx
28+
0, # upperlefty
29+
1, # scalex
30+
1, # scaley
31+
0, # skewx
32+
0, # skewy
33+
0, # srid
34+
),
35+
"1BB", # pixeltype
36+
)
37+
return select(
38+
ST_MapAlgebra(
39+
empty_raster,
40+
ST_AsRaster(
41+
ST_GeomFromText(raster.geometry.to_wkt()),
42+
empty_raster,
43+
"1BB",
44+
1,
45+
0,
46+
),
47+
"[rast2]",
48+
"1BB",
49+
"UNION",
50+
).label("raster")
51+
).cte()
52+
53+
1354
def _format_box(box: schemas.Box | None) -> str | None:
1455
return box.to_wkt() if box else None
1556

@@ -25,10 +66,17 @@ def _format_raster(
2566

2667

2768
def _format_bitmask(
69+
db: Session,
2870
raster: schemas.Raster | None,
2971
) -> str | None:
30-
if not raster or raster.geometry:
72+
"""
73+
Converts a Raster schema into a bitmask.
74+
"""
75+
if raster is None:
3176
return None
77+
elif raster and raster.geometry:
78+
r = _create_raster_from_multipolygon(raster)
79+
return db.scalar(func.raster_to_bitstring(r.c.raster))
3280
return "".join("1" if b else "0" for b in raster.array.flatten())
3381

3482

@@ -112,7 +160,7 @@ def create_annotations(
112160
"box": _format_box(annotation.bounding_box),
113161
"polygon": _format_polygon(annotation.polygon),
114162
"raster": _format_raster(annotation.raster),
115-
"bitmask": _format_bitmask(annotation.raster),
163+
"bitmask": _format_bitmask(db, annotation.raster),
116164
"embedding_id": _create_embedding(
117165
db=db, value=annotation.embedding
118166
),

api/valor_api/backend/metrics/segmentation.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ def _compute_iou(
143143
)
144144

145145
if iou is None:
146+
print(label)
146147
continue
147148

148149
metrics.extend(

integration_tests/client/metrics/test_segmentation.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ def test_evaluate_segmentation(
3434
model.add_prediction(dataset, pred)
3535
model.finalize_inferences(dataset)
3636

37+
import time
38+
39+
time.sleep(20)
40+
3741
eval_job = model.evaluate_segmentation(dataset)
3842
assert eval_job.missing_pred_labels == [
3943
{"key": "k3", "value": "v3", "score": None}
Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,35 @@
1-
ALTER TABLE annotation ADD COLUMN bitmask bit varying;
1+
ALTER TABLE annotation ADD COLUMN bitmask bit varying;
2+
3+
CREATE OR REPLACE FUNCTION raster_to_bitstring(input_raster raster)
4+
RETURNS text AS
5+
$$
6+
DECLARE
7+
width INTEGER;
8+
height INTEGER;
9+
bitstring TEXT := '';
10+
val INTEGER;
11+
pixelval INTEGER;
12+
BEGIN
13+
-- Get the width and height of the raster
14+
SELECT ST_Width(input_raster), ST_Height(input_raster) INTO width, height;
15+
16+
-- Iterate through each row and column of the raster
17+
FOR i IN 1..height LOOP
18+
FOR j IN 1..width LOOP
19+
-- Get the pixel value at position (i, j)
20+
pixelval := ST_Value(input_raster, i, j);
21+
22+
-- 1BB raster has values of 0 or 1, so just append it to the bitstring
23+
IF pixelval IS NOT NULL THEN
24+
val := pixelval::integer;
25+
bitstring := bitstring || val::text;
26+
ELSE
27+
bitstring := bitstring || '0'; -- or handle NULL as needed
28+
END IF;
29+
END LOOP;
30+
END LOOP;
31+
32+
RETURN bitstring;
33+
END;
34+
$$
35+
LANGUAGE plpgsql;

0 commit comments

Comments
 (0)