File size: 4,854 Bytes
1cdf54b
443e46c
de04b81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
---
license: agpl-3.0
tags:
  - object-detection
  - yolo
  - yolo11
  - watermark-detection
  - image-processing
  - ultralytics
pipeline_tag: object-detection
---

# BMD Watermark Detector — `bmd_watermark_n.pt`

A lightweight **YOLO11-nano** model fine-tuned for detecting watermarks in images. Trained from scratch on a custom dataset of real-world watermarked images, designed to power the smart-crop watermark removal pipeline in [DatasetStudio](https://github.com/BitcrushedHeart/DatasetStudio).

The `n` suffix denotes the **nano** variant — optimised for fast batch inference on large image datasets without sacrificing meaningful detection accuracy.

---

## Model Details

| Property | Value |
|---|---|
| **Architecture** | YOLO11n (nano) |
| **Task** | Object Detection |
| **Input** | RGB images (any resolution — resized to 640×640 internally) |
| **Output** | Bounding boxes (xyxy) + confidence scores |
| **Classes** | `0: watermark` |
| **License** | [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.html) |

---

## Intended Use

This model is intended to **detect the location of watermarks** in images so that a downstream cropping step can remove them cleanly. It is well-suited for:

- Batch processing large image datasets to remove corner/edge watermarks
- Automated dataset cleaning pipelines
- Identifying watermark position (top-left, bottom-right corner, etc.)

> [!WARNING]
> This model is intended for **legitimate dataset cleaning** use cases (e.g. removing watermarks from your own content). Do not use it to strip copyright protections from images you do not have the rights to modify.

---

## Usage

### Requirements

```bash
pip install ultralytics pillow
```

### Basic Inference

```python
from ultralytics import YOLO

model = YOLO("bmd_watermark_n.pt")

results = model("your_image.jpg", conf=0.25)
for r in results:
    for box in r.boxes:
        print(f"Watermark detected at {box.xyxy[0].tolist()} (conf: {float(box.conf[0]):.2f})")
```

### Batch Inference

```python
from ultralytics import YOLO

model = YOLO("bmd_watermark_n.pt")

image_paths = ["img1.jpg", "img2.jpg", "img3.png"]
results = model(image_paths, conf=0.25, verbose=False)

for path, r in zip(image_paths, results):
    if len(r.boxes) > 0:
        print(f"{path}: watermark found")
    else:
        print(f"{path}: clean")
```

### Smart Crop (remove watermark by cropping)

```python
from ultralytics import YOLO
from PIL import Image

def crop_out_watermark(img_path, model, conf=0.25, padding=0.1):
    results = model(img_path, conf=conf, verbose=False)
    r = results[0]
    img_w, img_h = r.orig_shape[1], r.orig_shape[0]

    if len(r.boxes) == 0:
        return Image.open(img_path)  # No watermark, return as-is

    # Find largest detected box
    best_box = max(r.boxes, key=lambda b: (b.xyxy[0][2]-b.xyxy[0][0]) * (b.xyxy[0][3]-b.xyxy[0][1]))
    x1, y1, x2, y2 = best_box.xyxy[0].tolist()

    # Add padding
    pw = (x2 - x1) * padding
    ph = (y2 - y1) * padding
    x1, y1, x2, y2 = max(0,x1-pw), max(0,y1-ph), min(img_w,x2+pw), min(img_h,y2+ph)

    # Crop to the largest region not containing the watermark
    candidates = [
        (0, 0, img_w, int(y1)),        # above
        (0, int(y2), img_w, img_h),    # below
        (0, 0, int(x1), img_h),        # left
        (int(x2), 0, img_w, img_h),    # right
    ]
    best = max(candidates, key=lambda c: (c[2]-c[0]) * (c[3]-c[1]))

    img = Image.open(img_path)
    return img.crop(best)

model = YOLO("bmd_watermark_n.pt")
clean = crop_out_watermark("watermarked.jpg", model)
clean.save("clean.jpg")
```

---

## Training

- **Base architecture:** YOLO11n (Ultralytics)
- **Training data:** Custom dataset of watermarked images with manual bounding box annotations
- **Annotation format:** YOLO format (normalised `class x_center y_center width height`)
- **Hardware:** GPU-accelerated training
- **Recommended confidence threshold:** `0.25` for single-image preview, `0.5` for batch processing

---

## Limitations

- Optimised for **corner and edge watermarks** (bottom-right, bottom-left, top-right, top-left). Centered full-image watermarks (overlays) are out of scope.
- Performance may degrade on very small watermarks (< ~3% of image area) or heavily blended semi-transparent watermarks.
- The nano variant trades some accuracy for speed. For higher accuracy at the cost of inference time, consider training an `s` or `m` size variant.

---

## License

This model is released under the **[AGPL-3.0 License](https://www.gnu.org/licenses/agpl-3.0.html)**, consistent with the Ultralytics YOLO11 framework used for training.

If you use this model in a commercial product or networked service, you must either comply with AGPL-3.0 (open-source your application) or obtain a separate commercial license from Ultralytics for the underlying framework.