deepdoctection 0.39.5__py3-none-any.whl → 0.39.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of deepdoctection might be problematic. Click here for more details.

@@ -25,7 +25,7 @@ from .utils.logger import LoggingRecord, logger
25
25
 
26
26
  # pylint: enable=wrong-import-position
27
27
 
28
- __version__ = "0.39.5"
28
+ __version__ = "0.39.7"
29
29
 
30
30
  _IMPORT_STRUCTURE = {
31
31
  "analyzer": ["config_sanity_checks", "get_dd_analyzer", "ServiceFactory"],
@@ -18,10 +18,11 @@
18
18
  """
19
19
  Implementation of BoundingBox class and related methods
20
20
  """
21
+ from __future__ import annotations
21
22
 
22
23
  from dataclasses import dataclass
23
24
  from math import ceil, floor
24
- from typing import Optional, Sequence, no_type_check
25
+ from typing import Optional, Sequence, Union, no_type_check
25
26
 
26
27
  import numpy as np
27
28
  import numpy.typing as npt
@@ -31,7 +32,7 @@ from numpy import float32
31
32
  from ..utils.error import BoundingBoxError
32
33
  from ..utils.file_utils import cocotools_available
33
34
  from ..utils.logger import LoggingRecord, logger
34
- from ..utils.types import PixelValues
35
+ from ..utils.types import BoxCoordinate, PixelValues
35
36
 
36
37
  with try_import() as import_guard:
37
38
  import pycocotools.mask as coco_mask
@@ -142,96 +143,213 @@ def iou(boxes1: npt.NDArray[float32], boxes2: npt.NDArray[float32]) -> npt.NDArr
142
143
  return np_iou(boxes1, boxes2)
143
144
 
144
145
 
146
+ RELATIVE_COORD_CONVERTER = 10**8
147
+
148
+
145
149
  @dataclass
146
150
  class BoundingBox:
147
151
  """
148
- Rectangular bounding box dataclass for object detection. Store coordinates and allows several
149
- representations. You can define an instance by passing the upper left point along with either height
150
- and width or along with the lower right point. Pass absolute_coords = 'True' if you work with image
151
- pixel coordinates. If you work with coordinates in the range between (0,1) then pass absolute_coords
152
- ='False'. A bounding box is a disposable object. Do not change the coordinates once the have been set but define
153
- a new box.
154
-
155
- `absolute_coords` indicates, whether given coordinates are in absolute or in relative terms
156
-
157
- `ulx`: upper left x
152
+ Rectangular bounding box that stores coordinates and allows different representations.
158
153
 
159
- `uly`: upper left y
154
+ This implementation differs from the previous version by using internal integer storage with precision scaling
155
+ for both absolute and relative coordinates. Coordinates are stored internally as integers (_ulx, _uly, etc.)
156
+ with relative coordinates multiplied by RELATIVE_COORD_CONVERTER (10^8) for precision. Properties (ulx, uly, etc.)
157
+ handle the conversion between internal storage and exposed values.
160
158
 
161
- `lrx`: lower right x
159
+ You can define an instance by passing:
160
+ - Upper left point (ulx, uly) + width and height, OR
161
+ - Upper left point (ulx, uly) + lower right point (lrx, lry)
162
162
 
163
- `lry`: lower right y
164
-
165
- `height`: height
166
-
167
- `width`: width
163
+ Notes:
164
+ - When absolute_coords=True, coordinates will be rounded to integers
165
+ - When absolute_coords=False, coordinates must be between 0 and 1
166
+ - The box is validated on initialization to ensure coordinates are valid
168
167
  """
169
168
 
170
169
  absolute_coords: bool
171
- ulx: float
172
- uly: float
173
- lrx: float = 0.0
174
- lry: float = 0.0
175
- height: float = 0.0
176
- width: float = 0.0
170
+ _ulx: int = 0
171
+ _uly: int = 0
172
+ _lrx: int = 0
173
+ _lry: int = 0
174
+ _height: int = 0
175
+ _width: int = 0
176
+
177
+ def __init__(
178
+ self,
179
+ absolute_coords: bool,
180
+ ulx: BoxCoordinate,
181
+ uly: BoxCoordinate,
182
+ lrx: BoxCoordinate = 0,
183
+ lry: BoxCoordinate = 0,
184
+ width: BoxCoordinate = 0,
185
+ height: BoxCoordinate = 0,
186
+ ):
187
+ """
188
+ Initialize a BoundingBox instance with the specified coordinates.
189
+
190
+ This initializer supports two ways of defining a bounding box:
191
+ 1. Using upper-left coordinates (ulx, uly) with width and height
192
+ 2. Using upper-left (ulx, uly) and lower-right (lrx, lry) coordinates
193
+
194
+ When absolute_coords is True, coordinates are stored as integers.
195
+ When absolute_coords is False, coordinates are stored as scaled integers
196
+ (original float values * RELATIVE_COORD_CONVERTER) for precision.
197
+
198
+ :param absolute_coords: Whether coordinates are absolute pixels (True) or normalized [0,1] values (False)
199
+ :param ulx: Upper-left x-coordinate (float or int)
200
+ :param uly: Upper-left y-coordinate (float or int)
201
+ :param lrx: Lower-right x-coordinate (float or int), default 0
202
+ :param lry: Lower-right y-coordinate (float or int), default 0
203
+ :param width: Width of the bounding box (float or int), default 0
204
+ :param height: Height of the bounding box (float or int), default 0
205
+ """
206
+ self.absolute_coords = absolute_coords
207
+ if absolute_coords:
208
+ self._ulx = round(ulx)
209
+ self._uly = round(uly)
210
+ if lrx and lry:
211
+ self._lrx = round(lrx)
212
+ self._lry = round(lry)
213
+ if width and height:
214
+ self._width = round(width)
215
+ self._height = round(height)
216
+ else:
217
+ self._ulx = round(ulx * RELATIVE_COORD_CONVERTER)
218
+ self._uly = round(uly * RELATIVE_COORD_CONVERTER)
219
+ if lrx and lry:
220
+ self._lrx = round(lrx * RELATIVE_COORD_CONVERTER)
221
+ self._lry = round(lry * RELATIVE_COORD_CONVERTER)
222
+ if width and height:
223
+ self._width = round(width * RELATIVE_COORD_CONVERTER)
224
+ self._height = round(height * RELATIVE_COORD_CONVERTER)
225
+ if not self._width and not self._height:
226
+ self._width = self._lrx - self._ulx
227
+ self._height = self._lry - self._uly
228
+ if not self._lrx and not self._lry:
229
+ self._lrx = self._ulx + self._width
230
+ self._lry = self._uly + self._height
231
+ self.__post_init__()
177
232
 
178
233
  def __post_init__(self) -> None:
179
- if self.width == 0.0:
180
- if self.lrx is None:
234
+ if self._width == 0:
235
+ if self._lrx is None:
181
236
  raise BoundingBoxError("Bounding box not fully initialized")
182
- self.width = self.lrx - self.ulx
183
- if self.height == 0.0:
184
- if self.lry is None:
237
+ self._width = self._lrx - self._ulx
238
+ if self._height == 0:
239
+ if self._lry is None:
185
240
  raise BoundingBoxError("Bounding box not fully initialized")
186
- self.height = self.lry - self.uly
241
+ self._height = self._lry - self._uly
187
242
 
188
- if self.lrx == 0.0:
189
- if self.width is None:
243
+ if self._lrx == 0:
244
+ if self._width is None:
190
245
  raise BoundingBoxError("Bounding box not fully initialized")
191
- self.lrx = self.ulx + self.width
192
- if self.lry == 0.0:
193
- if self.height is None:
246
+ self._lrx = self._ulx + self._width
247
+ if self._lry == 0:
248
+ if self._height is None:
194
249
  raise BoundingBoxError("Bounding box not fully initialized")
195
- self.lry = self.uly + self.height
250
+ self._lry = self._uly + self._height
196
251
 
197
- if not (self.ulx >= 0.0 and self.uly >= 0.0):
198
- raise BoundingBoxError("Bounding box ul must be >= (0.,0.)")
199
- if not (self.height > 0.0 and self.width > 0.0):
252
+ if not (self._ulx >= 0 and self._uly >= 0):
253
+ raise BoundingBoxError("Bounding box ul must be >= (0,0)")
254
+ if not (self._height > 0 and self._width > 0):
200
255
  raise BoundingBoxError(
201
256
  f"bounding box must have height and width >0. Check coords "
202
257
  f"ulx: {self.ulx}, uly: {self.uly}, lrx: {self.lrx}, "
203
258
  f"lry: {self.lry}."
204
259
  )
205
- if not self.absolute_coords:
206
- if not (self.ulx <= 1.0 and self.uly <= 1.0 and self.lrx <= 1.0 and self.lry <= 1.0):
207
- raise BoundingBoxError("coordinates must be between 0 and 1")
260
+ if not self.absolute_coords and not (
261
+ 0 <= self.ulx <= 1 and 0 <= self.uly <= 1 and 0 <= self.lrx <= 1 and 0 <= self.lry <= 1
262
+ ):
263
+ raise BoundingBoxError("coordinates must be between 0 and 1")
208
264
 
209
265
  @property
210
- def cx(self) -> float:
211
- """
212
- Bounding box center x coordinate
213
- """
266
+ def ulx(self) -> BoxCoordinate:
267
+ """ulx property"""
268
+ return self._ulx / RELATIVE_COORD_CONVERTER if not self.absolute_coords else self._ulx
269
+
270
+ @ulx.setter
271
+ def ulx(self, value: BoxCoordinate) -> None:
272
+ """ulx setter"""
273
+ self._ulx = round(value * RELATIVE_COORD_CONVERTER) if not self.absolute_coords else round(value)
274
+ self._width = self._lrx - self._ulx
275
+
276
+ @property
277
+ def uly(self) -> BoxCoordinate:
278
+ """uly property"""
279
+ return self._uly / RELATIVE_COORD_CONVERTER if not self.absolute_coords else self._uly
280
+
281
+ @uly.setter
282
+ def uly(self, value: BoxCoordinate) -> None:
283
+ """uly setter"""
284
+ self._uly = round(value * RELATIVE_COORD_CONVERTER) if not self.absolute_coords else round(value)
285
+ self._height = self._lry - self._uly
286
+
287
+ @property
288
+ def lrx(self) -> BoxCoordinate:
289
+ """lrx property"""
290
+ return self._lrx / RELATIVE_COORD_CONVERTER if not self.absolute_coords else self._lrx
291
+
292
+ @lrx.setter
293
+ def lrx(self, value: BoxCoordinate) -> None:
294
+ """lrx setter"""
295
+ self._lrx = round(value * RELATIVE_COORD_CONVERTER) if not self.absolute_coords else round(value)
296
+ self._width = self._lrx - self._ulx
297
+
298
+ @property
299
+ def lry(self) -> BoxCoordinate:
300
+ """lry property"""
301
+ return self._lry / RELATIVE_COORD_CONVERTER if not self.absolute_coords else self._lry
302
+
303
+ @lry.setter
304
+ def lry(self, value: BoxCoordinate) -> None:
305
+ """lry setter"""
306
+ self._lry = round(value * RELATIVE_COORD_CONVERTER) if not self.absolute_coords else round(value)
307
+ self._height = self._lry - self._uly
308
+
309
+ @property
310
+ def width(self) -> BoxCoordinate:
311
+ """width property"""
312
+ return self._width / RELATIVE_COORD_CONVERTER if not self.absolute_coords else self._width
313
+
314
+ @width.setter
315
+ def width(self, value: BoxCoordinate) -> None:
316
+ """width setter"""
317
+ self._width = round(value * RELATIVE_COORD_CONVERTER) if not self.absolute_coords else round(value)
318
+ self._lrx = self._ulx + self._width
319
+
320
+ @property
321
+ def height(self) -> BoxCoordinate:
322
+ """height property"""
323
+ return self._height / RELATIVE_COORD_CONVERTER if not self.absolute_coords else self._height
324
+
325
+ @height.setter
326
+ def height(self, value: BoxCoordinate) -> None:
327
+ """height setter"""
328
+ self._height = round(value * RELATIVE_COORD_CONVERTER) if not self.absolute_coords else round(value)
329
+ self._lry = self._uly + self._height
330
+
331
+ @property
332
+ def cx(self) -> BoxCoordinate:
333
+ """cx property"""
334
+ if self.absolute_coords:
335
+ return round(self.ulx + 0.5 * self.width)
214
336
  return self.ulx + 0.5 * self.width
215
337
 
216
338
  @property
217
- def cy(self) -> float:
218
- """
219
- Bounding box center y coordinate
220
- """
339
+ def cy(self) -> BoxCoordinate:
340
+ """cy property"""
341
+ if self.absolute_coords:
342
+ return round(self.uly + 0.5 * self.height)
221
343
  return self.uly + 0.5 * self.height
222
344
 
223
345
  @property
224
- def center(self) -> list[float]:
225
- """
226
- Bounding box center [x,y]
227
- """
228
- return [self.cx, self.cy]
346
+ def center(self) -> tuple[BoxCoordinate, BoxCoordinate]:
347
+ """center property"""
348
+ return (self.cx, self.cy)
229
349
 
230
350
  @property
231
- def area(self) -> float:
232
- """
233
- Bounding box area
234
- """
351
+ def area(self) -> Union[int, float]:
352
+ """area property"""
235
353
  if self.absolute_coords:
236
354
  return self.width * self.height
237
355
  raise ValueError("Cannot calculate area, when bounding box coords are relative")
@@ -264,7 +382,7 @@ class BoundingBox:
264
382
  * np_poly_scale
265
383
  )
266
384
 
267
- def to_list(self, mode: str, scale_x: float = 1.0, scale_y: float = 1.0) -> list[float]:
385
+ def to_list(self, mode: str, scale_x: float = 1.0, scale_y: float = 1.0) -> list[BoxCoordinate]:
268
386
  """
269
387
  Returns the coordinates as list
270
388
 
@@ -280,36 +398,62 @@ class BoundingBox:
280
398
  """
281
399
  assert mode in ("xyxy", "xywh", "poly"), "Not a valid mode"
282
400
  if mode == "xyxy":
283
- return [
401
+ return (
402
+ [
403
+ round(self.ulx * scale_x),
404
+ round(self.uly * scale_y),
405
+ round(self.lrx * scale_x),
406
+ round(self.lry * scale_y),
407
+ ]
408
+ if self.absolute_coords
409
+ else [
410
+ self.ulx * scale_x,
411
+ self.uly * scale_y,
412
+ self.lrx * scale_x,
413
+ self.lry * scale_y,
414
+ ]
415
+ )
416
+ if mode == "xywh":
417
+ return (
418
+ [
419
+ round(self.ulx * scale_x),
420
+ round(self.uly * scale_y),
421
+ round(self.width * scale_x),
422
+ round(self.height * scale_y),
423
+ ]
424
+ if self.absolute_coords
425
+ else [self.ulx * scale_x, self.uly * scale_y, self.width * scale_x, self.height * scale_y]
426
+ )
427
+ return (
428
+ [
429
+ round(self.ulx * scale_x),
430
+ round(self.uly * scale_y),
431
+ round(self.lrx * scale_x),
432
+ round(self.uly * scale_y),
433
+ round(self.lrx * scale_x),
434
+ round(self.lry * scale_y),
435
+ round(self.ulx * scale_x),
436
+ round(self.lry * scale_y),
437
+ ]
438
+ if self.absolute_coords
439
+ else [
284
440
  self.ulx * scale_x,
285
441
  self.uly * scale_y,
286
442
  self.lrx * scale_x,
443
+ self.uly * scale_y,
444
+ self.lrx * scale_x,
287
445
  self.lry * scale_y,
288
- ]
289
- if mode == "xywh":
290
- return [
291
446
  self.ulx * scale_x,
292
- self.uly * scale_y,
293
- self.width * scale_x,
294
- self.height * scale_y,
447
+ self.lry * scale_y,
295
448
  ]
296
- return [
297
- self.ulx * scale_x,
298
- self.uly * scale_y,
299
- self.lrx * scale_x,
300
- self.uly * scale_y,
301
- self.lrx * scale_x,
302
- self.lry * scale_y,
303
- self.ulx * scale_x,
304
- self.lry * scale_y,
305
- ]
449
+ )
306
450
 
307
451
  def transform(
308
452
  self,
309
453
  image_width: float,
310
454
  image_height: float,
311
455
  absolute_coords: bool = False,
312
- ) -> "BoundingBox":
456
+ ) -> BoundingBox:
313
457
  """
314
458
  Transforms bounding box coordinates into absolute or relative coords. Internally, a new bounding box will be
315
459
  created. Changing coordinates requires width and height of the whole image.
@@ -320,8 +464,7 @@ class BoundingBox:
320
464
 
321
465
  :return: Either a list or np.array.
322
466
  """
323
-
324
- if absolute_coords != self.absolute_coords: # only transforming in this case
467
+ if absolute_coords != self.absolute_coords:
325
468
  if self.absolute_coords:
326
469
  transformed_box = BoundingBox(
327
470
  absolute_coords=not self.absolute_coords,
@@ -344,22 +487,26 @@ class BoundingBox:
344
487
  def __str__(self) -> str:
345
488
  return f"Bounding Box ulx: {self.ulx}, uly: {self.uly}, lrx: {self.lrx}, lry: {self.lry}"
346
489
 
490
+ def __repr__(self) -> str:
491
+ return (
492
+ f"BoundingBox(absolute_coords={self.absolute_coords}, ulx={self.ulx}, uly={self.uly}, lrx={self.lrx},"
493
+ f" lry={self.lry}, width={self.width}, height={self.height})"
494
+ )
495
+
347
496
  @staticmethod
348
497
  def remove_keys() -> list[str]:
349
- """
350
- A list of attributes to suspend from as_dict creation.
351
- """
352
- return ["height", "width"]
498
+ """Removing keys when converting the dataclass object to a dict"""
499
+ return ["_height", "_width"]
500
+
501
+ @staticmethod
502
+ def replace_keys() -> dict[str, str]:
503
+ """Replacing keys when converting the dataclass object to a dict. Useful for backward compatibility"""
504
+ return {"_ulx": "ulx", "_uly": "uly", "_lrx": "lrx", "_lry": "lry"}
353
505
 
354
506
  @classmethod
355
507
  @no_type_check
356
- def from_dict(cls, **kwargs) -> "BoundingBox":
357
- """
358
- Create `BoundingBox` instance from dict
359
-
360
- :param kwargs: dict with `BoundingBox` attributes
361
- :return: Initialized BoundingBox
362
- """
508
+ def from_dict(cls, **kwargs) -> BoundingBox:
509
+ """from dict"""
363
510
  return cls(**kwargs)
364
511
 
365
512
 
@@ -65,6 +65,10 @@ def as_dict(obj: Any, dict_factory) -> Union[Any]: # type: ignore
65
65
  if hasattr(obj, "remove_keys"):
66
66
  if attribute.name in obj.remove_keys():
67
67
  continue
68
+ if hasattr(obj, "replace_keys"):
69
+ old_to_new_keys = obj.replace_keys()
70
+ if attribute.name in old_to_new_keys:
71
+ attribute.name = obj.replace_keys()[attribute.name]
68
72
  result.append((attribute.name, value))
69
73
  return dict_factory(result)
70
74
  if isinstance(obj, (list, tuple)):
@@ -433,7 +433,7 @@ class Table(Layout):
433
433
  filter(
434
434
  lambda c: column_number in (c.column_number, c.column_number + c.column_span - 1), # type: ignore
435
435
  all_cells,
436
- ) # type: ignore
436
+ )
437
437
  )
438
438
  column_cells.sort(key=lambda c: c.row_number) # type: ignore
439
439
  return column_cells # type: ignore
@@ -24,7 +24,7 @@ import catalogue # type: ignore
24
24
  from tabulate import tabulate
25
25
  from termcolor import colored
26
26
 
27
- from .base import DatasetBase
27
+ from .base import CustomDataset, DatasetBase
28
28
 
29
29
  __all__ = ["dataset_registry", "get_dataset", "print_dataset_infos"]
30
30
 
@@ -68,7 +68,10 @@ def print_dataset_infos(add_license: bool = True, add_info: bool = True) -> None
68
68
 
69
69
  for dataset in data.items():
70
70
  info = [dataset[0]]
71
- ds = dataset[1]()
71
+ if isinstance(dataset[1], CustomDataset):
72
+ ds = dataset[1]
73
+ else:
74
+ ds = dataset[1]()
72
75
  info.append(ds.dataset_info.type)
73
76
  if add_license:
74
77
  info.append(ds.dataset_info.license) # pylint: disable=W0212
@@ -123,7 +123,7 @@ class DetectResultGenerator:
123
123
  """
124
124
  sane_detect_results = []
125
125
  for detect_result in detect_result_list:
126
- if detect_result.box:
126
+ if detect_result.box is not None:
127
127
  ulx, uly, lrx, lry = detect_result.box
128
128
  if ulx >= 0 and lrx - ulx >= 0 and uly >= 0 and lry - uly >= 0:
129
129
  sane_detect_results.append(detect_result)
@@ -37,6 +37,8 @@ from ..extern.hfdetr import HFDetrDerivedDetector
37
37
  from ..mapper.hfstruct import DetrDataCollator, image_to_hf_detr_training
38
38
  from ..pipe.base import PipelineComponent
39
39
  from ..pipe.registry import pipeline_component_registry
40
+ from ..utils.error import DependencyError
41
+ from ..utils.file_utils import wandb_available
40
42
  from ..utils.logger import LoggingRecord, logger
41
43
  from ..utils.types import PathLikeOrStr
42
44
  from ..utils.utils import string_to_dict
@@ -56,6 +58,9 @@ with try_import() as hf_import_guard:
56
58
  TrainingArguments,
57
59
  )
58
60
 
61
+ with try_import() as wb_import_guard:
62
+ import wandb
63
+
59
64
 
60
65
  class DetrDerivedTrainer(Trainer):
61
66
  """
@@ -74,16 +79,18 @@ class DetrDerivedTrainer(Trainer):
74
79
  args: TrainingArguments,
75
80
  data_collator: DetrDataCollator,
76
81
  train_dataset: DatasetAdapter,
82
+ eval_dataset: Optional[DatasetBase] = None,
77
83
  ):
78
84
  self.evaluator: Optional[Evaluator] = None
79
85
  self.build_eval_kwargs: Optional[dict[str, Any]] = None
80
- super().__init__(model, args, data_collator, train_dataset)
86
+ super().__init__(model, args, data_collator, train_dataset, eval_dataset=eval_dataset)
81
87
 
82
88
  def setup_evaluator(
83
89
  self,
84
90
  dataset_val: DatasetBase,
85
91
  pipeline_component: PipelineComponent,
86
92
  metric: Union[Type[MetricBase], MetricBase],
93
+ run: Optional[wandb.sdk.wandb_run.Run] = None,
87
94
  **build_eval_kwargs: Union[str, int],
88
95
  ) -> None:
89
96
  """
@@ -93,10 +100,11 @@ class DetrDerivedTrainer(Trainer):
93
100
  :param dataset_val: dataset on which to run evaluation
94
101
  :param pipeline_component: pipeline component to plug into the evaluator
95
102
  :param metric: A metric class
103
+ :param run: WandB run
96
104
  :param build_eval_kwargs:
97
105
  """
98
106
 
99
- self.evaluator = Evaluator(dataset_val, pipeline_component, metric, num_threads=1)
107
+ self.evaluator = Evaluator(dataset_val, pipeline_component, metric, num_threads=1, run=run)
100
108
  assert self.evaluator.pipe_component
101
109
  for comp in self.evaluator.pipe_component.pipe_components:
102
110
  comp.clear_predictor()
@@ -205,12 +213,19 @@ def train_hf_detr(
205
213
  "remove_unused_columns": False,
206
214
  "per_device_train_batch_size": 2,
207
215
  "max_steps": number_samples,
208
- "evaluation_strategy": (
216
+ "eval_strategy": (
209
217
  "steps"
210
- if (dataset_val is not None and metric is not None and pipeline_component_name is not None)
218
+ if (
219
+ dataset_val is not None
220
+ and (metric is not None or metric_name is not None)
221
+ and pipeline_component_name is not None
222
+ )
211
223
  else "no"
212
224
  ),
213
225
  "eval_steps": 5000,
226
+ "use_wandb": False,
227
+ "wandb_project": None,
228
+ "wandb_repo": "deepdoctection",
214
229
  }
215
230
 
216
231
  for conf in config_overwrite:
@@ -224,6 +239,23 @@ def train_hf_detr(
224
239
  pass
225
240
  conf_dict[key] = val
226
241
 
242
+ use_wandb = conf_dict.pop("use_wandb")
243
+ wandb_project = str(conf_dict.pop("wandb_project"))
244
+ wandb_repo = str(conf_dict.pop("wandb_repo"))
245
+
246
+ # Initialize Wandb, if necessary
247
+ run = None
248
+ if use_wandb:
249
+ if not wandb_available():
250
+ raise DependencyError("WandB must be installed separately")
251
+ run = wandb.init(project=wandb_project, config=conf_dict)
252
+ run._label(repo=wandb_repo) # pylint: disable=W0212
253
+ os.environ["WANDB_DISABLED"] = "False"
254
+ os.environ["WANDB_WATCH"] = "True"
255
+ os.environ["WANDB_PROJECT"] = wandb_project
256
+ else:
257
+ os.environ["WANDB_DISABLED"] = "True"
258
+
227
259
  # Will inform about dataloader warnings if max_steps exceeds length of dataset
228
260
  if conf_dict["max_steps"] > number_samples: # type: ignore
229
261
  logger.warning(
@@ -232,7 +264,7 @@ def train_hf_detr(
232
264
  )
233
265
  )
234
266
 
235
- arguments = TrainingArguments(**conf_dict)
267
+ arguments = TrainingArguments(**conf_dict) # pylint: disable=E1123
236
268
  logger.info(LoggingRecord(f"Config: \n {arguments.to_dict()}", arguments.to_dict()))
237
269
 
238
270
  id2label = {int(k) - 1: v for v, k in categories_dict_name_as_key.items()}
@@ -252,9 +284,9 @@ def train_hf_detr(
252
284
  pretrained_model_name_or_path=path_feature_extractor_config_json
253
285
  )
254
286
  data_collator = DetrDataCollator(feature_extractor)
255
- trainer = DetrDerivedTrainer(model, arguments, data_collator, dataset)
287
+ trainer = DetrDerivedTrainer(model, arguments, data_collator, dataset, eval_dataset=dataset_val)
256
288
 
257
- if arguments.evaluation_strategy in (IntervalStrategy.STEPS,):
289
+ if arguments.eval_strategy in (IntervalStrategy.STEPS,):
258
290
  categories = dataset_val.dataflow.categories.get_categories(filtered=True) # type: ignore
259
291
  detector = HFDetrDerivedDetector(
260
292
  path_config_json, path_weights, path_feature_extractor_config_json, categories # type: ignore
@@ -266,6 +298,6 @@ def train_hf_detr(
266
298
  metric = metric_registry.get(metric_name)
267
299
  assert metric is not None
268
300
 
269
- trainer.setup_evaluator(dataset_val, pipeline_component, metric) # type: ignore
301
+ trainer.setup_evaluator(dataset_val, pipeline_component, metric, run, **build_val_dict) # type: ignore
270
302
 
271
303
  trainer.train()
@@ -395,7 +395,7 @@ def train_hf_layoutlm(
395
395
  "remove_unused_columns": False,
396
396
  "per_device_train_batch_size": 8,
397
397
  "max_steps": number_samples,
398
- "evaluation_strategy": (
398
+ "eval_strategy": (
399
399
  "steps"
400
400
  if (dataset_val is not None and metric is not None and pipeline_component_name is not None)
401
401
  else "no"
@@ -475,7 +475,7 @@ def train_hf_layoutlm(
475
475
  )
476
476
  trainer = LayoutLMTrainer(model, arguments, data_collator, dataset, eval_dataset=dataset_val)
477
477
 
478
- if arguments.evaluation_strategy in (IntervalStrategy.STEPS,):
478
+ if arguments.eval_strategy in (IntervalStrategy.STEPS,):
479
479
  assert metric is not None # silence mypy
480
480
  if dataset_type == DatasetType.SEQUENCE_CLASSIFICATION:
481
481
  categories = dataset_val.dataflow.categories.get_categories(filtered=True) # type: ignore
@@ -63,7 +63,7 @@ else:
63
63
 
64
64
 
65
65
  JsonDict = dict[str, Any]
66
-
66
+ BoxCoordinate = Union[int, float]
67
67
 
68
68
  # Some common deepdoctection dict-types
69
69
  AnnotationDict: TypeAlias = dict[str, Any]
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: deepdoctection
3
- Version: 0.39.5
3
+ Version: 0.39.7
4
4
  Summary: Repository for Document AI
5
5
  Home-page: https://github.com/deepdoctection/deepdoctection
6
6
  Author: Dr. Janis Meyer
@@ -133,6 +133,7 @@ Dynamic: description
133
133
  Dynamic: description-content-type
134
134
  Dynamic: home-page
135
135
  Dynamic: license
136
+ Dynamic: license-file
136
137
  Dynamic: provides-extra
137
138
  Dynamic: requires-dist
138
139
  Dynamic: requires-python
@@ -1,4 +1,4 @@
1
- deepdoctection/__init__.py,sha256=MbRCNpP9rjZdSs27aZt1LScR-Z_MW-I3kKgnfa8WjlY,12754
1
+ deepdoctection/__init__.py,sha256=SgzaP1SOePibE0bw0H_Jecy-ZmPWzhJYsZZ5UT_XLJs,12754
2
2
  deepdoctection/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  deepdoctection/analyzer/__init__.py,sha256=icClxrd20XutD6LxLgEPIWceSs4j_QfI3szCE-9BL2w,729
4
4
  deepdoctection/analyzer/_config.py,sha256=1rfvVrp7cI2YLzpahD77aa1tZ_KFAIQ21DM1NWhxYiI,5058
@@ -17,16 +17,16 @@ deepdoctection/dataflow/serialize.py,sha256=4pYC7m9h53JCu99waVeKpHDpsCDDdYCrSZpP
17
17
  deepdoctection/dataflow/stats.py,sha256=Bsr6v7lcesKXUYtO9wjqlzx_Yq_uyIF3Lel-tQ0i4wI,9619
18
18
  deepdoctection/datapoint/__init__.py,sha256=3K406GbOPhoEp8koVaSbMocmSsmWifnSZ1SPb7C1lOY,1643
19
19
  deepdoctection/datapoint/annotation.py,sha256=FEgz4COxVDfjic0gG7kS6iHnWLBIgFnquQ63Cbj2a4Y,22531
20
- deepdoctection/datapoint/box.py,sha256=UAdSnLexvFyg4KK1u9kXdJxhaWTwRxTU-cnQcvl37Q8,23410
21
- deepdoctection/datapoint/convert.py,sha256=gJbHY2V8nlMht1N5VdxTmWSsOeydpFPTJsaJHp6XGgE,7516
20
+ deepdoctection/datapoint/box.py,sha256=XPhC_xHqLZJjzafg1pIS_CxnVB5-0_yk-twsZZ3ncUU,30093
21
+ deepdoctection/datapoint/convert.py,sha256=Be2FvmRXt-5prZ1vwa5fG6VjgEQ_31hiQ13hAoXoaes,7740
22
22
  deepdoctection/datapoint/image.py,sha256=uGmlgF6zGptvNowZTqf-io4hbd8aFFngAvQqgdEQ5Kw,34040
23
- deepdoctection/datapoint/view.py,sha256=mReVQHX1PFGEma5n1-yOrNhp0E6aHaDMOpgtdt7wsm8,50790
23
+ deepdoctection/datapoint/view.py,sha256=sK6Ta9R6jdOS7iwF05-uPjL2wSz8wHQ5RIGCatw7i2M,50774
24
24
  deepdoctection/datasets/__init__.py,sha256=-A3aR90aDsHPmVM35JavfnQ2itYSCn3ujl4krRni1QU,1076
25
25
  deepdoctection/datasets/adapter.py,sha256=Ly_vbOAgVI73V41FUccnSX1ECTOyesW_qsuvQuvOZbw,7796
26
26
  deepdoctection/datasets/base.py,sha256=AZx-hw8Mchzb7FiOASt7zCbiybFNsM_diBzKXyC-auU,22618
27
27
  deepdoctection/datasets/dataflow_builder.py,sha256=cYU2zV3gZW2bFvMHimlO9VIl3BAUaCwML08cCIQ8Em4,4107
28
28
  deepdoctection/datasets/info.py,sha256=sC1QCOdLWFMooVmiShZ43sLUpAi3FK4d0fsLyl_9-gA,20548
29
- deepdoctection/datasets/registry.py,sha256=j0dqdemhbQNccjZEI33uqeJH5mkHn6psKgKGX71IwVc,3277
29
+ deepdoctection/datasets/registry.py,sha256=utiB-PnE6vc5HvjcudO0O4Urp2BC3snqswY6d8uPQAo,3388
30
30
  deepdoctection/datasets/save.py,sha256=Y9508Qqp8gIGN7pbGgVBBnkiC6NdCb9L2YR4wVvEUxM,3350
31
31
  deepdoctection/datasets/instances/__init__.py,sha256=XEc_4vT5lDn6bbZID9ujDEumWu8Ec2W-QS4pI_bfWWE,1388
32
32
  deepdoctection/datasets/instances/doclaynet.py,sha256=Az7USCqF0lMk1n1Dk59uUrBgBNAbKEjtUvZnCgdUH70,12286
@@ -114,13 +114,13 @@ deepdoctection/pipe/order.py,sha256=PnJZiCnxFluJiECXLTZT0c1Rr66vIRBFraa_G41UA2k,
114
114
  deepdoctection/pipe/refine.py,sha256=dTfI396xydPdbzpfo4yqFcuxl3UAB1y-WbSQn1o76ec,22367
115
115
  deepdoctection/pipe/registry.py,sha256=aFx-Tn0xhVA5l5H18duNW5QoTNKQltybsEUEzsMgUfg,902
116
116
  deepdoctection/pipe/segment.py,sha256=mWYRg7UR80PtIj1SIg_hiujDcCtLlvKJUP9vx4ZpW0Y,59318
117
- deepdoctection/pipe/sub_layout.py,sha256=N1RcID-boORcwsW_j0l64HpUu3rff0ge5qEanudLYgk,13838
117
+ deepdoctection/pipe/sub_layout.py,sha256=ldFFuFIW5em2Rl1O1BYwclrXJ86wg-1RmDZmv35Cruw,13850
118
118
  deepdoctection/pipe/text.py,sha256=h9q6d3HFOs7LOg-iwdLUPiQxrPqgunBVNmtYMBrfRQE,11180
119
119
  deepdoctection/pipe/transform.py,sha256=9Om7X7hJeL4jgUwHM1CHa4sb5v7Qo1PtVG0ls_3nI7w,3798
120
120
  deepdoctection/train/__init__.py,sha256=YFTRAZF1F7cEAKTdAIi1BLyYb6rSRcwq09Ui5Lu8d6E,1071
121
121
  deepdoctection/train/d2_frcnn_train.py,sha256=sFc_G-mEpaM8d1CCE0_6Gl4nBh11X2RYRBA3p_ylFJQ,16000
122
- deepdoctection/train/hf_detr_train.py,sha256=eHSdI11U8oGy93noZxAISfukhRBElj4dBerJ4Xcercw,10785
123
- deepdoctection/train/hf_layoutlm_train.py,sha256=DTPJZYKeDdRtDpcObYh93uh5D4sgT4c0ckHiAknCroY,22568
122
+ deepdoctection/train/hf_detr_train.py,sha256=NEOoRjZ00bPwN1supTJD7VIcHRgvDJFSYcugiHo_Rqs,12007
123
+ deepdoctection/train/hf_layoutlm_train.py,sha256=8kiGp_8GEyqCkLgeMgCJOLJWSVoKWkUBHsZtDjZOcRk,22556
124
124
  deepdoctection/train/tp_frcnn_train.py,sha256=pEpXokSVGveqo82pRnhnAmHPmjQ_8wQWpqM4ZyNHJgs,13049
125
125
  deepdoctection/utils/__init__.py,sha256=brBceRWeov9WXMiJTjyJOF2rHMP8trGGRRjhMdZ61nI,2371
126
126
  deepdoctection/utils/concurrency.py,sha256=nIhpkSncmv0LBB8PtcOLY-BsRGlfcDpz7foVdgzZd20,4598
@@ -138,11 +138,11 @@ deepdoctection/utils/pdf_utils.py,sha256=Fi0eZ2GbnO7N61Rd8b8YRKRff4dalHAzkcn3zpG
138
138
  deepdoctection/utils/settings.py,sha256=hDD6yDX_4pQXwR5ILVwJIj6hb7NXA0-ifnC25ldcUjA,12464
139
139
  deepdoctection/utils/tqdm.py,sha256=cBUtR0L1x0KMeYrLP2rrzyzCamCjpQAKroHXLv81_pk,1820
140
140
  deepdoctection/utils/transform.py,sha256=3kCgsEeRkG1efCdkfvj7tUFMs-e2jbjbflq826F2GPU,8502
141
- deepdoctection/utils/types.py,sha256=_3dmPdCIZNLbgU5QP5k_c5phDf18xLe1kYL6t2nM45s,2953
141
+ deepdoctection/utils/types.py,sha256=ti4WdtIJSg3TGK_YPkkoY9PYGMnR2tTX6Xfik8U1pNk,2986
142
142
  deepdoctection/utils/utils.py,sha256=csVs_VvCq4QBETPoE2JdTTL4MFYnD4xh-Js5vRb612g,6492
143
143
  deepdoctection/utils/viz.py,sha256=Jf8ePNYWlpuyaS6SeTYQ4OyA3eNhtgjvAQZnGNdgHC0,27051
144
- deepdoctection-0.39.5.dist-info/LICENSE,sha256=GQ0rUvuGdrMNEI3iHK5UQx6dIMU1QwAuyXsxUHn5MEQ,11351
145
- deepdoctection-0.39.5.dist-info/METADATA,sha256=O4KmPHyqhJ44FTeO5OLq1M-5dgBjAQM38ts55lemEiA,19741
146
- deepdoctection-0.39.5.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
147
- deepdoctection-0.39.5.dist-info/top_level.txt,sha256=hs2DdoOL9h4mnHhmO82BT4pz4QATIoOZ20PZmlnxFI8,15
148
- deepdoctection-0.39.5.dist-info/RECORD,,
144
+ deepdoctection-0.39.7.dist-info/licenses/LICENSE,sha256=GQ0rUvuGdrMNEI3iHK5UQx6dIMU1QwAuyXsxUHn5MEQ,11351
145
+ deepdoctection-0.39.7.dist-info/METADATA,sha256=f1bypRgjWbclKDMdqJMW_CwoIOCnE88r_C6PA9qGvDY,19763
146
+ deepdoctection-0.39.7.dist-info/WHEEL,sha256=DK49LOLCYiurdXXOXwGJm6U4DkHkg4lcxjhqwRa0CP4,91
147
+ deepdoctection-0.39.7.dist-info/top_level.txt,sha256=hs2DdoOL9h4mnHhmO82BT4pz4QATIoOZ20PZmlnxFI8,15
148
+ deepdoctection-0.39.7.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (76.0.0)
2
+ Generator: setuptools (78.0.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5