fix(dewarp): change manual slider to percentage (0-200%) instead of raw multiplier

The old -3.0 to +3.0 scale multiplied the full displacement map (up to ~79px)
directly, causing extreme distortion at values >1. New slider:
- 0% = no correction
- 100% = auto-detected correction (default)
- 200% = double correction
- Step size: 5%

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-02-26 18:10:34 +01:00
parent fb496c5e34
commit ff2bb79a91
3 changed files with 16 additions and 16 deletions

View File

@@ -29,7 +29,7 @@ export function DewarpControls({
onNext, onNext,
isApplying, isApplying,
}: DewarpControlsProps) { }: DewarpControlsProps) {
const [manualScale, setManualScale] = useState(0) const [manualScale, setManualScale] = useState(100)
const [gtFeedback, setGtFeedback] = useState<'correct' | 'incorrect' | null>(null) const [gtFeedback, setGtFeedback] = useState<'correct' | 'incorrect' | null>(null)
const [gtNotes, setGtNotes] = useState('') const [gtNotes, setGtNotes] = useState('')
const [gtSaved, setGtSaved] = useState(false) const [gtSaved, setGtSaved] = useState(false)
@@ -94,22 +94,22 @@ export function DewarpControls({
{/* Manual scale slider */} {/* Manual scale slider */}
{dewarpResult && ( {dewarpResult && (
<div className="bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 p-4"> <div className="bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 p-4">
<div className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Manuelle Staerke</div> <div className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Korrekturstaerke</div>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<span className="text-xs text-gray-400 w-8 text-right">-3.0</span> <span className="text-xs text-gray-400 w-8 text-right">0%</span>
<input <input
type="range" type="range"
min={-3} min={0}
max={3} max={200}
step={0.1} step={5}
value={manualScale} value={manualScale}
onChange={(e) => setManualScale(parseFloat(e.target.value))} onChange={(e) => setManualScale(parseInt(e.target.value))}
className="flex-1 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700 accent-teal-500" className="flex-1 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700 accent-teal-500"
/> />
<span className="text-xs text-gray-400 w-8">+3.0</span> <span className="text-xs text-gray-400 w-10">200%</span>
<span className="font-mono text-sm w-14 text-right">{manualScale.toFixed(1)}</span> <span className="font-mono text-sm w-14 text-right">{manualScale}%</span>
<button <button
onClick={() => onManualDewarp(manualScale)} onClick={() => onManualDewarp(manualScale / 100)}
disabled={isApplying} disabled={isApplying}
className="px-3 py-1.5 text-sm bg-teal-600 text-white rounded-md hover:bg-teal-700 disabled:opacity-50 transition-colors" className="px-3 py-1.5 text-sm bg-teal-600 text-white rounded-md hover:bg-teal-700 disabled:opacity-50 transition-colors"
> >
@@ -117,7 +117,7 @@ export function DewarpControls({
</button> </button>
</div> </div>
<p className="text-xs text-gray-400 mt-1"> <p className="text-xs text-gray-400 mt-1">
0 = keine Korrektur, positiv = nach rechts entzerren, negativ = nach links 100% = automatisch erkannte Korrektur, 0% = keine, 200% = doppelt so stark
</p> </p>
</div> </div>
)} )}

View File

@@ -668,13 +668,13 @@ def dewarp_image_manual(img: np.ndarray, displacement_map: np.ndarray,
Args: Args:
img: BGR image (deskewed, before dewarp). img: BGR image (deskewed, before dewarp).
displacement_map: The displacement map from auto-dewarp. displacement_map: The displacement map from auto-dewarp.
scale: Manual scale factor (-3.0 to +3.0). scale: Fraction of auto-detected correction (0.0 = none, 1.0 = auto, 2.0 = double).
Returns: Returns:
Corrected image. Corrected image.
""" """
scale = max(-3.0, min(3.0, scale)) scale = max(0.0, min(2.0, scale))
if abs(scale) < 0.01: if scale < 0.01:
return img return img
return _apply_displacement_map(img, displacement_map, scale=scale) return _apply_displacement_map(img, displacement_map, scale=scale)

View File

@@ -400,9 +400,9 @@ async def manual_dewarp(session_id: str, req: ManualDewarpRequest):
if deskewed_bgr is None: if deskewed_bgr is None:
raise HTTPException(status_code=400, detail="Deskew must be completed before dewarp") raise HTTPException(status_code=400, detail="Deskew must be completed before dewarp")
scale = max(-3.0, min(3.0, req.scale)) scale = max(0.0, min(2.0, req.scale))
if displacement_map is None or abs(scale) < 0.01: if displacement_map is None or scale < 0.01:
# No displacement map or zero scale — use deskewed as-is # No displacement map or zero scale — use deskewed as-is
dewarped_bgr = deskewed_bgr dewarped_bgr = deskewed_bgr
else: else: