Updating image splitter

This commit is contained in:
2026-01-12 13:28:00 +02:00
parent 510eabfa94
commit d998c65665
3 changed files with 83 additions and 42 deletions

View File

@@ -17,7 +17,7 @@ from tifffile import imread, imwrite
logger = get_logger(__name__) logger = get_logger(__name__)
def get_pseudo_rgb(arr: np.ndarray, gamma: float = 0.3) -> np.ndarray: def get_pseudo_rgb(arr: np.ndarray, gamma: float = 0.5) -> np.ndarray:
""" """
Convert a grayscale image to a pseudo-RGB image using a gamma correction. Convert a grayscale image to a pseudo-RGB image using a gamma correction.
@@ -33,10 +33,11 @@ def get_pseudo_rgb(arr: np.ndarray, gamma: float = 0.3) -> np.ndarray:
a1 = arr.copy().astype(np.float32) a1 = arr.copy().astype(np.float32)
a1 -= np.percentile(a1, 2) a1 -= np.percentile(a1, 2)
a1[a1 < 0] = 0 a1[a1 < 0] = 0
# p999 = np.percentile(a1, 99.9) p999 = np.percentile(a1, 99.9)
# a1[a1 > p999] = p999 a1[a1 > p999] = p999
a1 /= a1.max() a1 /= a1.max()
if 0:
a2 = a1.copy() a2 = a1.copy()
a2 = a2**gamma a2 = a2**gamma
a2 /= a2.max() a2 /= a2.max()
@@ -47,7 +48,7 @@ def get_pseudo_rgb(arr: np.ndarray, gamma: float = 0.3) -> np.ndarray:
a3 /= a3.max() a3 /= a3.max()
return np.stack([a1, np.zeros(a1.shape), np.zeros(a1.shape)], axis=0) return np.stack([a1, np.zeros(a1.shape), np.zeros(a1.shape)], axis=0)
return np.stack([a2, np.zeros(a1.shape), np.zeros(a1.shape)], axis=0) # return np.stack([a2, np.zeros(a1.shape), np.zeros(a1.shape)], axis=0)
# return np.stack([a1, a2, a3], axis=0) # return np.stack([a1, a2, a3], axis=0)

View File

@@ -4,10 +4,13 @@ from pathlib import Path
from tifffile import imread, imwrite from tifffile import imread, imwrite
from shapely.geometry import LineString from shapely.geometry import LineString
from copy import deepcopy from copy import deepcopy
from scipy.ndimage import zoom
# debug # debug
from src.utils.image import Image from src.utils.image import Image
from show_yolo_seg import draw_annotations from show_yolo_seg import draw_annotations
import pylab as plt import pylab as plt
import cv2 import cv2
@@ -24,13 +27,15 @@ class Label:
class_id = int(class_id) class_id = int(class_id)
bbox = np.array(coords[:4], dtype=np.float32) bbox = np.array(coords[:4], dtype=np.float32)
polygon = np.array(coords[4:], dtype=np.float32).reshape(-1, 2) if len(coords) > 4 else None polygon = np.array(coords[4:], dtype=np.float32).reshape(-1, 2) if len(coords) > 4 else None
if not any(np.isclose(polygon[0], polygon[-1])):
polygon = np.vstack([polygon, polygon[0]])
return class_id, bbox, polygon return class_id, bbox, polygon
def offset_label( def offset_label(
self, self,
img_w, img_w,
img_h, img_h,
distance: float = 3.0, distance: float = 1.0,
cap_style: int = 2, cap_style: int = 2,
join_style: int = 2, join_style: int = 2,
): ):
@@ -64,7 +69,7 @@ class Label:
line = LineString(pts) line = LineString(pts)
# Buffer distance in pixels # Buffer distance in pixels
buffered = line.buffer(distance=distance, cap_style=cap_style, join_style=join_style) buffered = line.buffer(distance=distance, cap_style=cap_style, join_style=join_style)
self.polygon = np.array(buffered.exterior.coords, dtype=np.float32) self.polygon = np.array(buffered.exterior.coords, dtype=np.float32) / (img_w, img_h)
xmn, ymn = self.polygon.min(axis=0) xmn, ymn = self.polygon.min(axis=0)
xmx, ymx = self.polygon.max(axis=0) xmx, ymx = self.polygon.max(axis=0)
xc = (xmn + xmx) / 2 xc = (xmn + xmx) / 2
@@ -158,6 +163,10 @@ class ImageSplitter:
self.image = imread(image_path) self.image = imread(image_path)
self.image_path = image_path self.image_path = image_path
self.label_path = label_path self.label_path = label_path
if not label_path.exists():
print(f"Label file {label_path} not found")
self.labels = None
else:
self.labels = YoloLabelReader(label_path) self.labels = YoloLabelReader(label_path)
def split_into_tiles(self, patch_size: tuple = (2, 2)): def split_into_tiles(self, patch_size: tuple = (2, 2)):
@@ -173,8 +182,11 @@ class ImageSplitter:
tile_reference = f"i{i}j{j}" tile_reference = f"i{i}j{j}"
hrange = (i * hstep / h, (i + 1) * hstep / h) hrange = (i * hstep / h, (i + 1) * hstep / h)
wrange = (j * wstep / w, (j + 1) * wstep / w) wrange = (j * wstep / w, (j + 1) * wstep / w)
labels = deepcopy(self.labels.get_labels(hrange, wrange))
tile = self.image[i * hstep : (i + 1) * hstep, j * wstep : (j + 1) * wstep] tile = self.image[i * hstep : (i + 1) * hstep, j * wstep : (j + 1) * wstep]
labels = None
if self.labels is not None:
labels = deepcopy(self.labels.get_labels(hrange, wrange))
print(id(labels)) print(id(labels))
if labels is not None: if labels is not None:
@@ -234,13 +246,14 @@ class ImageSplitter:
# print("tile shape:", tile.shape) # print("tile shape:", tile.shape)
yolo_annotation = f"{label.class_id} {x_offset/nx} {y_offset/ny} {h/ny} {w/nx} " + " ".join( yolo_annotation = f"{label.class_id} {x_offset/nx} {y_offset/ny} {h_norm} {w_norm} "
print(yolo_annotation)
yolo_annotation += " ".join(
[ [
f"{(x*self.image.shape[1]-(xc - x_offset))/nx:.6f} {(y*self.image.shape[0]-(yc-y_offset))/ny:.6f}" f"{(x*self.image.shape[1]-(xc - x_offset))/nx:.6f} {(y*self.image.shape[0]-(yc-y_offset))/ny:.6f}"
for x, y in label.polygon for x, y in label.polygon
] ]
) )
# print(yolo_annotation)
new_label = Label(yolo_annotation=yolo_annotation) new_label = Label(yolo_annotation=yolo_annotation)
yield tile_reference, tile, [new_label] yield tile_reference, tile, [new_label]
@@ -251,6 +264,7 @@ def main(args):
if args.output: if args.output:
args.output.mkdir(exist_ok=True, parents=True) args.output.mkdir(exist_ok=True, parents=True)
(args.output / "images").mkdir(exist_ok=True) (args.output / "images").mkdir(exist_ok=True)
(args.output / "images-zoomed").mkdir(exist_ok=True)
(args.output / "labels").mkdir(exist_ok=True) (args.output / "labels").mkdir(exist_ok=True)
for image_path in (args.input / "images").glob("*.tif"): for image_path in (args.input / "images").glob("*.tif"):
@@ -297,6 +311,11 @@ def main(args):
if args.output: if args.output:
imwrite(args.output / "images" / f"{image_path.stem}_{tile_reference}.tif", tile) imwrite(args.output / "images" / f"{image_path.stem}_{tile_reference}.tif", tile)
scale = 5
tile_zoomed = zoom(tile, zoom=scale)
imwrite(args.output / "images-zoomed" / f"{image_path.stem}_{tile_reference}.tif", tile_zoomed)
if labels is not None:
with open(args.output / "labels" / f"{image_path.stem}_{tile_reference}.txt", "w") as f: with open(args.output / "labels" / f"{image_path.stem}_{tile_reference}.txt", "w") as f:
for label in labels: for label in labels:
label.offset_label(tile.shape[1], tile.shape[0]) label.offset_label(tile.shape[1], tile.shape[0])

View File

@@ -103,6 +103,7 @@ def draw_annotations(img, labels, alpha=0.4, draw_bbox_for_poly=True):
cv2.polylines(img, [pts], isClosed=True, color=color, thickness=1) cv2.polylines(img, [pts], isClosed=True, color=color, thickness=1)
# put class text at first point # put class text at first point
x, y = int(pts[0, 0]), int(pts[0, 1]) - 6 x, y = int(pts[0, 0]), int(pts[0, 1]) - 6
if 0:
cv2.putText( cv2.putText(
img, img,
str(cls), str(cls),
@@ -188,12 +189,32 @@ def main():
# continue and just show image # continue and just show image
out = draw_annotations(img.copy(), labels, alpha=args.alpha, draw_bbox_for_poly=(not args.no_bbox)) out = draw_annotations(img.copy(), labels, alpha=args.alpha, draw_bbox_for_poly=(not args.no_bbox))
lclass, coords = labels[0]
print(lclass, coords)
bbox = coords[:4]
print("bbox", bbox)
bbox = np.array(bbox) * np.array([img.shape[1], img.shape[0], img.shape[1], img.shape[0]])
yc, xc, h, w = bbox
print("bbox", bbox)
polyline = np.array(coords[4:]).reshape(-1, 2) * np.array([img.shape[1], img.shape[0]])
print("pl", coords[4:])
print("pl", polyline)
# Convert BGR -> RGB for matplotlib display # Convert BGR -> RGB for matplotlib display
out_rgb = cv2.cvtColor(out, cv2.COLOR_BGR2RGB) # out_rgb = cv2.cvtColor(out, cv2.COLOR_BGR2RGB)
out_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# out_rgb = Image() # out_rgb = Image()
plt.figure(figsize=(10, 10 * out.shape[0] / out.shape[1])) plt.figure(figsize=(10, 10 * out.shape[0] / out.shape[1]))
plt.imshow(out_rgb) plt.imshow(out_rgb)
plt.axis("off") plt.plot(polyline[:, 0], polyline[:, 1], "y", linewidth=2)
plt.plot(
[yc - h / 2, yc - h / 2, yc + h / 2, yc + h / 2, yc - h / 2],
[xc - w / 2, xc + w / 2, xc + w / 2, xc - w / 2, xc - w / 2],
"r",
linewidth=2,
)
# plt.axis("off")
plt.title(f"{img_path.name} ({lbl_path.name})") plt.title(f"{img_path.name} ({lbl_path.name})")
plt.show() plt.show()