datasety 0.1.0__py3-none-any.whl → 0.2.0__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.
datasety/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """datasety - CLI tool for dataset preparation: image resizing and captioning."""
2
2
 
3
- __version__ = "0.1.0"
3
+ __version__ = "0.2.0"
datasety/cli.py CHANGED
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
- datasety - CLI tool for dataset preparation: image resizing and captioning.
3
+ datasety - CLI tool for dataset preparation: resize, caption, and synthetic generation.
4
4
 
5
5
  Usage:
6
6
  datasety resize --input ./in --output ./out --resolution 768x1024 --crop-position top
7
7
  datasety caption --input ./in --output ./out --trigger-word "[trigger]" --florence-2-large
8
+ datasety synthetic --input ./in --output ./out --prompt "add a winter hat"
8
9
  """
9
10
 
10
11
  import argparse
@@ -283,6 +284,114 @@ def cmd_caption(args):
283
284
  print(f"Done! Processed: {processed} images")
284
285
 
285
286
 
287
+ def cmd_synthetic(args):
288
+ """Execute the synthetic image generation command."""
289
+ # Lazy import for faster CLI startup
290
+ try:
291
+ import torch
292
+ except ImportError:
293
+ print("Error: PyTorch not installed.")
294
+ print("Run: pip install 'datasety[synthetic]'")
295
+ sys.exit(1)
296
+
297
+ input_dir = Path(args.input)
298
+ output_dir = Path(args.output)
299
+
300
+ if not input_dir.exists():
301
+ print(f"Error: Input directory '{input_dir}' does not exist.")
302
+ sys.exit(1)
303
+
304
+ output_dir.mkdir(parents=True, exist_ok=True)
305
+
306
+ # Determine device
307
+ if args.device == "cuda" and not torch.cuda.is_available():
308
+ print("Warning: CUDA not available, falling back to CPU")
309
+ device = "cpu"
310
+ else:
311
+ device = args.device
312
+
313
+ # Import the correct pipeline based on model
314
+ try:
315
+ from diffusers import QwenImageEditPlusPipeline
316
+ pipeline_class = QwenImageEditPlusPipeline
317
+ except ImportError:
318
+ print("Error: QwenImageEditPlusPipeline not found.")
319
+ print("Make sure you have the latest diffusers: pip install -U diffusers")
320
+ sys.exit(1)
321
+
322
+ print(f"Loading model: {args.model}")
323
+ print(f"Device: {device}")
324
+
325
+ torch_dtype = torch.bfloat16 if device == "cuda" else torch.float32
326
+
327
+ try:
328
+ pipeline = pipeline_class.from_pretrained(
329
+ args.model,
330
+ torch_dtype=torch_dtype
331
+ )
332
+ pipeline.to(device)
333
+ pipeline.set_progress_bar_config(disable=False)
334
+ except Exception as e:
335
+ print(f"Error loading model: {e}")
336
+ sys.exit(1)
337
+
338
+ # Find images
339
+ formats = ["jpg", "jpeg", "png", "webp", "bmp", "tiff"]
340
+ image_files = get_image_files(input_dir, formats)
341
+
342
+ if not image_files:
343
+ print(f"No images found in '{input_dir}'")
344
+ sys.exit(0)
345
+
346
+ print(f"Found {len(image_files)} images")
347
+ print(f"Prompt: {args.prompt}")
348
+ print(f"Steps: {args.steps}, CFG: {args.cfg_scale}, True CFG: {args.true_cfg_scale}")
349
+ print("-" * 50)
350
+
351
+ processed = 0
352
+
353
+ for img_path in image_files:
354
+ try:
355
+ image = Image.open(img_path).convert("RGB")
356
+
357
+ # Set up generation parameters
358
+ gen_kwargs = {
359
+ "image": [image],
360
+ "prompt": args.prompt,
361
+ "negative_prompt": args.negative_prompt,
362
+ "num_inference_steps": args.steps,
363
+ "guidance_scale": args.cfg_scale,
364
+ "true_cfg_scale": args.true_cfg_scale,
365
+ "num_images_per_prompt": args.num_images,
366
+ }
367
+
368
+ # Add seed if specified
369
+ if args.seed is not None:
370
+ gen_kwargs["generator"] = torch.manual_seed(args.seed)
371
+
372
+ with torch.inference_mode():
373
+ output = pipeline(**gen_kwargs)
374
+
375
+ # Save output image(s)
376
+ for idx, out_img in enumerate(output.images):
377
+ if args.num_images > 1:
378
+ out_name = f"{img_path.stem}_{idx + 1}.png"
379
+ else:
380
+ out_name = f"{img_path.stem}.png"
381
+
382
+ out_path = output_dir / out_name
383
+ out_img.save(out_path)
384
+
385
+ print(f"[OK] {img_path.name} -> {len(output.images)} image(s)")
386
+ processed += 1
387
+
388
+ except Exception as e:
389
+ print(f"[ERROR] {img_path.name}: {e}")
390
+
391
+ print("-" * 50)
392
+ print(f"Done! Processed: {processed} images")
393
+
394
+
286
395
  def main():
287
396
  parser = argparse.ArgumentParser(
288
397
  prog="datasety",
@@ -379,6 +488,74 @@ def main():
379
488
  )
380
489
  caption_parser.set_defaults(func=cmd_caption)
381
490
 
491
+ # === SYNTHETIC command ===
492
+ synthetic_parser = subparsers.add_parser(
493
+ "synthetic",
494
+ help="Generate synthetic images using image editing models"
495
+ )
496
+ synthetic_parser.add_argument(
497
+ "--input", "-i",
498
+ required=True,
499
+ help="Input directory containing images"
500
+ )
501
+ synthetic_parser.add_argument(
502
+ "--output", "-o",
503
+ required=True,
504
+ help="Output directory for generated images"
505
+ )
506
+ synthetic_parser.add_argument(
507
+ "--prompt", "-p",
508
+ required=True,
509
+ help="Edit prompt (e.g., 'add a winter hat to the person')"
510
+ )
511
+ synthetic_parser.add_argument(
512
+ "--model",
513
+ default="Qwen/Qwen-Image-Edit-2511",
514
+ help="Model to use (default: Qwen/Qwen-Image-Edit-2511)"
515
+ )
516
+ synthetic_parser.add_argument(
517
+ "--device",
518
+ choices=["cpu", "cuda"],
519
+ default="cuda",
520
+ help="Device to run model on (default: cuda)"
521
+ )
522
+ synthetic_parser.add_argument(
523
+ "--steps",
524
+ type=int,
525
+ default=40,
526
+ help="Number of inference steps (default: 40)"
527
+ )
528
+ synthetic_parser.add_argument(
529
+ "--cfg-scale",
530
+ type=float,
531
+ default=1.0,
532
+ help="Guidance scale (default: 1.0)"
533
+ )
534
+ synthetic_parser.add_argument(
535
+ "--true-cfg-scale",
536
+ type=float,
537
+ default=4.0,
538
+ help="True CFG scale (default: 4.0)"
539
+ )
540
+ synthetic_parser.add_argument(
541
+ "--negative-prompt",
542
+ default=" ",
543
+ help="Negative prompt (default: ' ')"
544
+ )
545
+ synthetic_parser.add_argument(
546
+ "--num-images",
547
+ type=int,
548
+ default=1,
549
+ help="Number of images to generate per input (default: 1)"
550
+ )
551
+ synthetic_parser.add_argument(
552
+ "--seed",
553
+ type=int,
554
+ default=None,
555
+ help="Random seed for reproducibility"
556
+ )
557
+ synthetic_parser.set_defaults(func=cmd_synthetic)
558
+
382
559
  # Parse and execute
383
560
  args = parser.parse_args()
384
561
  args.func(args)
@@ -1,14 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datasety
3
- Version: 0.1.0
4
- Summary: CLI tool for dataset preparation: image resizing and captioning with Florence-2
3
+ Version: 0.2.0
4
+ Summary: CLI tool for dataset preparation: resize, caption, and synthetic image generation
5
5
  Project-URL: Homepage, https://github.com/kontextox/datasety
6
6
  Project-URL: Repository, https://github.com/kontextox/datasety
7
7
  Project-URL: Issues, https://github.com/kontextox/datasety/issues
8
8
  Author: kontextox
9
9
  License-Expression: MIT
10
10
  License-File: LICENSE
11
- Keywords: captioning,cli,dataset,florence-2,image-processing,machine-learning
11
+ Keywords: captioning,cli,dataset,diffusers,florence-2,image-editing,image-processing,machine-learning,synthetic
12
12
  Classifier: Development Status :: 4 - Beta
13
13
  Classifier: Environment :: Console
14
14
  Classifier: Intended Audience :: Developers
@@ -23,6 +23,15 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
23
  Classifier: Topic :: Scientific/Engineering :: Image Processing
24
24
  Requires-Python: >=3.10
25
25
  Requires-Dist: pillow>=9.0.0
26
+ Provides-Extra: all
27
+ Requires-Dist: accelerate; extra == 'all'
28
+ Requires-Dist: diffusers>=0.32.0; extra == 'all'
29
+ Requires-Dist: einops; extra == 'all'
30
+ Requires-Dist: sentencepiece; extra == 'all'
31
+ Requires-Dist: timm; extra == 'all'
32
+ Requires-Dist: torch>=2.0.0; extra == 'all'
33
+ Requires-Dist: transformers<4.46.0,>=4.38.0; extra == 'all'
34
+ Requires-Dist: transformers>=4.38.0; extra == 'all'
26
35
  Provides-Extra: caption
27
36
  Requires-Dist: einops; extra == 'caption'
28
37
  Requires-Dist: timm; extra == 'caption'
@@ -31,11 +40,17 @@ Requires-Dist: transformers<4.46.0,>=4.38.0; extra == 'caption'
31
40
  Provides-Extra: dev
32
41
  Requires-Dist: pytest>=7.0.0; extra == 'dev'
33
42
  Requires-Dist: ruff>=0.1.0; extra == 'dev'
43
+ Provides-Extra: synthetic
44
+ Requires-Dist: accelerate; extra == 'synthetic'
45
+ Requires-Dist: diffusers>=0.32.0; extra == 'synthetic'
46
+ Requires-Dist: sentencepiece; extra == 'synthetic'
47
+ Requires-Dist: torch>=2.0.0; extra == 'synthetic'
48
+ Requires-Dist: transformers>=4.38.0; extra == 'synthetic'
34
49
  Description-Content-Type: text/markdown
35
50
 
36
51
  # datasety
37
52
 
38
- CLI tool for dataset preparation: image resizing and captioning with Florence-2.
53
+ CLI tool for dataset preparation: resize, caption, and synthetic image generation.
39
54
 
40
55
  ## Installation
41
56
 
@@ -43,10 +58,12 @@ CLI tool for dataset preparation: image resizing and captioning with Florence-2.
43
58
  pip install datasety
44
59
  ```
45
60
 
46
- For captioning support (requires PyTorch and Transformers):
61
+ Install with specific features:
47
62
 
48
63
  ```bash
49
- pip install datasety[caption]
64
+ pip install datasety[caption] # Florence-2 captioning
65
+ pip install datasety[synthetic] # Qwen image editing
66
+ pip install datasety[all] # All features
50
67
  ```
51
68
 
52
69
  ## Usage
@@ -88,7 +105,7 @@ datasety resize \
88
105
  1. Finds all images matching input formats
89
106
  2. Skips images where either dimension is smaller than target
90
107
  3. Resizes proportionally so the smaller side matches target
91
- 4. Crops from the specified area to exact dimensions
108
+ 4. Crops from the specified position to exact dimensions
92
109
  5. Saves with high quality (95% for jpg/webp)
93
110
 
94
111
  ### Generate Captions
@@ -130,6 +147,43 @@ datasety caption \
130
147
 
131
148
  This creates a `.txt` file for each image with the generated caption.
132
149
 
150
+ ### Generate Synthetic Images
151
+
152
+ Generate synthetic variations of images using Qwen-Image-Edit:
153
+
154
+ ```bash
155
+ datasety synthetic --input ./images --output ./synthetic --prompt "add a winter hat"
156
+ ```
157
+
158
+ **Options:**
159
+
160
+ | Option | Description | Default |
161
+ | ------------------- | --------------------------------- | -------------------------- |
162
+ | `--input`, `-i` | Input directory | (required) |
163
+ | `--output`, `-o` | Output directory | (required) |
164
+ | `--prompt`, `-p` | Edit prompt | (required) |
165
+ | `--model` | Model to use | `Qwen/Qwen-Image-Edit-2511`|
166
+ | `--device` | `cpu` or `cuda` | `cuda` |
167
+ | `--steps` | Number of inference steps | `40` |
168
+ | `--cfg-scale` | Guidance scale | `1.0` |
169
+ | `--true-cfg-scale` | True CFG scale | `4.0` |
170
+ | `--negative-prompt` | Negative prompt | `" "` |
171
+ | `--num-images` | Images to generate per input | `1` |
172
+ | `--seed` | Random seed for reproducibility | (random) |
173
+
174
+ **Example:**
175
+
176
+ ```bash
177
+ datasety synthetic \
178
+ --input ./dataset \
179
+ --output ./synthetic \
180
+ --prompt "add sunglasses to the person, keep everything else the same" \
181
+ --device cuda \
182
+ --steps 40 \
183
+ --true-cfg-scale 4.0 \
184
+ --seed 42
185
+ ```
186
+
133
187
  ## Common Workflows
134
188
 
135
189
  ### Prepare a LoRA Training Dataset
@@ -142,6 +196,18 @@ datasety resize -i ./raw -o ./dataset -r 1024x1024 --crop-position center
142
196
  datasety caption -i ./dataset -o ./dataset --trigger-word "[trigger]" --device cuda
143
197
  ```
144
198
 
199
+ ### Augment Dataset with Synthetic Variations
200
+
201
+ ```bash
202
+ # Generate variations with different accessories
203
+ datasety synthetic \
204
+ -i ./dataset \
205
+ -o ./synthetic \
206
+ --prompt "add a red scarf" \
207
+ --num-images 2 \
208
+ --device cuda
209
+ ```
210
+
145
211
  ### Batch Process with Numbered Files
146
212
 
147
213
  ```bash
@@ -157,7 +223,8 @@ datasety resize \
157
223
 
158
224
  - Python 3.10+
159
225
  - Pillow (for resize)
160
- - PyTorch + Transformers (for caption, install with `pip install datasety[caption]`)
226
+ - PyTorch + Transformers (for caption: `pip install datasety[caption]`)
227
+ - PyTorch + Diffusers (for synthetic: `pip install datasety[synthetic]`)
161
228
 
162
229
  ## License
163
230
 
@@ -0,0 +1,8 @@
1
+ datasety/__init__.py,sha256=rApR3JxIHU0q1LJ8_k_oM-5alQO0mW-4Ac9-GH5HmhA,105
2
+ datasety/__main__.py,sha256=rhdW0XGNAX-GC5IqU62ulCVccf3kgelddrGghYMZzn4,115
3
+ datasety/cli.py,sha256=lI18ORKHQdiZdIJ5icr3lo4YS8divLp8tz8yrrhtkF4,17807
4
+ datasety-0.2.0.dist-info/METADATA,sha256=xmi3GjI3mNVgu-tvls6HUA8yM8Wrsul6IcuZjK0xqGo,8170
5
+ datasety-0.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
6
+ datasety-0.2.0.dist-info/entry_points.txt,sha256=oWbVHN1_qyuWezjxuhsAGAqqwmivRUtG2jCYKm8bVnE,47
7
+ datasety-0.2.0.dist-info/licenses/LICENSE,sha256=dUhuoK-TCRQMpuLEAdfme-qPSJI0TlcH9jlNxeg9_EQ,1056
8
+ datasety-0.2.0.dist-info/RECORD,,
datasety/py.typed DELETED
File without changes
@@ -1,9 +0,0 @@
1
- datasety/__init__.py,sha256=LeNjBou33I9yomQhLmpfZWXEJeW2Io9ZvHnZmYXltQ4,105
2
- datasety/__main__.py,sha256=rhdW0XGNAX-GC5IqU62ulCVccf3kgelddrGghYMZzn4,115
3
- datasety/cli.py,sha256=K5doc2QZBLKDS3MjVkTsGe4giz31eo6xMCx8G4wdBEM,12399
4
- datasety/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- datasety-0.1.0.dist-info/METADATA,sha256=u-9NanmOw3QZ3pWI1VNmrUG8CBAjFwyCnVVY_I6TpSE,5429
6
- datasety-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
7
- datasety-0.1.0.dist-info/entry_points.txt,sha256=oWbVHN1_qyuWezjxuhsAGAqqwmivRUtG2jCYKm8bVnE,47
8
- datasety-0.1.0.dist-info/licenses/LICENSE,sha256=dUhuoK-TCRQMpuLEAdfme-qPSJI0TlcH9jlNxeg9_EQ,1056
9
- datasety-0.1.0.dist-info/RECORD,,