imagePreprocessor.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // server/utils/imagePreprocessor.js
  2. import sharp from 'sharp';
  3. class ImagePreprocessor {
  4. constructor() {
  5. this.tempDir = './temp/processed';
  6. }
  7. async preprocessWithPadding(imagePath, config) {
  8. try {
  9. const metadata = await sharp(imagePath).metadata();
  10. // 减少填充,避免过度改变图像
  11. const minPadding = 30;
  12. const paddingX = Math.max(minPadding, Math.floor(metadata.width * 0.05));
  13. const paddingY = Math.max(minPadding, Math.floor(metadata.height * 0.05));
  14. const paddedWidth = metadata.width + paddingX * 2;
  15. const paddedHeight = metadata.height + paddingY * 2;
  16. const paddedBuffer = await sharp(imagePath)
  17. .extend({
  18. top: paddingY,
  19. bottom: paddingY,
  20. left: paddingX,
  21. right: paddingX,
  22. background: { r: 255, g: 255, b: 255 }
  23. })
  24. .png()
  25. .toBuffer();
  26. const { width, height } = this.resizeForDetection({
  27. width: paddedWidth,
  28. height: paddedHeight
  29. }, config);
  30. const resizedBuffer = await sharp(paddedBuffer)
  31. .resize(width, height)
  32. .png()
  33. .toBuffer();
  34. console.log(`🖼️ 图像预处理完成: ${metadata.width}x${metadata.height} -> ${width}x${height}`);
  35. return {
  36. processedImage: {
  37. buffer: resizedBuffer,
  38. width,
  39. height,
  40. originalWidth: metadata.width,
  41. originalHeight: metadata.height,
  42. paddedWidth: paddedWidth,
  43. paddedHeight: paddedHeight,
  44. paddingX,
  45. paddingY,
  46. scaleX: paddedWidth / width,
  47. scaleY: paddedHeight / height
  48. }
  49. };
  50. } catch (error) {
  51. console.error('预处理错误:', error);
  52. throw error;
  53. }
  54. }
  55. resizeForDetection(metadata, config) {
  56. const { width, height } = metadata;
  57. const limitSideLen = config.detLimitSideLen || 960;
  58. let ratio = 1;
  59. if (Math.max(width, height) > limitSideLen) {
  60. ratio = limitSideLen / Math.max(width, height);
  61. }
  62. const newWidth = Math.floor(width * ratio);
  63. const newHeight = Math.floor(height * ratio);
  64. return {
  65. width: Math.max(32, Math.floor(newWidth / 32) * 32),
  66. height: Math.max(32, Math.floor(newHeight / 32) * 32)
  67. };
  68. }
  69. async getImageInfo(imagePath) {
  70. try {
  71. const metadata = await sharp(imagePath).metadata();
  72. return {
  73. width: metadata.width || 0,
  74. height: metadata.height || 0,
  75. format: metadata.format || 'unknown',
  76. processed: false
  77. };
  78. } catch (error) {
  79. return {
  80. width: 0,
  81. height: 0,
  82. format: 'unknown',
  83. processed: false
  84. };
  85. }
  86. }
  87. }
  88. export default ImagePreprocessor;