Mark Duppenthaler commited on
Commit
d411f8a
·
1 Parent(s): 9eea4a2

Add fallback path handling for SPA and start descriptions

Browse files
README.md CHANGED
@@ -30,7 +30,7 @@ conda activate omniseal-benchmark-backend
30
  ```bash
31
  cd frontend
32
  npm install
33
- npm run build
34
  ```
35
 
36
  3. Run backend server from project root. This would serve frontend files from port http://localhost:7860
 
30
  ```bash
31
  cd frontend
32
  npm install
33
+ npm run build -- --mode prod
34
  ```
35
 
36
  3. Run backend server from project root. This would serve frontend files from port http://localhost:7860
backend/app.py CHANGED
@@ -3,6 +3,7 @@ from backend.config import (
3
  get_dataset_config,
4
  get_datasets,
5
  )
 
6
  from backend.examples import (
7
  get_examples_tab,
8
  )
@@ -92,6 +93,22 @@ def example_files(type):
92
  return Response(json.dumps(result), mimetype="application/json")
93
 
94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  # Add a proxy endpoint to bypass CORS issues
96
  @app.route("/proxy/<path:url>")
97
  def proxy(url):
@@ -197,5 +214,11 @@ def get_chart(config, df):
197
  return Response(json.dumps(chart_data), mimetype="application/json")
198
 
199
 
 
 
 
 
 
 
200
  if __name__ == "__main__":
201
  app.run(host="0.0.0.0", port=7860, debug=True, use_reloader=True)
 
3
  get_dataset_config,
4
  get_datasets,
5
  )
6
+ from backend.descriptions import DESCRIPTIONS, MODEL_DESCRIPTIONS
7
  from backend.examples import (
8
  get_examples_tab,
9
  )
 
93
  return Response(json.dumps(result), mimetype="application/json")
94
 
95
 
96
+ @app.route("/descriptions")
97
+ def descriptions():
98
+ """
99
+ Serve descriptions and model descriptions from descriptions.py
100
+ """
101
+ return Response(
102
+ json.dumps(
103
+ {
104
+ "descriptions": DESCRIPTIONS,
105
+ "model_descriptions": MODEL_DESCRIPTIONS,
106
+ }
107
+ ),
108
+ mimetype="application/json",
109
+ )
110
+
111
+
112
  # Add a proxy endpoint to bypass CORS issues
113
  @app.route("/proxy/<path:url>")
114
  def proxy(url):
 
214
  return Response(json.dumps(chart_data), mimetype="application/json")
215
 
216
 
217
+ @app.errorhandler(404)
218
+ def not_found(e):
219
+ # Serve index.html for any 404 (SPA fallback)
220
+ return send_from_directory(app.static_folder, "index.html")
221
+
222
+
223
  if __name__ == "__main__":
224
  app.run(host="0.0.0.0", port=7860, debug=True, use_reloader=True)
backend/descriptions.py ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ DESCRIPTIONS = {
2
+ "snr": {
3
+ "full_name": "Signal-to-Noise Ratio",
4
+ "description": "Measures the ratio between the power of a signal and the power of background noise, expressed in decibels (dB). Higher values indicate better quality, with less noise relative to the signal.",
5
+ "link": "https://en.wikipedia.org/wiki/Signal-to-noise_ratio",
6
+ },
7
+ "sisnr": {
8
+ "full_name": "Scale-Invariant Signal-to-Noise Ratio",
9
+ "description": "A variant of SNR that is invariant to scaling of the signal, making it better for comparing audio quality across different amplitude levels. Higher values indicate better quality.",
10
+ "link": "https://arxiv.org/abs/1811.02508",
11
+ },
12
+ "stoi": {
13
+ "full_name": "Short-Time Objective Intelligibility",
14
+ "description": "Measures the intelligibility of speech by comparing temporal envelopes of clean and degraded speech. Values range from 0 to 1, with higher values indicating better intelligibility.",
15
+ "link": "https://ieeexplore.ieee.org/document/5495701",
16
+ },
17
+ "pesq": {
18
+ "full_name": "Perceptual Evaluation of Speech Quality",
19
+ "description": "An ITU-T standard for measuring speech quality, designed to mimic human perception. Scores range from -0.5 to 4.5, with higher values indicating better perceived quality.",
20
+ "link": "https://www.itu.int/rec/T-REC-P.862",
21
+ },
22
+ "psnr": {
23
+ "full_name": "Peak Signal-to-Noise Ratio",
24
+ "description": "Measures the ratio between the maximum possible power of a signal and the power of corrupting noise. Used primarily for image and video quality assessment, with higher values (in dB) indicating better quality.",
25
+ "link": "https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio",
26
+ },
27
+ "ssim": {
28
+ "full_name": "Structural SIMilarity Index",
29
+ "description": "Measures the perceived similarity between two images based on structural information, contrast, and luminance. Values range from -1 to 1, with 1 indicating perfect similarity.",
30
+ "link": "https://en.wikipedia.org/wiki/Structural_similarity",
31
+ },
32
+ "msssim": {
33
+ "full_name": "Multi-Scale Structural Similarity Index",
34
+ "description": "An extension of SSIM that measures image quality at multiple scales, providing a more robust quality assessment that better mimics human visual perception. Values range from 0 to 1, with higher values indicating better quality.",
35
+ "link": "https://ieeexplore.ieee.org/document/1292216",
36
+ },
37
+ "lpips": {
38
+ "full_name": "Learned Perceptual Image Patch Similarity",
39
+ "description": "A perceptual similarity metric that uses deep neural networks to better approximate human perception. Lower values indicate greater similarity, with 0 representing identical images.",
40
+ "link": "https://arxiv.org/abs/1801.03924",
41
+ },
42
+ "vmaf": {
43
+ "full_name": "Video Multi-method Assessment Fusion",
44
+ "description": "A machine learning-based video quality metric developed by Netflix that combines multiple quality measurements to better correlate with human perception. Scores range from 0 to 100, with higher values indicating better quality.",
45
+ "link": "https://github.com/Netflix/vmaf",
46
+ },
47
+ "decoder_time": {
48
+ "full_name": "Decoder Time",
49
+ "description": "The time (in seconds) taken by the watermark decoder to extract the watermark from the media. Lower values indicate more efficient decoding.",
50
+ "link": "",
51
+ },
52
+ "bit_acc": {
53
+ "full_name": "Bit Accuracy",
54
+ "description": "The percentage of bits correctly decoded from a watermark. Values range from 0 to 1, with 1 indicating perfect extraction of the watermark message.",
55
+ "link": "",
56
+ },
57
+ "word_acc": {
58
+ "full_name": "Word Accuracy",
59
+ "description": "A binary metric indicating whether the entire watermark message was correctly decoded (True) or not (False).",
60
+ "link": "",
61
+ },
62
+ "log10_p_value": {
63
+ "full_name": "Log10 P-Value",
64
+ "description": "The logarithm (base 10) of the probability that a decoded watermark could have occurred by chance. More negative values indicate stronger confidence that a real watermark was detected. This metric provides a better comparison that bit accuracy because it fairly compares different message sizes.",
65
+ "link": "",
66
+ },
67
+ "tpr": {
68
+ "full_name": "True Positive Rate",
69
+ "description": "The proportion of watermarked media correctly identified as containing a watermark. Also known as sensitivity or recall. Values range from 0 to 1, with higher values indicating better detection performance.",
70
+ "link": "https://en.wikipedia.org/wiki/Sensitivity_and_specificity",
71
+ },
72
+ "fpr": {
73
+ "full_name": "False Positive Rate",
74
+ "description": "The proportion of unwatermarked media incorrectly identified as containing a watermark. Values range from 0 to 1, with lower values indicating better detection performance.",
75
+ "link": "https://en.wikipedia.org/wiki/False_positive_rate",
76
+ },
77
+ "watermark_det_score": {
78
+ "full_name": "Watermark Detection Score",
79
+ "description": "A confidence score indicating the system's certainty that a watermark is present. Values typically range from 0 to 1, with higher values indicating greater confidence in watermark detection.",
80
+ "link": "",
81
+ },
82
+ }
83
+
84
+ MODEL_DESCRIPTIONS = {
85
+ "audioseal": {
86
+ "full_name": "AudioSeal",
87
+ "description": "AudioSeal is the first audio watermarking technique designed specifically for localized detection of AI-generated speech.",
88
+ "paper_link": "https://arxiv.org/abs/2401.17264",
89
+ "github_link": "https://github.com/facebookresearch/audioseal",
90
+ },
91
+ "wavmark": {
92
+ "full_name": "WavMark",
93
+ "description": "WavMark uses invertible networks to hide 32 bits in 1-second audio segments. Detection is performed by sliding along the audio in 0.05-second steps and decoding the message for each window. If the first 10 decoded bits match a synchronization pattern, the rest of the payload is saved (22 bits), and the window can directly slide 1 second (instead of 0.05 seconds).",
94
+ "paper_link": "https://arxiv.org/abs/2308.12770",
95
+ "github_link": "https://github.com/swesterfeld/audiowmark",
96
+ },
97
+ "timbre": {
98
+ "full_name": "Timbre",
99
+ "description": "Timbre embeds the watermark into the frequency domain, which is inherently robust against common data processing methods.",
100
+ "paper_link": "https://arxiv.org/abs/2312.03410",
101
+ "github_link": "https://github.com/TimbreWatermarking/TimbreWatermarking",
102
+ },
103
+ "wam": {
104
+ "full_name": "Watermark Anything Model",
105
+ "description": "The Watermark Anything Model (WAM) is designed for localized image watermarking.",
106
+ "paper_link": "https://arxiv.org/abs/2411.07231",
107
+ "github_link": "https://github.com/facebookresearch/watermark-anything",
108
+ },
109
+ "trustmark": {
110
+ "full_name": "TrustMark",
111
+ "description": "TrustMark is a GAN-based watermarking method.",
112
+ "paper_link": "https://arxiv.org/abs/2311.18297",
113
+ "github_link": "https://github.com/adobe/trustmark",
114
+ },
115
+ "ssl": {
116
+ "full_name": "Self-Supervised Latent Spaces",
117
+ "description": "This approach revisits watermarking techniques using pre-trained deep networks and self-supervised methods to embed marks and binary messages into latent spaces.",
118
+ "paper_link": "https://arxiv.org/abs/2112.09581",
119
+ "github_link": "https://github.com/facebookresearch/ssl_watermarking",
120
+ },
121
+ "fnns": {
122
+ "full_name": "Fixed Neural Network Steganography",
123
+ "description": "This approach revisits steganography through adversarial perturbation: it modifies the image such that a fixed decoder correctly outputs the desired message (similar to SSL but with a different network).",
124
+ "paper_link": "https://openreview.net/pdf?id=hcMvApxGSzZ",
125
+ "github_link": "https://github.com/varshakishore/FNNS",
126
+ },
127
+ "hidden": {
128
+ "full_name": "Hiding Data With Deep Networks",
129
+ "description": "First deep watermarking approach from 2018. We use the model trained and open-sourced here, which uses the same architecture and a similar training procedure. Note that this implementation uses a Just Noticeable Difference heatmap to modulate the watermark distortion for less visibility instead of using a perceptual loss during training like in the original paper.",
130
+ "paper_link": "https://arxiv.org/abs/1807.09937",
131
+ # "github_link": "https://github.com/ando-khachatryan/HiDDeN",
132
+ },
133
+ "dct_dwt": {
134
+ "full_name": "Combined DCT-DWT",
135
+ "description": "The algorithm watermarks a given image using a combination of the Discrete Wavelet Transform (DWT) and the Discrete Cosine Transform (DCT). Performance evaluation results show that combining the two transforms improved the performance of the watermarking algorithms that are based solely on the DWT transform.",
136
+ "paper_link": "https://pdfs.semanticscholar.org/1c47/f281c00cffad4e30deff48a922553cb04d17.pdf",
137
+ # "github_link": "",
138
+ },
139
+ # Fill this in, these are autogenned
140
+ "cine": {
141
+ "full_name": "CINE-Watermarking",
142
+ "description": "A network inversion-based watermarking method for high-resolution images, offering strong robustness against various image transformations while maintaining visual quality.",
143
+ "paper_link": "https://arxiv.org/abs/2402.19414",
144
+ "github_link": "",
145
+ },
146
+ "mbrs": {
147
+ "full_name": "Model-Based Robust Steganography (MBRS)",
148
+ "description": "A deep learning approach for robust image steganography that maintains high image quality while being resilient to common image distortions.",
149
+ "paper_link": "https://arxiv.org/abs/2204.12677",
150
+ "github_link": "https://github.com/jzyustc/mbrs",
151
+ },
152
+ "videoseal": {
153
+ "full_name": "VideoSeal",
154
+ "description": "A neural video watermarking system designed to embed imperceptible watermarks that are robust against common video manipulations and processing operations.",
155
+ "paper_link": "https://arxiv.org/abs/2405.20977",
156
+ "github_link": "https://github.com/facebookresearch/audioseal",
157
+ },
158
+ "rivagan": {
159
+ "full_name": "RivaGAN",
160
+ "description": "A GAN-based approach for robust invisible video watermarking that maintains high visual quality while providing resistance against common video attacks and transformations.",
161
+ "paper_link": "https://arxiv.org/abs/2102.05551",
162
+ "github_link": "https://github.com/eyalnakar/RivaGAN",
163
+ },
164
+ }
frontend/.env.prod ADDED
@@ -0,0 +1 @@
 
 
1
+ VITE_API_SERVER_URL=""
frontend/dist/assets/{index-UqKblgA6.js → index-B4l7vkQT.js} RENAMED
The diff for this file is too large to render. See raw diff
 
frontend/dist/index.html CHANGED
@@ -5,7 +5,7 @@
5
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
  <title>🥇 Omni Seal Bench Watermarking Leaderboard</title>
8
- <script type="module" crossorigin src="/assets/index-UqKblgA6.js"></script>
9
  <link rel="stylesheet" crossorigin href="/assets/index-CUEVu_CX.css">
10
  </head>
11
  <body>
 
5
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
  <title>🥇 Omni Seal Bench Watermarking Leaderboard</title>
8
+ <script type="module" crossorigin src="/assets/index-B4l7vkQT.js"></script>
9
  <link rel="stylesheet" crossorigin href="/assets/index-CUEVu_CX.css">
10
  </head>
11
  <body>
frontend/src/API.ts CHANGED
@@ -36,6 +36,13 @@ class API {
36
  if (!response.ok) throw new Error('Failed to fetch datasets')
37
  return response.json()
38
  }
 
 
 
 
 
 
 
39
  }
40
 
41
  export default API
 
36
  if (!response.ok) throw new Error('Failed to fetch datasets')
37
  return response.json()
38
  }
39
+
40
+ // Fetch descriptions and model descriptions from the backend
41
+ static async fetchDescriptions(): Promise<{ descriptions: any; model_descriptions: any }> {
42
+ const response = await fetch(VITE_API_SERVER_URL + '/descriptions')
43
+ if (!response.ok) throw new Error('Failed to fetch descriptions')
44
+ return response.json()
45
+ }
46
  }
47
 
48
  export default API
frontend/src/App.tsx CHANGED
@@ -10,6 +10,7 @@ import {
10
  import LeaderboardPage from './components/LeaderboardPage'
11
  import Examples from './components/Examples'
12
  import Docs from './components/Docs'
 
13
 
14
  const TABS = [
15
  { label: 'Audio', type: 'audio-leaderboard', path: '/audio-leaderboard' },
@@ -44,6 +45,11 @@ function AppContent() {
44
  const location = useLocation()
45
  const [theme, setTheme] = useState<'dark' | 'light'>('dark')
46
 
 
 
 
 
 
47
  useEffect(() => {
48
  document.documentElement.setAttribute('data-theme', theme)
49
  }, [theme])
 
10
  import LeaderboardPage from './components/LeaderboardPage'
11
  import Examples from './components/Examples'
12
  import Docs from './components/Docs'
13
+ import Descriptions from './Descriptions'
14
 
15
  const TABS = [
16
  { label: 'Audio', type: 'audio-leaderboard', path: '/audio-leaderboard' },
 
45
  const location = useLocation()
46
  const [theme, setTheme] = useState<'dark' | 'light'>('dark')
47
 
48
+ // Load descriptions on app load
49
+ useEffect(() => {
50
+ Descriptions.getInstance().load()
51
+ }, [])
52
+
53
  useEffect(() => {
54
  document.documentElement.setAttribute('data-theme', theme)
55
  }, [theme])
frontend/src/Descriptions.ts ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import API from './API'
2
+
3
+ class Descriptions {
4
+ private static instance: Descriptions | null = null
5
+ private descriptions: Record<string, any> = {}
6
+ private modelDescriptions: Record<string, any> = {}
7
+ private loaded: boolean = false
8
+ private loadingPromise: Promise<void> | null = null
9
+
10
+ private constructor() {}
11
+
12
+ static getInstance(): Descriptions {
13
+ if (!Descriptions.instance) {
14
+ Descriptions.instance = new Descriptions()
15
+ }
16
+ return Descriptions.instance
17
+ }
18
+
19
+ async load(): Promise<void> {
20
+ if (this.loaded) return
21
+ if (this.loadingPromise) return this.loadingPromise
22
+ this.loadingPromise = API.fetchDescriptions().then((data) => {
23
+ this.descriptions = data.descriptions || {}
24
+ this.modelDescriptions = data.model_descriptions || {}
25
+ this.loaded = true
26
+ })
27
+ return this.loadingPromise
28
+ }
29
+
30
+ getFullName(name: string): string | undefined {
31
+ return this.descriptions[name]?.full_name
32
+ }
33
+
34
+ getDescription(name: string): string | undefined {
35
+ return this.descriptions[name]?.description
36
+ }
37
+
38
+ getUrl(name: string): string | undefined {
39
+ return this.descriptions[name]?.link
40
+ }
41
+
42
+ getModelDescription(name: string): string | undefined {
43
+ return this.modelDescriptions[name]?.description
44
+ }
45
+
46
+ getModelFullName(name: string): string | undefined {
47
+ return this.modelDescriptions[name]?.full_name
48
+ }
49
+
50
+ getModelPaperUrl(name: string): string | undefined {
51
+ return this.modelDescriptions[name]?.paper_link
52
+ }
53
+
54
+ getModelGithubUrl(name: string): string | undefined {
55
+ return this.modelDescriptions[name]?.github_link
56
+ }
57
+ }
58
+
59
+ export default Descriptions