meet4150 commited on
Commit
dd33601
·
verified ·
1 Parent(s): 65cfb2c

Upload folder using huggingface_hub

Browse files
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Shilin Yan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md CHANGED
@@ -1,3 +1,164 @@
1
- ---
2
- license: apache-2.0
3
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ library_name: pytorch
4
+ tags:
5
+ - image-classification
6
+ - ai-generated-image-detection
7
+ - deepfake-detection
8
+ - computer-vision
9
+ - pytorch
10
+ pipeline_tag: image-classification
11
+ ---
12
+
13
+ # AIDE Image Detector
14
+
15
+ This repository packages the `checkpoint-19.pth` model from the local AIDE training run at `/home/meet/Aivsre_001/AIDE/output_multisource_run1/checkpoint-19.pth` as a Hugging Face model repository. The exported weights are provided both as a safe deployment artifact in `model.safetensors` and, if uploaded, as the original PyTorch training snapshot `checkpoint-19.pth`.
16
+
17
+ The model is based on **AIDE**: a hybrid AI-generated image detector that combines frequency-forensic evidence and high-level semantic cues. In this run, the detector uses:
18
+
19
+ - A fixed **30-filter SRM high-pass bank** to expose subtle forensic residuals.
20
+ - Two **ResNet-50-style frequency encoders** that process DCT-derived reconstructions.
21
+ - A frozen **OpenCLIP ConvNeXt-XXL visual trunk** for high-level semantic/image-manifold features.
22
+ - A final **MLP fusion head** that merges ConvNeXt and forensic embeddings into a binary classifier: `real` vs `fake`.
23
+
24
+ ## Architecture
25
+
26
+ The forward path in [`models/AIDE.py`](./models/AIDE.py) is:
27
+
28
+ 1. Start from one RGB image.
29
+ 2. Build four DCT-based reconstructed views with [`data/dct.py`](./data/dct.py):
30
+ - `x_minmin`
31
+ - `x_maxmax`
32
+ - `x_minmin1`
33
+ - `x_maxmax1`
34
+ 3. Build a fifth view, `x_0`, from the normalized RGB image.
35
+ 4. Pass the four DCT views through the fixed SRM high-pass filters and into two ResNet branches.
36
+ 5. Pass the RGB view through the frozen OpenCLIP ConvNeXt-XXL trunk.
37
+ 6. Project the ConvNeXt pooled embedding from `3072 -> 256`.
38
+ 7. Average the four ResNet forensic embeddings into a single `2048`-dimensional frequency representation.
39
+ 8. Concatenate `[ConvNeXt_256, Forensic_2048]` into a `2304`-dimensional vector.
40
+ 9. Classify with an MLP `2304 -> 1024 -> 2`.
41
+
42
+ Important implementation details taken directly from the code:
43
+
44
+ - The frequency branch uses `HPF -> ResNet(Bottleneck, [3, 4, 6, 3])`.
45
+ - The ConvNeXt branch is constructed with `open_clip.create_model_and_transforms("convnext_xxlarge", pretrained=None)` and then populated from the checkpoint weights.
46
+ - The ConvNeXt trunk is frozen in the model definition used for this checkpoint.
47
+ - Inside the model, the RGB input is remapped from ImageNet normalization to CLIP normalization before entering the ConvNeXt visual trunk.
48
+
49
+ ## Input Preparation
50
+
51
+ Inference must follow the same preparation used during training/evaluation:
52
+
53
+ 1. Convert the image to RGB.
54
+ 2. Convert to tensor in `[0, 1]`.
55
+ 3. Use `DCT_base_Rec_Module(window_size=32, stride=16, output=256, grade_N=6)` to reconstruct four frequency-ranked views.
56
+ 4. Resize all five views to `256 x 256`.
57
+ 5. Normalize each view with:
58
+
59
+ ```python
60
+ mean = [0.485, 0.456, 0.406]
61
+ std = [0.229, 0.224, 0.225]
62
+ ```
63
+
64
+ 6. Stack the views in this exact order:
65
+
66
+ ```python
67
+ [x_minmin, x_maxmax, x_minmin1, x_maxmax1, x_0]
68
+ ```
69
+
70
+ The provided [`inference.py`](./inference.py) script reproduces this preparation pipeline.
71
+
72
+ ## Checkpoint Details
73
+
74
+ - Source checkpoint: `checkpoint-19.pth`
75
+ - Exported safe weights: `model.safetensors`
76
+ - Labels:
77
+ - `0 -> real`
78
+ - `1 -> fake`
79
+ - Epoch: `19`
80
+ - Logged trainable parameters: `54,432,466`
81
+
82
+ From the local training log for `output_multisource_run1`:
83
+
84
+ - Epoch 19 validation/top-1 accuracy: `77.9186`
85
+ - Epoch 19 validation loss: `0.4757`
86
+ - Best validation/top-1 accuracy observed in the same run: `78.5831` at epoch `17`
87
+
88
+ ## Training Context
89
+
90
+ This checkpoint came from a multi-source run configured with:
91
+
92
+ - `data_path=/home/meet/Aivsre_001/aide_data/train_multi_v1`
93
+ - `eval_data_path=/home/meet/Aivsre_001/aide_data/eval_multi_v1`
94
+ - `epochs=20`
95
+ - `batch_size=8`
96
+ - `blr=5e-4`
97
+ - `weight_decay=0.0`
98
+ - `nb_classes=2`
99
+ - `aa=rand-m9-mstd0.5-inc1`
100
+ - `smoothing=0.1`
101
+
102
+ The upstream AIDE project is introduced in the paper **"A Sanity Check for AI-generated Image Detection"** and uses a hybrid design intended to improve robustness on challenging real-world AI-image detection settings.
103
+
104
+ ## Files In This Repo
105
+
106
+ - `model.safetensors`: exported model state dict for safer deployment.
107
+ - `checkpoint-19.pth`: original PyTorch training snapshot, if uploaded.
108
+ - `config.json`: architecture and label metadata.
109
+ - `model.json`: lightweight manifest for this packaged repo.
110
+ - `preprocessor_config.json`: image normalization and DCT-view preparation metadata.
111
+ - `inference.py`: local loading and prediction helper.
112
+ - `models/` and `data/`: source modules required to reconstruct the architecture.
113
+
114
+ ## Usage
115
+
116
+ Clone or download the repository, then install dependencies:
117
+
118
+ ```bash
119
+ pip install -r requirements.txt
120
+ ```
121
+
122
+ Run local inference:
123
+
124
+ ```bash
125
+ python inference.py --repo_dir . --image /path/to/image.jpg
126
+ ```
127
+
128
+ Or use it programmatically:
129
+
130
+ ```python
131
+ from PIL import Image
132
+
133
+ from inference import load_model, predict_pil_images
134
+
135
+ model = load_model(".")
136
+ image = Image.open("example.jpg").convert("RGB")
137
+ result = predict_pil_images(model, [image])[0]
138
+ print(result)
139
+ ```
140
+
141
+ Example output:
142
+
143
+ ```python
144
+ {
145
+ "label": "fake",
146
+ "real_probability": 0.082134,
147
+ "fake_probability": 0.917866,
148
+ }
149
+ ```
150
+
151
+ ## Notes
152
+
153
+ - This repository is designed for **weight hosting and reproducible local inference**.
154
+ - The architecture is custom and is not a native `transformers` `AutoModel` implementation.
155
+ - Because the model relies on OpenCLIP ConvNeXt-XXL plus custom DCT/SRM preprocessing, users should use the provided loader and inference script.
156
+
157
+ ## Credits
158
+
159
+ This packaged repository is derived from the original AIDE implementation:
160
+
161
+ - Project: https://github.com/shilinyan99/AIDE
162
+ - Paper: https://arxiv.org/abs/2406.19435
163
+
164
+ Original AIDE code is MIT licensed. See [`LICENSE`](./LICENSE).
config.json ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "AIDE"
4
+ ],
5
+ "model_type": "aide",
6
+ "library_name": "pytorch",
7
+ "task": "image-classification",
8
+ "num_labels": 2,
9
+ "id2label": {
10
+ "0": "real",
11
+ "1": "fake"
12
+ },
13
+ "label2id": {
14
+ "real": 0,
15
+ "fake": 1
16
+ },
17
+ "image_size": 256,
18
+ "input_tensor_shape": [
19
+ 5,
20
+ 3,
21
+ 256,
22
+ 256
23
+ ],
24
+ "frequency_branch": {
25
+ "hpf_filters": 30,
26
+ "resnet_backbones": 2,
27
+ "resnet_variant": "ResNet-50-style encoder",
28
+ "output_dim": 2048
29
+ },
30
+ "semantic_branch": {
31
+ "backbone": "OpenCLIP ConvNeXt-XXL visual trunk",
32
+ "pooled_dim": 3072,
33
+ "projection_dim": 256,
34
+ "frozen": true
35
+ },
36
+ "classifier": {
37
+ "type": "mlp",
38
+ "input_dim": 2304,
39
+ "hidden_dim": 1024,
40
+ "output_dim": 2
41
+ },
42
+ "dct_preparation": {
43
+ "window_size": 32,
44
+ "stride": 16,
45
+ "output_size": 256,
46
+ "grade_N": 6,
47
+ "selected_views": [
48
+ "x_minmin",
49
+ "x_maxmax",
50
+ "x_minmin1",
51
+ "x_maxmax1",
52
+ "x_0_rgb"
53
+ ]
54
+ },
55
+ "checkpoint": {
56
+ "source": "checkpoint-19.pth",
57
+ "epoch": 19
58
+ }
59
+ }
60
+
data/__init__.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ # Package marker for local DCT utilities.
2
+
data/dct.py ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ import torch.nn as nn
4
+ import numpy as np
5
+ import torch.nn.functional as F
6
+
7
+
8
+ def DCT_mat(size):
9
+ m = [[ (np.sqrt(1./size) if i == 0 else np.sqrt(2./size)) * np.cos((j + 0.5) * np.pi * i / size) for j in range(size)] for i in range(size)]
10
+ return m
11
+
12
+ def generate_filter(start, end, size):
13
+ return [[0. if i + j > end or i + j < start else 1. for j in range(size)] for i in range(size)]
14
+
15
+ def norm_sigma(x):
16
+ return 2. * torch.sigmoid(x) - 1.
17
+
18
+ class Filter(nn.Module):
19
+ def __init__(self, size, band_start, band_end, use_learnable=False, norm=False):
20
+ super(Filter, self).__init__()
21
+ self.use_learnable = use_learnable
22
+
23
+ self.base = nn.Parameter(torch.tensor(generate_filter(band_start, band_end, size)), requires_grad=False)
24
+ if self.use_learnable:
25
+ self.learnable = nn.Parameter(torch.randn(size, size), requires_grad=True)
26
+ self.learnable.data.normal_(0., 0.1)
27
+ self.norm = norm
28
+ if norm:
29
+ self.ft_num = nn.Parameter(torch.sum(torch.tensor(generate_filter(band_start, band_end, size))), requires_grad=False)
30
+
31
+
32
+ def forward(self, x):
33
+ if self.use_learnable:
34
+ filt = self.base + norm_sigma(self.learnable)
35
+ else:
36
+ filt = self.base
37
+
38
+ if self.norm:
39
+ y = x * filt / self.ft_num
40
+ else:
41
+ y = x * filt
42
+ return y
43
+
44
+ class DCT_base_Rec_Module(nn.Module):
45
+ """_summary_
46
+
47
+ Args:
48
+ x: [C, H, W] -> [C*level, output, output]
49
+ """
50
+ def __init__(self, window_size=32, stride=16, output=256, grade_N=6, level_fliter=[0]):
51
+ super().__init__()
52
+
53
+ assert output % window_size == 0
54
+ assert len(level_fliter) > 0
55
+
56
+ self.window_size = window_size
57
+ self.grade_N = grade_N
58
+ self.level_N = len(level_fliter)
59
+ self.N = (output // window_size) * (output // window_size)
60
+
61
+ self._DCT_patch = nn.Parameter(torch.tensor(DCT_mat(window_size)).float(), requires_grad=False)
62
+ self._DCT_patch_T = nn.Parameter(torch.transpose(torch.tensor(DCT_mat(window_size)).float(), 0, 1), requires_grad=False)
63
+
64
+ self.unfold = nn.Unfold(
65
+ kernel_size=(window_size, window_size), stride=stride
66
+ )
67
+ self.fold0 = nn.Fold(
68
+ output_size=(window_size, window_size),
69
+ kernel_size=(window_size, window_size),
70
+ stride=window_size
71
+ )
72
+
73
+ lm, mh = 2.82, 2
74
+ level_f = [
75
+ Filter(window_size, 0, window_size * 2)
76
+ ]
77
+
78
+ self.level_filters = nn.ModuleList([level_f[i] for i in level_fliter])
79
+ self.grade_filters = nn.ModuleList([Filter(window_size, window_size * 2. / grade_N * i, window_size * 2. / grade_N * (i+1), norm=True) for i in range(grade_N)])
80
+
81
+
82
+ def forward(self, x):
83
+
84
+ N = self.N
85
+ grade_N = self.grade_N
86
+ level_N = self.level_N
87
+ window_size = self.window_size
88
+ C, W, H = x.shape
89
+ x_unfold = self.unfold(x.unsqueeze(0)).squeeze(0)
90
+
91
+
92
+ _, L = x_unfold.shape
93
+ x_unfold = x_unfold.transpose(0, 1).reshape(L, C, window_size, window_size)
94
+ x_dct = self._DCT_patch @ x_unfold @ self._DCT_patch_T
95
+
96
+ y_list = []
97
+ for i in range(self.level_N):
98
+ x_pass = self.level_filters[i](x_dct)
99
+ y = self._DCT_patch_T @ x_pass @ self._DCT_patch
100
+ y_list.append(y)
101
+ level_x_unfold = torch.cat(y_list, dim=1)
102
+
103
+ grade = torch.zeros(L).to(x.device)
104
+ w, k = 1, 2
105
+ for _ in range(grade_N):
106
+ _x = torch.abs(x_dct)
107
+ _x = torch.log(_x + 1)
108
+ _x = self.grade_filters[_](_x)
109
+ _x = torch.sum(_x, dim=[1,2,3])
110
+ grade += w * _x
111
+ w *= k
112
+
113
+ _, idx = torch.sort(grade)
114
+ max_idx = torch.flip(idx, dims=[0])[:N]
115
+ maxmax_idx = max_idx[0]
116
+ if len(max_idx) == 1:
117
+ maxmax_idx1 = max_idx[0]
118
+ else:
119
+ maxmax_idx1 = max_idx[1]
120
+
121
+ min_idx = idx[:N]
122
+ minmin_idx = idx[0]
123
+ if len(min_idx) == 1:
124
+ minmin_idx1 = idx[0]
125
+ else:
126
+ minmin_idx1 = idx[1]
127
+
128
+ x_minmin = torch.index_select(level_x_unfold, 0, minmin_idx)
129
+ x_maxmax = torch.index_select(level_x_unfold, 0, maxmax_idx)
130
+ x_minmin1 = torch.index_select(level_x_unfold, 0, minmin_idx1)
131
+ x_maxmax1 = torch.index_select(level_x_unfold, 0, maxmax_idx1)
132
+
133
+ x_minmin = x_minmin.reshape(1, level_N*C*window_size* window_size).transpose(0, 1)
134
+ x_maxmax = x_maxmax.reshape(1, level_N*C*window_size* window_size).transpose(0, 1)
135
+ x_minmin1 = x_minmin1.reshape(1, level_N*C*window_size* window_size).transpose(0, 1)
136
+ x_maxmax1 = x_maxmax1.reshape(1, level_N*C*window_size* window_size).transpose(0, 1)
137
+
138
+ x_minmin = self.fold0(x_minmin)
139
+ x_maxmax = self.fold0(x_maxmax)
140
+ x_minmin1 = self.fold0(x_minmin1)
141
+ x_maxmax1 = self.fold0(x_maxmax1)
142
+
143
+
144
+ return x_minmin, x_maxmax, x_minmin1, x_maxmax1
145
+
146
+
147
+
148
+
149
+
inference.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ from pathlib import Path
5
+ from typing import Iterable, List
6
+
7
+ import numpy as np
8
+ import torch
9
+ from PIL import Image
10
+ from safetensors.torch import load_file as load_safetensors
11
+ from torchvision import transforms
12
+
13
+ from data.dct import DCT_base_Rec_Module
14
+ from models import AIDE as build_aide_model
15
+
16
+
17
+ IMAGE_SIZE = 256
18
+ TO_TENSOR = transforms.ToTensor()
19
+ NORMALIZE_AND_RESIZE = transforms.Compose(
20
+ [
21
+ transforms.Resize([IMAGE_SIZE, IMAGE_SIZE]),
22
+ transforms.Normalize(
23
+ mean=[0.485, 0.456, 0.406],
24
+ std=[0.229, 0.224, 0.225],
25
+ ),
26
+ ]
27
+ )
28
+
29
+
30
+ def build_aide_input_from_pil(image: Image.Image, dct_module: DCT_base_Rec_Module) -> torch.Tensor:
31
+ image = image.convert("RGB")
32
+ image_tensor = TO_TENSOR(image)
33
+ x_minmin, x_maxmax, x_minmin1, x_maxmax1 = dct_module(image_tensor)
34
+
35
+ x_0 = NORMALIZE_AND_RESIZE(image_tensor)
36
+ x_minmin = NORMALIZE_AND_RESIZE(x_minmin)
37
+ x_maxmax = NORMALIZE_AND_RESIZE(x_maxmax)
38
+ x_minmin1 = NORMALIZE_AND_RESIZE(x_minmin1)
39
+ x_maxmax1 = NORMALIZE_AND_RESIZE(x_maxmax1)
40
+
41
+ return torch.stack([x_minmin, x_maxmax, x_minmin1, x_maxmax1, x_0], dim=0)
42
+
43
+
44
+ def load_model(
45
+ repo_dir: str | Path,
46
+ device: str | None = None,
47
+ weights_name: str = "model.safetensors",
48
+ ) -> torch.nn.Module:
49
+ repo_dir = Path(repo_dir)
50
+ weights_path = repo_dir / weights_name
51
+ device = device or ("cuda" if torch.cuda.is_available() else "cpu")
52
+
53
+ model = build_aide_model(resnet_path=None, convnext_path=None)
54
+ state_dict = load_safetensors(str(weights_path))
55
+ model.load_state_dict(state_dict, strict=True)
56
+ model.to(device)
57
+ model.eval()
58
+ return model
59
+
60
+
61
+ @torch.inference_mode()
62
+ def predict_pil_images(
63
+ model: torch.nn.Module,
64
+ images: Iterable[Image.Image],
65
+ device: str | None = None,
66
+ ) -> List[dict]:
67
+ device = device or next(model.parameters()).device.type
68
+ dct_module = DCT_base_Rec_Module()
69
+ batch = torch.stack([build_aide_input_from_pil(img, dct_module) for img in images], dim=0).to(device)
70
+ logits = model(batch)
71
+ probs = torch.softmax(logits, dim=-1).cpu().numpy()
72
+
73
+ outputs = []
74
+ for prob in probs:
75
+ real_prob = float(prob[0])
76
+ fake_prob = float(prob[1])
77
+ label = "fake" if fake_prob >= real_prob else "real"
78
+ outputs.append(
79
+ {
80
+ "label": label,
81
+ "real_probability": round(real_prob, 6),
82
+ "fake_probability": round(fake_prob, 6),
83
+ }
84
+ )
85
+ return outputs
86
+
87
+
88
+ def _load_images(paths: Iterable[str]) -> List[Image.Image]:
89
+ return [Image.open(path).convert("RGB") for path in paths]
90
+
91
+
92
+ def main() -> None:
93
+ parser = argparse.ArgumentParser(description="Run AIDE image detector inference.")
94
+ parser.add_argument("--repo_dir", type=str, default=".", help="Local path to the model repository.")
95
+ parser.add_argument("--image", type=str, nargs="+", required=True, help="One or more image paths.")
96
+ parser.add_argument("--device", type=str, default=None, help="cuda or cpu")
97
+ args = parser.parse_args()
98
+
99
+ model = load_model(args.repo_dir, device=args.device)
100
+ images = _load_images(args.image)
101
+ predictions = predict_pil_images(model, images, device=args.device)
102
+
103
+ for image_path, prediction in zip(args.image, predictions):
104
+ print(
105
+ {
106
+ "image": str(image_path),
107
+ **prediction,
108
+ }
109
+ )
110
+
111
+
112
+ if __name__ == "__main__":
113
+ main()
114
+
model.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "AIDE Image Detector",
3
+ "repo_id": "meet4150/AIDE_image_detector",
4
+ "framework": "PyTorch",
5
+ "weights": {
6
+ "primary": "model.safetensors",
7
+ "training_snapshot": "checkpoint-19.pth"
8
+ },
9
+ "config_file": "config.json",
10
+ "preprocessor_file": "preprocessor_config.json",
11
+ "inference_file": "inference.py",
12
+ "labels": [
13
+ "real",
14
+ "fake"
15
+ ],
16
+ "notes": "Hybrid AIDE checkpoint exported from /home/meet/Aivsre_001/AIDE/output_multisource_run1/checkpoint-19.pth."
17
+ }
18
+
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f9c39868bbefde44af859ff760a9763b719562087e8d019fd78407db1520e177
3
+ size 3591869768
models/AIDE.py ADDED
@@ -0,0 +1,297 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ import open_clip
4
+ import numpy as np
5
+
6
+ from .srm_filter_kernel import all_normalized_hpf_list
7
+
8
+ class HPF(nn.Module):
9
+ def __init__(self):
10
+ super(HPF, self).__init__()
11
+
12
+ #Load 30 SRM Filters
13
+ all_hpf_list_5x5 = []
14
+
15
+ for hpf_item in all_normalized_hpf_list:
16
+ if hpf_item.shape[0] == 3:
17
+ hpf_item = np.pad(hpf_item, pad_width=((1, 1), (1, 1)), mode='constant')
18
+
19
+ all_hpf_list_5x5.append(hpf_item)
20
+
21
+ hpf_weight = torch.Tensor(all_hpf_list_5x5).view(30, 1, 5, 5).contiguous()
22
+ hpf_weight = torch.nn.Parameter(hpf_weight.repeat(1, 3, 1, 1), requires_grad=False)
23
+
24
+
25
+ self.hpf = nn.Conv2d(3, 30, kernel_size=5, padding=2, bias=False)
26
+ self.hpf.weight = hpf_weight
27
+
28
+
29
+ def forward(self, input):
30
+
31
+ output = self.hpf(input)
32
+
33
+ return output
34
+
35
+
36
+
37
+ def conv3x3(in_planes, out_planes, stride=1):
38
+ """3x3 convolution with padding"""
39
+ return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
40
+ padding=1, bias=False)
41
+
42
+
43
+ def conv1x1(in_planes, out_planes, stride=1):
44
+ """1x1 convolution"""
45
+ return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)
46
+
47
+
48
+ class BasicBlock(nn.Module):
49
+ expansion = 1
50
+
51
+ def __init__(self, inplanes, planes, stride=1, downsample=None):
52
+ super(BasicBlock, self).__init__()
53
+ self.conv1 = conv3x3(inplanes, planes, stride)
54
+ self.bn1 = nn.BatchNorm2d(planes)
55
+ self.relu = nn.ReLU(inplace=True)
56
+ self.conv2 = conv3x3(planes, planes)
57
+ self.bn2 = nn.BatchNorm2d(planes)
58
+ self.downsample = downsample
59
+ self.stride = stride
60
+
61
+ def forward(self, x):
62
+ identity = x
63
+
64
+ out = self.conv1(x)
65
+ out = self.bn1(out)
66
+ out = self.relu(out)
67
+
68
+ out = self.conv2(out)
69
+ out = self.bn2(out)
70
+
71
+ if self.downsample is not None:
72
+ identity = self.downsample(x)
73
+
74
+ out += identity
75
+ out = self.relu(out)
76
+
77
+ return out
78
+
79
+
80
+ class Bottleneck(nn.Module):
81
+ expansion = 4
82
+
83
+ def __init__(self, inplanes, planes, stride=1, downsample=None):
84
+ super(Bottleneck, self).__init__()
85
+ self.conv1 = conv1x1(inplanes, planes)
86
+ self.bn1 = nn.BatchNorm2d(planes)
87
+ self.conv2 = conv3x3(planes, planes, stride)
88
+ self.bn2 = nn.BatchNorm2d(planes)
89
+ self.conv3 = conv1x1(planes, planes * self.expansion)
90
+ self.bn3 = nn.BatchNorm2d(planes * self.expansion)
91
+ self.relu = nn.ReLU(inplace=True)
92
+ self.downsample = downsample
93
+ self.stride = stride
94
+
95
+ def forward(self, x):
96
+ identity = x
97
+
98
+ out = self.conv1(x)
99
+ out = self.bn1(out)
100
+ out = self.relu(out)
101
+
102
+ out = self.conv2(out)
103
+ out = self.bn2(out)
104
+ out = self.relu(out)
105
+
106
+ out = self.conv3(out)
107
+ out = self.bn3(out)
108
+
109
+ if self.downsample is not None:
110
+ identity = self.downsample(x)
111
+
112
+ out += identity
113
+ out = self.relu(out)
114
+
115
+ return out
116
+
117
+
118
+ class ResNet(nn.Module):
119
+
120
+ def __init__(self, block, layers, num_classes=1000, zero_init_residual=True):
121
+ super(ResNet, self).__init__()
122
+
123
+ self.inplanes = 64
124
+ self.conv1 = nn.Conv2d(30, 64, kernel_size=7, stride=2, padding=3,
125
+ bias=False)
126
+ self.bn1 = nn.BatchNorm2d(64)
127
+ self.relu = nn.ReLU(inplace=True)
128
+ self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
129
+ self.layer1 = self._make_layer(block, 64, layers[0])
130
+ self.layer2 = self._make_layer(block, 128, layers[1], stride=2)
131
+ self.layer3 = self._make_layer(block, 256, layers[2], stride=2)
132
+ self.layer4 = self._make_layer(block, 512, layers[3], stride=2)
133
+ self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
134
+ self.fc = nn.Linear(512 * block.expansion, num_classes)
135
+
136
+ for m in self.modules():
137
+ if isinstance(m, nn.Conv2d):
138
+ nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
139
+ elif isinstance(m, nn.BatchNorm2d):
140
+ nn.init.constant_(m.weight, 1)
141
+ nn.init.constant_(m.bias, 0)
142
+
143
+ # Zero-initialize the last BN in each residual branch,
144
+ # so that the residual branch starts with zeros, and each residual block behaves like an identity.
145
+ # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677
146
+ if zero_init_residual:
147
+ for m in self.modules():
148
+ if isinstance(m, Bottleneck):
149
+ nn.init.constant_(m.bn3.weight, 0)
150
+ elif isinstance(m, BasicBlock):
151
+ nn.init.constant_(m.bn2.weight, 0)
152
+
153
+ def _make_layer(self, block, planes, blocks, stride=1):
154
+ downsample = None
155
+ if stride != 1 or self.inplanes != planes * block.expansion:
156
+ downsample = nn.Sequential(
157
+ conv1x1(self.inplanes, planes * block.expansion, stride),
158
+ nn.BatchNorm2d(planes * block.expansion),
159
+ )
160
+
161
+ layers = []
162
+ layers.append(block(self.inplanes, planes, stride, downsample))
163
+ self.inplanes = planes * block.expansion
164
+ for _ in range(1, blocks):
165
+ layers.append(block(self.inplanes, planes))
166
+
167
+ return nn.Sequential(*layers)
168
+
169
+ def forward(self, x):
170
+
171
+ x = self.conv1(x)
172
+ x = self.bn1(x)
173
+ x = self.relu(x)
174
+ x = self.maxpool(x)
175
+
176
+ x = self.layer1(x)
177
+ x = self.layer2(x)
178
+ x = self.layer3(x)
179
+ x = self.layer4(x)
180
+
181
+ x = self.avgpool(x)
182
+ x = x.view(x.size(0), -1)
183
+
184
+
185
+ return x
186
+
187
+ class Mlp(nn.Module):
188
+ """ MLP as used in Vision Transformer, MLP-Mixer and related networks
189
+ """
190
+
191
+ def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU):
192
+ super().__init__()
193
+ out_features = out_features or in_features
194
+ hidden_features = hidden_features or in_features
195
+
196
+ self.fc1 = nn.Linear(in_features, hidden_features)
197
+ self.act = act_layer()
198
+ self.fc2 = nn.Linear(hidden_features, out_features)
199
+
200
+ def forward(self, x):
201
+ x = self.fc1(x)
202
+ x = self.act(x)
203
+ x = self.fc2(x)
204
+ return x
205
+
206
+ class AIDE_Model(nn.Module):
207
+
208
+ def __init__(self, resnet_path, convnext_path):
209
+ super(AIDE_Model, self).__init__()
210
+ self.hpf = HPF()
211
+ self.model_min = ResNet(Bottleneck, [3, 4, 6, 3])
212
+ self.model_max = ResNet(Bottleneck, [3, 4, 6, 3])
213
+
214
+ if resnet_path is not None:
215
+ pretrained_dict = torch.load(resnet_path, map_location='cpu')
216
+
217
+ model_min_dict = self.model_min.state_dict()
218
+ model_max_dict = self.model_max.state_dict()
219
+
220
+ for k in pretrained_dict.keys():
221
+ if k in model_min_dict and pretrained_dict[k].size() == model_min_dict[k].size():
222
+ model_min_dict[k] = pretrained_dict[k]
223
+ model_max_dict[k] = pretrained_dict[k]
224
+ else:
225
+ print(f"Skipping layer {k} because of size mismatch")
226
+
227
+ self.fc = Mlp(2048 + 256 , 1024, 2)
228
+
229
+ print("build model with convnext_xxl")
230
+ self.openclip_convnext_xxl, _, _ = open_clip.create_model_and_transforms(
231
+ "convnext_xxlarge", pretrained=convnext_path
232
+ )
233
+
234
+ self.openclip_convnext_xxl = self.openclip_convnext_xxl.visual.trunk
235
+ self.openclip_convnext_xxl.head.global_pool = nn.Identity()
236
+ self.openclip_convnext_xxl.head.flatten = nn.Identity()
237
+
238
+ self.openclip_convnext_xxl.eval()
239
+
240
+ self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
241
+ self.convnext_proj = nn.Sequential(
242
+ nn.Linear(3072, 256),
243
+
244
+ )
245
+ for param in self.openclip_convnext_xxl.parameters():
246
+ param.requires_grad = False
247
+
248
+
249
+
250
+ def forward(self, x):
251
+
252
+ b, t, c, h, w = x.shape
253
+
254
+ x_minmin = x[:, 0] #[b, c, h, w]
255
+ x_maxmax = x[:, 1]
256
+ x_minmin1 = x[:, 2]
257
+ x_maxmax1 = x[:, 3]
258
+ tokens = x[:, 4]
259
+
260
+ x_minmin = self.hpf(x_minmin)
261
+ x_maxmax = self.hpf(x_maxmax)
262
+ x_minmin1 = self.hpf(x_minmin1)
263
+ x_maxmax1 = self.hpf(x_maxmax1)
264
+
265
+ with torch.no_grad():
266
+
267
+ clip_mean = torch.Tensor([0.48145466, 0.4578275, 0.40821073])
268
+ clip_mean = clip_mean.to(tokens, non_blocking=True).view(3, 1, 1)
269
+ clip_std = torch.Tensor([0.26862954, 0.26130258, 0.27577711])
270
+ clip_std = clip_std.to(tokens, non_blocking=True).view(3, 1, 1)
271
+ dinov2_mean = torch.Tensor([0.485, 0.456, 0.406]).to(tokens, non_blocking=True).view(3, 1, 1)
272
+ dinov2_std = torch.Tensor([0.229, 0.224, 0.225]).to(tokens, non_blocking=True).view(3, 1, 1)
273
+
274
+ local_convnext_image_feats = self.openclip_convnext_xxl(
275
+ tokens * (dinov2_std / clip_std) + (dinov2_mean - clip_mean) / clip_std
276
+ ) #[b, 3072, 8, 8]
277
+ assert local_convnext_image_feats.size()[1:] == (3072, 8, 8)
278
+ local_convnext_image_feats = self.avgpool(local_convnext_image_feats).view(tokens.size(0), -1)
279
+ x_0 = self.convnext_proj(local_convnext_image_feats)
280
+
281
+ x_min = self.model_min(x_minmin)
282
+ x_max = self.model_max(x_maxmax)
283
+ x_min1 = self.model_min(x_minmin1)
284
+ x_max1 = self.model_max(x_maxmax1)
285
+
286
+ x_1 = (x_min + x_max + x_min1 + x_max1) / 4
287
+
288
+ x = torch.cat([x_0, x_1], dim=1)
289
+
290
+ x = self.fc(x)
291
+
292
+ return x
293
+
294
+ def AIDE(resnet_path, convnext_path):
295
+ model = AIDE_Model(resnet_path, convnext_path)
296
+ return model
297
+
models/__init__.py ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ from .AIDE import AIDE
2
+
models/srm_filter_kernel.py ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import numpy as np
3
+
4
+ filter_class_1 = [
5
+ np.array([
6
+ [1, 0, 0],
7
+ [0, -1, 0],
8
+ [0, 0, 0]
9
+ ], dtype=np.float32),
10
+ np.array([
11
+ [0, 1, 0],
12
+ [0, -1, 0],
13
+ [0, 0, 0]
14
+ ], dtype=np.float32),
15
+ np.array([
16
+ [0, 0, 1],
17
+ [0, -1, 0],
18
+ [0, 0, 0]
19
+ ], dtype=np.float32),
20
+ np.array([
21
+ [0, 0, 0],
22
+ [1, -1, 0],
23
+ [0, 0, 0]
24
+ ], dtype=np.float32),
25
+ np.array([
26
+ [0, 0, 0],
27
+ [0, -1, 1],
28
+ [0, 0, 0]
29
+ ], dtype=np.float32),
30
+ np.array([
31
+ [0, 0, 0],
32
+ [0, -1, 0],
33
+ [1, 0, 0]
34
+ ], dtype=np.float32),
35
+ np.array([
36
+ [0, 0, 0],
37
+ [0, -1, 0],
38
+ [0, 1, 0]
39
+ ], dtype=np.float32),
40
+ np.array([
41
+ [0, 0, 0],
42
+ [0, -1, 0],
43
+ [0, 0, 1]
44
+ ], dtype=np.float32)
45
+ ]
46
+
47
+
48
+ filter_class_2 = [
49
+ np.array([
50
+ [1, 0, 0],
51
+ [0, -2, 0],
52
+ [0, 0, 1]
53
+ ], dtype=np.float32),
54
+ np.array([
55
+ [0, 1, 0],
56
+ [0, -2, 0],
57
+ [0, 1, 0]
58
+ ], dtype=np.float32),
59
+ np.array([
60
+ [0, 0, 1],
61
+ [0, -2, 0],
62
+ [1, 0, 0]
63
+ ], dtype=np.float32),
64
+ np.array([
65
+ [0, 0, 0],
66
+ [1, -2, 1],
67
+ [0, 0, 0]
68
+ ], dtype=np.float32),
69
+ ]
70
+
71
+
72
+ filter_class_3 = [
73
+ np.array([
74
+ [-1, 0, 0, 0, 0],
75
+ [0, 3, 0, 0, 0],
76
+ [0, 0, -3, 0, 0],
77
+ [0, 0, 0, 1, 0],
78
+ [0, 0, 0, 0, 0]
79
+ ], dtype=np.float32),
80
+ np.array([
81
+ [0, 0, -1, 0, 0],
82
+ [0, 0, 3, 0, 0],
83
+ [0, 0, -3, 0, 0],
84
+ [0, 0, 1, 0, 0],
85
+ [0, 0, 0, 0, 0]
86
+ ], dtype=np.float32),
87
+ np.array([
88
+ [0, 0, 0, 0, -1],
89
+ [0, 0, 0, 3, 0],
90
+ [0, 0, -3, 0, 0],
91
+ [0, 1, 0, 0, 0],
92
+ [0, 0, 0, 0, 0]
93
+ ], dtype=np.float32),
94
+ np.array([
95
+ [0, 0, 0, 0, 0],
96
+ [0, 0, 0, 0, 0],
97
+ [0, 1, -3, 3, -1],
98
+ [0, 0, 0, 0, 0],
99
+ [0, 0, 0, 0, 0]
100
+ ], dtype=np.float32),
101
+ np.array([
102
+ [0, 0, 0, 0, 0],
103
+ [0, 1, 0, 0, 0],
104
+ [0, 0, -3, 0, 0],
105
+ [0, 0, 0, 3, 0],
106
+ [0, 0, 0, 0, -1]
107
+ ], dtype=np.float32),
108
+ np.array([
109
+ [0, 0, 0, 0, 0],
110
+ [0, 0, 1, 0, 0],
111
+ [0, 0, -3, 0, 0],
112
+ [0, 0, 3, 0, 0],
113
+ [0, 0, -1, 0, 0]
114
+ ], dtype=np.float32),
115
+ np.array([
116
+ [0, 0, 0, 0, 0],
117
+ [0, 0, 0, 1, 0],
118
+ [0, 0, -3, 0, 0],
119
+ [0, 3, 0, 0, 0],
120
+ [-1, 0, 0, 0, 0]
121
+ ], dtype=np.float32),
122
+ np.array([
123
+ [0, 0, 0, 0, 0],
124
+ [0, 0, 0, 0, 0],
125
+ [-1, 3, -3, 1, 0],
126
+ [0, 0, 0, 0, 0],
127
+ [0, 0, 0, 0, 0]
128
+ ], dtype=np.float32)
129
+ ]
130
+
131
+
132
+ filter_edge_3x3 = [
133
+ np.array([
134
+ [-1, 2, -1],
135
+ [2, -4, 2],
136
+ [0, 0, 0]
137
+ ], dtype=np.float32),
138
+ np.array([
139
+ [0, 2, -1],
140
+ [0, -4, 2],
141
+ [0, 2, -1]
142
+ ], dtype=np.float32),
143
+ np.array([
144
+ [0, 0, 0],
145
+ [2, -4, 2],
146
+ [-1, 2, -1]
147
+ ], dtype=np.float32),
148
+ np.array([
149
+ [-1, 2, 0],
150
+ [2, -4, 0],
151
+ [-1, 2, 0]
152
+ ], dtype=np.float32),
153
+ ]
154
+
155
+ filter_edge_5x5 = [
156
+ np.array([
157
+ [-1, 2, -2, 2, -1],
158
+ [2, -6, 8, -6, 2],
159
+ [-2, 8, -12, 8, -2],
160
+ [0, 0, 0, 0, 0],
161
+ [0, 0, 0, 0, 0]
162
+ ], dtype=np.float32),
163
+ np.array([
164
+ [0, 0, -2, 2, -1],
165
+ [0, 0, 8, -6, 2],
166
+ [0, 0, -12, 8, -2],
167
+ [0, 0, 8, -6, 2],
168
+ [0, 0, -2, 2, -1]
169
+ ], dtype=np.float32),
170
+ np.array([
171
+ [0, 0, 0, 0, 0],
172
+ [0, 0, 0, 0, 0],
173
+ [-2, 8, -12, 8, -2],
174
+ [2, -6, 8, -6, 2],
175
+ [-1, 2, -2, 2, -1]
176
+ ], dtype=np.float32),
177
+ np.array([
178
+ [-1, 2, -2, 0, 0],
179
+ [2, -6, 8, 0, 0],
180
+ [-2, 8, -12, 0, 0],
181
+ [2, -6, 8, 0, 0],
182
+ [-1, 2, -2, 0, 0]
183
+ ], dtype=np.float32),
184
+ ]
185
+
186
+ square_3x3 = np.array([
187
+ [-1, 2, -1],
188
+ [2, -4, 2],
189
+ [-1, 2, -1]
190
+ ], dtype=np.float32)
191
+
192
+ square_5x5 = np.array([
193
+ [-1, 2, -2, 2, -1],
194
+ [2, -6, 8, -6, 2],
195
+ [-2, 8, -12, 8, -2],
196
+ [2, -6, 8, -6, 2],
197
+ [-1, 2, -2, 2, -1]
198
+ ], dtype=np.float32)
199
+
200
+
201
+ all_hpf_list = filter_class_1 + filter_class_2 + filter_class_3 + filter_edge_3x3 + filter_edge_5x5 + [square_3x3, square_5x5]
202
+
203
+ hpf_3x3_list = filter_class_1 + filter_class_2 + filter_edge_3x3 + [square_3x3]
204
+ hpf_5x5_list = filter_class_3 + filter_edge_5x5 + [square_5x5]
205
+
206
+ normalized_filter_class_2 = [hpf / 2 for hpf in filter_class_2]
207
+ normalized_filter_class_3 = [hpf / 3 for hpf in filter_class_3]
208
+ normalized_filter_edge_3x3 = [hpf / 4 for hpf in filter_edge_3x3]
209
+ normalized_square_3x3 = square_3x3 / 4
210
+ normalized_filter_edge_5x5 = [hpf / 12 for hpf in filter_edge_5x5]
211
+ normalized_square_5x5 = square_5x5 / 12
212
+
213
+ all_normalized_hpf_list = filter_class_1 + normalized_filter_class_2 + normalized_filter_class_3 + \
214
+ normalized_filter_edge_3x3 + normalized_filter_edge_5x5 + [normalized_square_3x3, normalized_square_5x5]
215
+
216
+ normalized_hpf_3x3_list = filter_class_1 + normalized_filter_class_2 + normalized_filter_edge_3x3 + [normalized_square_3x3]
217
+ normalized_hpf_5x5_list = normalized_filter_class_3 + normalized_filter_edge_5x5 + [normalized_square_5x5]
218
+
219
+ normalized_3x3_list = normalized_filter_edge_3x3 + [normalized_square_3x3]
220
+ normalized_5x5_list = normalized_filter_edge_5x5 + [normalized_square_5x5]
preprocessor_config.json ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "do_convert_rgb": true,
3
+ "do_resize": true,
4
+ "size": {
5
+ "height": 256,
6
+ "width": 256
7
+ },
8
+ "resample": 3,
9
+ "do_rescale": true,
10
+ "rescale_factor": 0.00392156862745098,
11
+ "do_normalize": true,
12
+ "image_mean": [
13
+ 0.485,
14
+ 0.456,
15
+ 0.406
16
+ ],
17
+ "image_std": [
18
+ 0.229,
19
+ 0.224,
20
+ 0.225
21
+ ],
22
+ "extra_views": {
23
+ "type": "dct_reconstruction",
24
+ "window_size": 32,
25
+ "stride": 16,
26
+ "grade_N": 6,
27
+ "selected_views": [
28
+ "x_minmin",
29
+ "x_maxmax",
30
+ "x_minmin1",
31
+ "x_maxmax1"
32
+ ]
33
+ }
34
+ }
35
+
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ torch>=2.0
2
+ torchvision>=0.15
3
+ numpy>=1.24
4
+ Pillow>=9.5
5
+ safetensors>=0.4
6
+ open-clip-torch>=2.24.0
7
+