Skip to content

Commit 563da6c

Browse files
committed
add LucidNFT
1 parent 2560377 commit 563da6c

3 files changed

Lines changed: 131 additions & 91 deletions

File tree

LucidNFT/index.html

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ <h2>Method Overview</h2>
7777
</div>
7878
<div class="table-wrapper">
7979
<table class="table-consistency">
80+
<caption>Cosine similarity between LR-HR image pairs under correct pairing and cross-bench swapped pairing. LucidConsistency improves alignment on correctly paired data while maintaining low similarity under mismatched pairing.</caption>
8081
<thead>
8182
<tr>
8283
<th>Domain</th>
@@ -116,9 +117,6 @@ <h2>Method Overview</h2>
116117
</tr>
117118
</tbody>
118119
</table>
119-
<div class="table-caption">
120-
<span class="table-number">Table 2:</span> Cosine similarity between LR-HR image pairs under correct pairing and cross-bench swapped pairing. LucidConsistency improves alignment on correctly paired data while maintaining low similarity under mismatched pairing.
121-
</div>
122120
</div>
123121
</section>
124122

@@ -131,6 +129,7 @@ <h2>LucidLR Dataset</h2>
131129
</div>
132130
<div class="table-wrapper">
133131
<table class="table-dataset">
132+
<caption>Comparison of representative real-world datasets used in Real-ISR. Existing datasets are mainly designed for benchmarking and contain limited samples, while LucidLR provides large-scale real-world degradations suitable for preference-optimization-based training.</caption>
134133
<thead>
135134
<tr>
136135
<th>Dataset</th>
@@ -171,9 +170,6 @@ <h2>LucidLR Dataset</h2>
171170
</tr>
172171
</tbody>
173172
</table>
174-
<div class="table-caption">
175-
<span class="table-number">Table 1:</span> Comparison of representative real-world datasets used in Real-ISR. Existing datasets are mainly designed for benchmarking and contain limited samples, while LucidLR provides large-scale real-world degradations suitable for preference-optimization-based training.
176-
</div>
177173
</div>
178174
</section>
179175

@@ -200,6 +196,7 @@ <h2>Results</h2>
200196
<h3>Quantitative Results</h3>
201197
<div class="table-container">
202198
<table>
199+
<caption>Quantitative comparison with state-of-the-art Real-ISR methods on RealLQ250, DRealSR, and RealSR. Higher is better for all metrics except NIQE. Values in the last column show improvements relative to the LucidFlux baseline.</caption>
203200
<thead>
204201
<tr>
205202
<th rowspan="2">Benchmark</th>
@@ -626,9 +623,6 @@ <h3>Quantitative Results</h3>
626623
</tbody>
627624
</table>
628625
</div>
629-
<div class="table-caption">
630-
<span class="table-number">Table 3:</span> Quantitative comparison with state-of-the-art Real-ISR methods on RealLQ250, DRealSR, and RealSR. Higher is better for all metrics except NIQE. Values in the last column show improvements relative to the LucidFlux baseline.
631-
</div>
632626
</div>
633627
</section>
634628

@@ -669,22 +663,36 @@ <h2>Gallery</h2>
669663
<button class="gallery-modal__close" type="button" aria-label="Close" data-gallery-close>&times;</button>
670664
<div class="gallery-modal__header">
671665
<div class="gallery-modal__title" id="gallery-modal-title">Example</div>
672-
<div class="gallery-modal__toggles" role="tablist" aria-label="Choose output">
673-
<button class="gallery-toggle active" type="button" data-after="base" aria-selected="true">LucidFlux</button>
674-
<button class="gallery-toggle" type="button" data-after="nft" aria-selected="false">LucidFlux(+LucidNFT)</button>
666+
</div>
667+
668+
<div class="gallery-comparison-block">
669+
<div class="gallery-comparison-title">LQ vs LucidFlux</div>
670+
<div class="image-comparison gallery-comparison" id="gallery-comparison-base">
671+
<img src="" alt="Before (LQ input)" class="before-image" id="gallery-before-base">
672+
<img src="" alt="After (LucidFlux output)" class="after-image" id="gallery-after-base">
673+
<div class="comparison-slider" id="gallery-slider-base" aria-label="Comparison slider (LucidFlux)">
674+
<div class="slider-handle">
675+
<div class="slider-arrow">◀ ▶</div>
676+
</div>
677+
</div>
678+
<div class="compare-tag before">LQ</div>
679+
<div class="compare-tag after">LucidFlux</div>
675680
</div>
676681
</div>
677682

678-
<div class="image-comparison gallery-comparison" id="gallery-comparison">
679-
<img src="" alt="Before (LQ input)" class="before-image" id="gallery-before">
680-
<img src="" alt="After output" class="after-image" id="gallery-after">
681-
<div class="comparison-slider" id="gallery-slider" aria-label="Comparison slider">
682-
<div class="slider-handle">
683-
<div class="slider-arrow">◀ ▶</div>
683+
<div class="gallery-comparison-block">
684+
<div class="gallery-comparison-title">LQ vs LucidFlux(+LucidNFT)</div>
685+
<div class="image-comparison gallery-comparison" id="gallery-comparison-nft">
686+
<img src="" alt="Before (LQ input)" class="before-image" id="gallery-before-nft">
687+
<img src="" alt="After (LucidFlux+LucidNFT output)" class="after-image" id="gallery-after-nft">
688+
<div class="comparison-slider" id="gallery-slider-nft" aria-label="Comparison slider (LucidFlux+LucidNFT)">
689+
<div class="slider-handle">
690+
<div class="slider-arrow">◀ ▶</div>
691+
</div>
684692
</div>
693+
<div class="compare-tag before">LQ</div>
694+
<div class="compare-tag after">LucidFlux(+LucidNFT)</div>
685695
</div>
686-
<div class="compare-tag before">LQ</div>
687-
<div class="compare-tag after" id="gallery-after-tag">LucidFlux</div>
688696
</div>
689697
</div>
690698
</div>

LucidNFT/script.js

Lines changed: 65 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -61,63 +61,82 @@ document.addEventListener('DOMContentLoaded', function() {
6161
function initGalleryModal() {
6262
const modal = document.getElementById('gallery-modal');
6363
const title = document.getElementById('gallery-modal-title');
64-
const comparison = document.getElementById('gallery-comparison');
65-
const slider = document.getElementById('gallery-slider');
66-
const beforeImg = document.getElementById('gallery-before');
67-
const afterImg = document.getElementById('gallery-after');
68-
const afterTag = document.getElementById('gallery-after-tag');
69-
const toggles = Array.from(modal.querySelectorAll('.gallery-toggle'));
64+
const baseComparison = document.getElementById('gallery-comparison-base');
65+
const baseSlider = document.getElementById('gallery-slider-base');
66+
const baseBefore = document.getElementById('gallery-before-base');
67+
const baseAfter = document.getElementById('gallery-after-base');
7068

71-
if (!modal || !comparison || !slider || !beforeImg || !afterImg) return;
69+
const nftComparison = document.getElementById('gallery-comparison-nft');
70+
const nftSlider = document.getElementById('gallery-slider-nft');
71+
const nftBefore = document.getElementById('gallery-before-nft');
72+
const nftAfter = document.getElementById('gallery-after-nft');
73+
74+
if (!modal || !baseComparison || !baseSlider || !baseBefore || !baseAfter || !nftComparison || !nftSlider || !nftBefore || !nftAfter) return;
7275

73-
let isDragging = false;
7476
let currentExample = null;
75-
let currentAfterKey = 'base';
76-
77-
function setAfterKey(key) {
78-
currentAfterKey = key;
79-
toggles.forEach(btn => {
80-
const active = btn.dataset.after === key;
81-
btn.classList.toggle('active', active);
82-
btn.setAttribute('aria-selected', active ? 'true' : 'false');
83-
});
77+
const dragState = {
78+
isDragging: false,
79+
active: null,
80+
};
8481

85-
if (!currentExample) return;
86-
const src = currentExample.dataset[key];
87-
afterImg.src = src;
88-
afterImg.alt = key === 'nft' ? 'LucidFlux(+LucidNFT) output' : 'LucidFlux output';
89-
afterTag.textContent = key === 'nft' ? 'LucidFlux(+LucidNFT)' : 'LucidFlux';
82+
function updateSlider(comparisonEl, sliderEl, afterEl, x) {
83+
const rect = comparisonEl.getBoundingClientRect();
84+
const percentage = Math.max(0, Math.min(100, ((x - rect.left) / rect.width) * 100));
85+
sliderEl.style.left = percentage + '%';
86+
afterEl.style.clipPath = `polygon(${percentage}% 0%, 100% 0%, 100% 100%, ${percentage}% 100%)`;
9087
}
9188

92-
function updateSlider(x) {
93-
const rect = comparison.getBoundingClientRect();
94-
const percentage = Math.max(0, Math.min(100, ((x - rect.left) / rect.width) * 100));
95-
slider.style.left = percentage + '%';
96-
afterImg.style.clipPath = `polygon(${percentage}% 0%, 100% 0%, 100% 100%, ${percentage}% 100%)`;
89+
function initComparison(comparisonEl, sliderEl, afterEl) {
90+
sliderEl.addEventListener('mousedown', (e) => {
91+
dragState.isDragging = true;
92+
dragState.active = { comparisonEl, sliderEl, afterEl };
93+
e.preventDefault();
94+
});
95+
96+
sliderEl.addEventListener('touchstart', (e) => {
97+
dragState.isDragging = true;
98+
dragState.active = { comparisonEl, sliderEl, afterEl };
99+
e.preventDefault();
100+
}, { passive: false });
101+
102+
comparisonEl.addEventListener('click', (e) => {
103+
if (e.target === sliderEl || e.target.closest('.slider-handle')) return;
104+
updateSlider(comparisonEl, sliderEl, afterEl, e.clientX);
105+
});
97106
}
98107

99108
function openModal(exampleBtn) {
100109
currentExample = exampleBtn;
101110
const id = exampleBtn.dataset.example || '';
102111
title.textContent = `Example ${id}`;
103112

104-
beforeImg.src = exampleBtn.dataset.lq;
105-
beforeImg.alt = `Example ${id} LQ input`;
106-
setAfterKey('base');
113+
baseBefore.src = exampleBtn.dataset.lq;
114+
baseBefore.alt = `Example ${id} LQ input`;
115+
baseAfter.src = exampleBtn.dataset.base;
116+
117+
nftBefore.src = exampleBtn.dataset.lq;
118+
nftBefore.alt = `Example ${id} LQ input`;
119+
nftAfter.src = exampleBtn.dataset.nft;
107120

108121
modal.classList.add('is-open');
109122
modal.setAttribute('aria-hidden', 'false');
110123
document.body.style.overflow = 'hidden';
111124

112-
// Center slider after layout.
113-
requestAnimationFrame(() => updateSlider(comparison.getBoundingClientRect().left + comparison.getBoundingClientRect().width * 0.5));
125+
// Center sliders after layout.
126+
requestAnimationFrame(() => {
127+
const baseRect = baseComparison.getBoundingClientRect();
128+
updateSlider(baseComparison, baseSlider, baseAfter, baseRect.left + baseRect.width * 0.5);
129+
const nftRect = nftComparison.getBoundingClientRect();
130+
updateSlider(nftComparison, nftSlider, nftAfter, nftRect.left + nftRect.width * 0.5);
131+
});
114132
}
115133

116134
function closeModal() {
117135
modal.classList.remove('is-open');
118136
modal.setAttribute('aria-hidden', 'true');
119137
document.body.style.overflow = '';
120-
isDragging = false;
138+
dragState.isDragging = false;
139+
dragState.active = null;
121140
}
122141

123142
document.querySelectorAll('.lq-card').forEach(btn => {
@@ -128,41 +147,30 @@ document.addEventListener('DOMContentLoaded', function() {
128147
el.addEventListener('click', closeModal);
129148
});
130149

131-
toggles.forEach(btn => {
132-
btn.addEventListener('click', () => setAfterKey(btn.dataset.after));
133-
});
134-
135-
slider.addEventListener('mousedown', (e) => {
136-
isDragging = true;
137-
e.preventDefault();
138-
});
139-
slider.addEventListener('touchstart', (e) => {
140-
isDragging = true;
141-
e.preventDefault();
142-
}, { passive: false });
150+
initComparison(baseComparison, baseSlider, baseAfter);
151+
initComparison(nftComparison, nftSlider, nftAfter);
143152

144153
document.addEventListener('mousemove', (e) => {
145-
if (!isDragging) return;
146-
updateSlider(e.clientX);
154+
if (!dragState.isDragging || !dragState.active) return;
155+
updateSlider(dragState.active.comparisonEl, dragState.active.sliderEl, dragState.active.afterEl, e.clientX);
147156
});
148157
document.addEventListener('touchmove', (e) => {
149-
if (!isDragging) return;
150-
updateSlider(e.touches[0].clientX);
158+
if (!dragState.isDragging || !dragState.active) return;
159+
updateSlider(dragState.active.comparisonEl, dragState.active.sliderEl, dragState.active.afterEl, e.touches[0].clientX);
151160
}, { passive: true });
152161

153-
document.addEventListener('mouseup', () => { isDragging = false; });
154-
document.addEventListener('touchend', () => { isDragging = false; });
155-
156-
comparison.addEventListener('click', (e) => {
157-
if (e.target === slider || e.target.closest('.slider-handle')) return;
158-
updateSlider(e.clientX);
162+
document.addEventListener('mouseup', () => {
163+
dragState.isDragging = false;
164+
dragState.active = null;
165+
});
166+
document.addEventListener('touchend', () => {
167+
dragState.isDragging = false;
168+
dragState.active = null;
159169
});
160170

161171
document.addEventListener('keydown', (e) => {
162172
if (!modal.classList.contains('is-open')) return;
163173
if (e.key === 'Escape') closeModal();
164-
if (e.key === 'ArrowLeft') setAfterKey('base');
165-
if (e.key === 'ArrowRight') setAfterKey('nft');
166174
});
167175
}
168176

LucidNFT/styles.css

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,17 @@ body {
352352
flex-wrap: wrap;
353353
}
354354

355+
.gallery-comparison-block + .gallery-comparison-block {
356+
margin-top: 16px;
357+
}
358+
359+
.gallery-comparison-title {
360+
font-weight: 700;
361+
color: #333;
362+
margin: 6px 0 8px;
363+
text-align: center;
364+
}
365+
355366
.gallery-modal__title {
356367
font-weight: 800;
357368
font-size: 1.1em;
@@ -420,30 +431,30 @@ body {
420431
position: absolute;
421432
top: 0;
422433
bottom: 0;
423-
left: -1px;
424-
width: 2px;
425-
background: rgba(255, 255, 255, 0.92);
426-
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08);
434+
left: 0;
435+
width: 1px;
436+
background: rgba(255, 255, 255, 0.65);
437+
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.04);
427438
}
428439

429440
.slider-handle {
430441
position: absolute;
431442
top: 50%;
432-
left: -22px;
443+
left: -20px;
433444
transform: translateY(-50%);
434-
width: 44px;
435-
height: 44px;
445+
width: 40px;
446+
height: 40px;
436447
border-radius: 50%;
437-
background: rgba(255, 255, 255, 0.95);
438-
box-shadow: 0 10px 22px rgba(0, 0, 0, 0.18);
448+
background: rgba(255, 255, 255, 0.88);
449+
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.12);
439450
display: flex;
440451
align-items: center;
441452
justify-content: center;
442453
}
443454

444455
.slider-arrow {
445456
font-size: 12px;
446-
color: #333;
457+
color: rgba(17, 17, 17, 0.65);
447458
letter-spacing: 1px;
448459
user-select: none;
449460
}
@@ -498,11 +509,13 @@ body {
498509

499510
.table-wrapper caption {
500511
caption-side: top;
501-
text-align: left;
502-
font-weight: 600;
503-
color: #222;
512+
text-align: center;
513+
font-weight: 400;
514+
color: #666;
504515
margin-bottom: 10px;
505516
line-height: 1.5;
517+
font-size: 0.82em;
518+
font-style: italic;
506519
}
507520

508521
.table-wrapper th,
@@ -689,6 +702,17 @@ body {
689702
padding: 10px 0;
690703
}
691704

705+
.table-container caption {
706+
caption-side: top;
707+
text-align: center;
708+
font-weight: 400;
709+
color: #666;
710+
margin-bottom: 10px;
711+
line-height: 1.5;
712+
font-size: 0.82em;
713+
font-style: italic;
714+
}
715+
692716
.table-container table {
693717
border-collapse: collapse;
694718
width: 70%;
@@ -797,7 +821,7 @@ body {
797821

798822
/* Table number styling */
799823
.table-number {
800-
font-weight: bold;
824+
font-weight: 400;
801825
margin-right: 5px;
802826
}
803827

0 commit comments

Comments
 (0)