or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdinference.mdlayer-management.mdmain-pipeline.mdnote-grouping.mdnotehead-extraction.mdstaffline-detection.md

layer-management.mddocs/

0

# Layer Management System

1

2

Global state management system for intermediate processing results, enabling modular pipeline architecture and debugging capabilities. The layer system allows each processing stage to register intermediate results for use by subsequent stages.

3

4

## Capabilities

5

6

### Layer Registration

7

8

Register processing layers for global access throughout the pipeline.

9

10

```python { .api }

11

def register_layer(name: str, layer: ndarray) -> None:

12

"""

13

Register a processing layer with a given name.

14

15

Stores the layer data in global memory for access by other

16

processing stages. Prints a warning if layer name already exists.

17

18

Parameters:

19

- name (str): Unique identifier for the layer

20

- layer (ndarray): Numpy array containing the layer data

21

22

Raises:

23

AssertionError: If layer is not a numpy array

24

"""

25

```

26

27

### Layer Retrieval

28

29

Retrieve registered processing layers by name.

30

31

```python { .api }

32

def get_layer(name: str) -> ndarray:

33

"""

34

Retrieve a registered processing layer by name.

35

36

Parameters:

37

- name (str): Name of the layer to retrieve

38

39

Returns:

40

ndarray: The requested layer data

41

42

Raises:

43

KeyError: If no layer with the given name exists

44

"""

45

```

46

47

### Layer Management

48

49

Manage the lifecycle of registered layers.

50

51

```python { .api }

52

def delete_layer(name: str) -> None:

53

"""

54

Delete a registered layer and free its memory.

55

56

Silently handles cases where the layer doesn't exist.

57

58

Parameters:

59

- name (str): Name of the layer to delete

60

"""

61

62

def list_layers() -> List[str]:

63

"""

64

List all currently registered layer names.

65

66

Returns:

67

List[str]: List of all registered layer names

68

"""

69

70

def show_access_count() -> None:

71

"""

72

Display access statistics for all registered layers.

73

74

Shows how many times each layer has been accessed,

75

useful for debugging and optimization.

76

"""

77

```

78

79

## Standard Layer Names

80

81

The oemer pipeline uses standardized layer names for consistency:

82

83

### Input Layers

84

- `"original_image"` - Original input image (RGB)

85

- `"staff_pred"` - Staff line predictions from neural network

86

- `"symbols_pred"` - Combined symbol predictions

87

- `"notehead_pred"` - Note head predictions

88

- `"stems_rests_pred"` - Stems and rests predictions

89

- `"clefs_keys_pred"` - Clefs and accidentals predictions

90

91

### Extracted Elements

92

- `"staffs"` - Array of Staff instances

93

- `"zones"` - Staff zone boundaries

94

- `"notes"` - Array of NoteHead instances

95

- `"note_groups"` - Array of NoteGroup instances

96

- `"clefs"` - Array of Clef instances

97

- `"sfns"` - Array of sharp/flat/natural instances

98

- `"rests"` - Array of Rest instances

99

- `"barlines"` - Array of Barline instances

100

101

### Processing Layers

102

- `"note_id"` - Note ID mapping layer

103

- `"group_map"` - Note group mapping layer

104

- `"bboxes"` - Bounding box registration layer

105

106

## Usage Examples

107

108

### Basic Layer Operations

109

110

```python

111

from oemer.layers import register_layer, get_layer, delete_layer, list_layers

112

import numpy as np

113

import cv2

114

115

# Register an image layer

116

image = cv2.imread("sheet_music.jpg")

117

register_layer("original_image", image)

118

119

# Register prediction layers

120

staff_predictions = np.random.randint(0, 2, (1000, 1500), dtype=np.uint8)

121

register_layer("staff_pred", staff_predictions)

122

123

symbol_predictions = np.random.randint(0, 3, (1000, 1500), dtype=np.uint8)

124

register_layer("symbols_pred", symbol_predictions)

125

126

# List all registered layers

127

print("Registered layers:", list_layers())

128

129

# Retrieve layers for processing

130

original = get_layer("original_image")

131

staff = get_layer("staff_pred")

132

symbols = get_layer("symbols_pred")

133

134

print(f"Original image shape: {original.shape}")

135

print(f"Staff predictions shape: {staff.shape}")

136

print(f"Symbol predictions shape: {symbols.shape}")

137

138

# Clean up specific layer

139

delete_layer("symbols_pred")

140

print("Layers after deletion:", list_layers())

141

```

142

143

### Pipeline Integration

144

145

```python

146

from oemer.layers import register_layer, get_layer

147

from oemer.staffline_extraction import extract as staff_extract

148

from oemer.notehead_extraction import extract as note_extract

149

import numpy as np

150

151

def process_with_layers(image_path: str):

152

"""Example of layer-based processing pipeline."""

153

154

# 1. Load and register input image

155

image = cv2.imread(image_path)

156

register_layer("original_image", image)

157

158

# 2. Generate and register predictions (simplified)

159

# In real usage, these come from neural network inference

160

h, w = image.shape[:2]

161

staff_pred = np.random.randint(0, 2, (h, w), dtype=np.uint8)

162

symbols_pred = np.random.randint(0, 2, (h, w), dtype=np.uint8)

163

164

register_layer("staff_pred", staff_pred)

165

register_layer("symbols_pred", symbols_pred)

166

167

# 3. Extract stafflines (reads from layers automatically)

168

staffs, zones = staff_extract()

169

register_layer("staffs", np.array(staffs))

170

register_layer("zones", zones)

171

172

# 4. Extract noteheads (reads from layers automatically)

173

notes = note_extract()

174

register_layer("notes", np.array(notes))

175

176

# 5. Access results from any stage

177

extracted_staffs = get_layer("staffs")

178

extracted_notes = get_layer("notes")

179

180

print(f"Extracted {len(extracted_staffs)} staffs")

181

print(f"Extracted {len(extracted_notes)} notes")

182

183

return extracted_staffs, extracted_notes

184

185

# Run the pipeline

186

staffs, notes = process_with_layers("test_score.jpg")

187

```

188

189

### Memory Management

190

191

```python

192

from oemer.layers import register_layer, delete_layer, list_layers, show_access_count

193

import numpy as np

194

195

def memory_efficient_processing():

196

"""Example of memory-efficient layer management."""

197

198

# Register large intermediate layers

199

large_layer1 = np.zeros((5000, 5000), dtype=np.float32)

200

large_layer2 = np.zeros((5000, 5000), dtype=np.float32)

201

202

register_layer("temp_layer1", large_layer1)

203

register_layer("temp_layer2", large_layer2)

204

205

print(f"Layers registered: {list_layers()}")

206

207

# Process data using the layers

208

data1 = get_layer("temp_layer1")

209

data2 = get_layer("temp_layer2")

210

211

# Combine and create final result

212

result = data1 + data2

213

register_layer("final_result", result)

214

215

# Clean up intermediate layers to free memory

216

delete_layer("temp_layer1")

217

delete_layer("temp_layer2")

218

219

print(f"Layers after cleanup: {list_layers()}")

220

221

# Show access statistics

222

show_access_count()

223

224

return get_layer("final_result")

225

226

result = memory_efficient_processing()

227

```

228

229

### Debugging with Layers

230

231

```python

232

from oemer.layers import register_layer, get_layer, list_layers

233

import matplotlib.pyplot as plt

234

import numpy as np

235

236

def debug_pipeline_stage(stage_name: str):

237

"""Debug a specific pipeline stage by examining its layers."""

238

239

print(f"\n=== Debugging {stage_name} ===")

240

print(f"Available layers: {list_layers()}")

241

242

# Check if expected layers exist

243

expected_layers = ["original_image", "staff_pred", "symbols_pred"]

244

for layer_name in expected_layers:

245

try:

246

layer = get_layer(layer_name)

247

print(f"✓ {layer_name}: shape={layer.shape}, dtype={layer.dtype}")

248

249

# Show basic statistics

250

if layer.dtype in [np.uint8, np.int32, np.float32]:

251

print(f" Range: [{np.min(layer)}, {np.max(layer)}]")

252

print(f" Non-zero pixels: {np.count_nonzero(layer)}")

253

254

except KeyError:

255

print(f"✗ {layer_name}: NOT FOUND")

256

257

# Visualize layers if available

258

try:

259

original = get_layer("original_image")

260

staff = get_layer("staff_pred")

261

262

fig, axes = plt.subplots(1, 2, figsize=(12, 6))

263

264

axes[0].imshow(original)

265

axes[0].set_title("Original Image")

266

axes[0].axis('off')

267

268

axes[1].imshow(staff, cmap='gray')

269

axes[1].set_title("Staff Predictions")

270

axes[1].axis('off')

271

272

plt.tight_layout()

273

plt.savefig(f"debug_{stage_name}.png")

274

print(f"Saved debug visualization: debug_{stage_name}.png")

275

276

except KeyError as e:

277

print(f"Could not create visualization: {e}")

278

279

# Use in pipeline debugging

280

debug_pipeline_stage("after_inference")

281

```

282

283

### Layer Data Validation

284

285

```python

286

from oemer.layers import get_layer, register_layer

287

import numpy as np

288

289

def validate_layer_consistency():

290

"""Validate that all layers have consistent dimensions."""

291

292

try:

293

# Get core layers

294

original = get_layer("original_image")

295

staff = get_layer("staff_pred")

296

symbols = get_layer("symbols_pred")

297

298

# Check shape consistency

299

h, w = original.shape[:2]

300

301

if staff.shape != (h, w):

302

print(f"WARNING: Staff predictions shape {staff.shape} != image shape {(h, w)}")

303

304

if symbols.shape != (h, w):

305

print(f"WARNING: Symbol predictions shape {symbols.shape} != image shape {(h, w)}")

306

307

# Check data ranges

308

if staff.dtype == np.uint8 and (staff.min() < 0 or staff.max() > 255):

309

print(f"WARNING: Staff predictions out of uint8 range: [{staff.min()}, {staff.max()}]")

310

311

if symbols.dtype == np.uint8 and (symbols.min() < 0 or symbols.max() > 255):

312

print(f"WARNING: Symbol predictions out of uint8 range: [{symbols.min()}, {symbols.max()}]")

313

314

print("✓ Layer consistency validation passed")

315

316

except KeyError as e:

317

print(f"✗ Layer validation failed: Missing layer {e}")

318

except Exception as e:

319

print(f"✗ Layer validation error: {e}")

320

321

# Run validation during pipeline execution

322

validate_layer_consistency()

323

```

324

325

## Best Practices

326

327

### Layer Naming Conventions

328

- Use descriptive, lowercase names with underscores

329

- Follow the standard naming scheme when possible

330

- Use prefixes for temporary or debug layers (`temp_`, `debug_`)

331

332

### Memory Management

333

- Delete large intermediate layers when no longer needed

334

- Use `show_access_count()` to identify unused layers

335

- Clear all layers between processing different images

336

337

### Error Handling

338

- Always check if required layers exist before accessing them

339

- Handle `KeyError` exceptions when retrieving layers

340

- Validate layer shapes and data types for consistency

341

342

The layer management system provides a flexible foundation for the oemer pipeline, enabling modular development, easy debugging, and efficient memory usage.