// server/utils/imagePreprocessor.js import sharp from 'sharp'; class ImagePreprocessor { constructor() { this.tempDir = './temp/processed'; } async preprocessWithPadding(imagePath, config) { try { const metadata = await sharp(imagePath).metadata(); // 减少填充,避免过度改变图像 const minPadding = 30; const paddingX = Math.max(minPadding, Math.floor(metadata.width * 0.05)); const paddingY = Math.max(minPadding, Math.floor(metadata.height * 0.05)); const paddedWidth = metadata.width + paddingX * 2; const paddedHeight = metadata.height + paddingY * 2; const paddedBuffer = await sharp(imagePath) .extend({ top: paddingY, bottom: paddingY, left: paddingX, right: paddingX, background: { r: 255, g: 255, b: 255 } }) .png() .toBuffer(); const { width, height } = this.resizeForDetection({ width: paddedWidth, height: paddedHeight }, config); const resizedBuffer = await sharp(paddedBuffer) .resize(width, height) .png() .toBuffer(); console.log(`🖼️ 图像预处理完成: ${metadata.width}x${metadata.height} -> ${width}x${height}`); return { processedImage: { buffer: resizedBuffer, width, height, originalWidth: metadata.width, originalHeight: metadata.height, paddedWidth: paddedWidth, paddedHeight: paddedHeight, paddingX, paddingY, scaleX: paddedWidth / width, scaleY: paddedHeight / height } }; } catch (error) { console.error('预处理错误:', error); throw error; } } resizeForDetection(metadata, config) { const { width, height } = metadata; const limitSideLen = config.detLimitSideLen || 960; let ratio = 1; if (Math.max(width, height) > limitSideLen) { ratio = limitSideLen / Math.max(width, height); } const newWidth = Math.floor(width * ratio); const newHeight = Math.floor(height * ratio); return { width: Math.max(32, Math.floor(newWidth / 32) * 32), height: Math.max(32, Math.floor(newHeight / 32) * 32) }; } async getImageInfo(imagePath) { try { const metadata = await sharp(imagePath).metadata(); return { width: metadata.width || 0, height: metadata.height || 0, format: metadata.format || 'unknown', processed: false }; } catch (error) { return { width: 0, height: 0, format: 'unknown', processed: false }; } } } export default ImagePreprocessor;