nomid2 commited on
Commit
a145779
·
verified ·
1 Parent(s): 3be483a

Upload imageProcessor.js

Browse files
Files changed (1) hide show
  1. src/lib/imageProcessor.js +127 -22
src/lib/imageProcessor.js CHANGED
@@ -6,13 +6,18 @@ const sharp = require('sharp')
6
  */
7
  class ImageProcessor {
8
  constructor() {
9
- // 长图阈值:高度超过宽度*2.5倍(更合理的阈值)
10
- this.LONG_IMAGE_RATIO = 2.5
11
  // 重叠像素范围
12
  this.OVERLAP_MIN = 50
13
  this.OVERLAP_MAX = 100
14
  // 默认重叠像素
15
  this.DEFAULT_OVERLAP = 75
 
 
 
 
 
16
  }
17
 
18
  /**
@@ -48,7 +53,71 @@ class ImageProcessor {
48
  }
49
 
50
  /**
51
- * 计算切割参数
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  * @param {number} width - 图片宽度
53
  * @param {number} height - 图片高度
54
  * @param {number} overlap - 重叠像素数
@@ -56,26 +125,39 @@ class ImageProcessor {
56
  */
57
  calculateCropRegions(width, height, overlap = this.DEFAULT_OVERLAP) {
58
  const regions = []
59
- const maxHeight = width * this.LONG_IMAGE_RATIO // 每个片段的最大高度
60
-
 
 
 
 
 
61
  let currentTop = 0
62
  let segmentIndex = 0
63
-
64
- while (currentTop < height) {
65
  const remainingHeight = height - currentTop
66
- let segmentHeight = Math.min(maxHeight, remainingHeight)
67
-
68
  // 如果不是第一个片段,需要向上扩展重叠区域
69
  if (segmentIndex > 0) {
70
- currentTop = Math.max(0, currentTop - overlap)
71
- segmentHeight = Math.min(maxHeight + overlap, height - currentTop)
 
72
  }
73
-
74
  // 如果不是最后一个片段,需要向下扩展重叠区域
75
- if (currentTop + segmentHeight < height) {
76
- segmentHeight = Math.min(segmentHeight + overlap, height - currentTop)
 
 
77
  }
78
-
 
 
 
 
 
79
  regions.push({
80
  top: currentTop,
81
  left: 0,
@@ -83,14 +165,30 @@ class ImageProcessor {
83
  height: segmentHeight,
84
  segmentIndex: segmentIndex,
85
  isFirst: segmentIndex === 0,
86
- isLast: currentTop + segmentHeight >= height
 
87
  })
88
-
89
- // 移动到下一个片段的起始位置(考虑重叠)
90
- currentTop += (segmentIndex === 0 ? maxHeight : maxHeight - overlap)
 
 
 
 
 
 
 
 
 
91
  segmentIndex++
 
 
 
 
 
92
  }
93
-
 
94
  return regions
95
  }
96
 
@@ -172,13 +270,18 @@ class ImageProcessor {
172
  }
173
 
174
  const { width, height, format } = detection
 
 
 
175
  const regions = this.calculateCropRegions(width, height, overlap)
176
  const segments = []
177
 
178
  // 选择最优输出格式
179
  const outputFormat = this.getOptimalOutputFormat(format)
180
 
181
- console.log(`检测到长图 ${width}x${height} (${format}),切割 ${regions.length} 个片段,输出格式: ${outputFormat}`)
 
 
182
 
183
  for (const region of regions) {
184
  const sharpInstance = sharp(imageBuffer)
@@ -206,6 +309,7 @@ class ImageProcessor {
206
  segmentHeight: region.height,
207
  originalFormat: format,
208
  outputFormat: outputFormat,
 
209
  cropRegion: {
210
  top: region.top,
211
  left: region.left,
@@ -215,7 +319,8 @@ class ImageProcessor {
215
  }
216
  })
217
 
218
- console.log(`生成片段 ${region.segmentIndex + 1}/${regions.length}: ${region.width}x${region.height} (top: ${region.top})`)
 
219
  }
220
 
221
  return segments
 
6
  */
7
  class ImageProcessor {
8
  constructor() {
9
+ // 长图阈值:高度超过宽度*3倍(更合理的阈值)
10
+ this.LONG_IMAGE_RATIO = 3
11
  // 重叠像素范围
12
  this.OVERLAP_MIN = 50
13
  this.OVERLAP_MAX = 100
14
  // 默认重叠像素
15
  this.DEFAULT_OVERLAP = 75
16
+
17
+ // 智能切割参数 - 针对模型识别效果优化
18
+ this.OPTIMAL_SEGMENT_HEIGHT = 3000 // 理想片段高度
19
+ this.MAX_SEGMENT_HEIGHT = 3500 // 最大片段高度
20
+ this.MIN_SEGMENT_HEIGHT = 2500 // 最小片段高度
21
  }
22
 
23
  /**
 
53
  }
54
 
55
  /**
56
+ * 计算最优片段高度
57
+ * @param {number} width - 图片宽度
58
+ * @param {number} height - 图片高度
59
+ * @param {number} overlap - 重叠像素数
60
+ * @returns {Object} 包含最优高度和片段数的对象
61
+ */
62
+ calculateOptimalSegmentHeight(width, height, overlap = this.DEFAULT_OVERLAP) {
63
+ // 如果图片高度小于最大片段高度,直接返回原高度
64
+ if (height <= this.MAX_SEGMENT_HEIGHT) {
65
+ return {
66
+ segmentHeight: height,
67
+ segmentCount: 1,
68
+ strategy: 'single_segment'
69
+ }
70
+ }
71
+
72
+ // 计算理想的片段数量(基于理想高度)
73
+ const idealSegmentCount = Math.ceil(height / this.OPTIMAL_SEGMENT_HEIGHT)
74
+
75
+ // 计算每个片段的理想高度(不考虑重叠)
76
+ const baseSegmentHeight = Math.floor(height / idealSegmentCount)
77
+
78
+ // 检查是否在合理范围内
79
+ if (baseSegmentHeight >= this.MIN_SEGMENT_HEIGHT && baseSegmentHeight <= this.MAX_SEGMENT_HEIGHT) {
80
+ return {
81
+ segmentHeight: baseSegmentHeight,
82
+ segmentCount: idealSegmentCount,
83
+ strategy: 'optimal_division'
84
+ }
85
+ }
86
+
87
+ // 如果理想高度太小,减少片段数量
88
+ if (baseSegmentHeight < this.MIN_SEGMENT_HEIGHT) {
89
+ const adjustedSegmentCount = Math.max(1, Math.floor(height / this.MIN_SEGMENT_HEIGHT))
90
+ const adjustedSegmentHeight = Math.floor(height / adjustedSegmentCount)
91
+
92
+ return {
93
+ segmentHeight: Math.min(adjustedSegmentHeight, this.MAX_SEGMENT_HEIGHT),
94
+ segmentCount: adjustedSegmentCount,
95
+ strategy: 'min_height_constraint'
96
+ }
97
+ }
98
+
99
+ // 如果理想高度太大,增加片段数量
100
+ if (baseSegmentHeight > this.MAX_SEGMENT_HEIGHT) {
101
+ const adjustedSegmentCount = Math.ceil(height / this.MAX_SEGMENT_HEIGHT)
102
+ const adjustedSegmentHeight = Math.floor(height / adjustedSegmentCount)
103
+
104
+ return {
105
+ segmentHeight: adjustedSegmentHeight,
106
+ segmentCount: adjustedSegmentCount,
107
+ strategy: 'max_height_constraint'
108
+ }
109
+ }
110
+
111
+ // 兜底策略:使用最大高度
112
+ return {
113
+ segmentHeight: this.MAX_SEGMENT_HEIGHT,
114
+ segmentCount: Math.ceil(height / this.MAX_SEGMENT_HEIGHT),
115
+ strategy: 'fallback'
116
+ }
117
+ }
118
+
119
+ /**
120
+ * 计算切割参数(智能自适应版本)
121
  * @param {number} width - 图片宽度
122
  * @param {number} height - 图片高度
123
  * @param {number} overlap - 重叠像素数
 
125
  */
126
  calculateCropRegions(width, height, overlap = this.DEFAULT_OVERLAP) {
127
  const regions = []
128
+
129
+ // 计算最优片段高度
130
+ const optimalConfig = this.calculateOptimalSegmentHeight(width, height, overlap)
131
+ const { segmentHeight: baseSegmentHeight, segmentCount, strategy } = optimalConfig
132
+
133
+ console.log(`[智能切割] 图片尺寸: ${width}x${height}, 策略: ${strategy}, 预计片段数: ${segmentCount}, 基础高度: ${baseSegmentHeight}`)
134
+
135
  let currentTop = 0
136
  let segmentIndex = 0
137
+
138
+ while (currentTop < height && segmentIndex < segmentCount * 2) { // 防止无限循环
139
  const remainingHeight = height - currentTop
140
+ let segmentHeight = Math.min(baseSegmentHeight, remainingHeight)
141
+
142
  // 如果不是第一个片段,需要向上扩展重叠区域
143
  if (segmentIndex > 0) {
144
+ const overlapTop = Math.min(overlap, currentTop)
145
+ currentTop = currentTop - overlapTop
146
+ segmentHeight = Math.min(baseSegmentHeight + overlapTop, height - currentTop)
147
  }
148
+
149
  // 如果不是最后一个片段,需要向下扩展重叠区域
150
+ const isLastSegment = (currentTop + segmentHeight >= height) || (segmentIndex >= segmentCount - 1)
151
+ if (!isLastSegment) {
152
+ const overlapBottom = Math.min(overlap, remainingHeight - segmentHeight)
153
+ segmentHeight = Math.min(segmentHeight + overlapBottom, height - currentTop)
154
  }
155
+
156
+ // 确保片段高度在合理范围内
157
+ segmentHeight = Math.max(segmentHeight, this.MIN_SEGMENT_HEIGHT)
158
+ segmentHeight = Math.min(segmentHeight, this.MAX_SEGMENT_HEIGHT)
159
+ segmentHeight = Math.min(segmentHeight, height - currentTop) // 不能超出图片边界
160
+
161
  regions.push({
162
  top: currentTop,
163
  left: 0,
 
165
  height: segmentHeight,
166
  segmentIndex: segmentIndex,
167
  isFirst: segmentIndex === 0,
168
+ isLast: currentTop + segmentHeight >= height,
169
+ strategy: strategy
170
  })
171
+
172
+ console.log(`[切割片段] 片段${segmentIndex + 1}: top=${currentTop}, height=${segmentHeight}, 范围=[${currentTop}, ${currentTop + segmentHeight}]`)
173
+
174
+ // 移动到下一个片段的起始位置
175
+ if (segmentIndex === 0) {
176
+ // 第一个片段:直接移动基础高度
177
+ currentTop += baseSegmentHeight
178
+ } else {
179
+ // 后续片段:移动基础高度减去重叠
180
+ currentTop += Math.max(baseSegmentHeight - overlap, 1)
181
+ }
182
+
183
  segmentIndex++
184
+
185
+ // 如果已经覆盖了整个图片,退出循环
186
+ if (currentTop >= height) {
187
+ break
188
+ }
189
  }
190
+
191
+ console.log(`[切割完成] 实际生成${regions.length}个片段`)
192
  return regions
193
  }
194
 
 
270
  }
271
 
272
  const { width, height, format } = detection
273
+
274
+ // 计算最优切割配置
275
+ const optimalConfig = this.calculateOptimalSegmentHeight(width, height, overlap)
276
  const regions = this.calculateCropRegions(width, height, overlap)
277
  const segments = []
278
 
279
  // 选择最优输出格式
280
  const outputFormat = this.getOptimalOutputFormat(format)
281
 
282
+ console.log(`检测到长图 ${width}x${height} (${format}),智能切割策略: ${optimalConfig.strategy}`)
283
+ console.log(`切割配置: 目标高度=${optimalConfig.segmentHeight}px, 预计片段=${optimalConfig.segmentCount}个, 实际片段=${regions.length}个`)
284
+ console.log(`输出格式: ${outputFormat}, 重叠像素: ${overlap}px`)
285
 
286
  for (const region of regions) {
287
  const sharpInstance = sharp(imageBuffer)
 
309
  segmentHeight: region.height,
310
  originalFormat: format,
311
  outputFormat: outputFormat,
312
+ strategy: region.strategy,
313
  cropRegion: {
314
  top: region.top,
315
  left: region.left,
 
319
  }
320
  })
321
 
322
+ const heightStatus = region.height <= 3000 ? '✓理想' : region.height <= 3500 ? '✓良好' : '⚠超限'
323
+ console.log(`生成片段 ${region.segmentIndex + 1}/${regions.length}: ${region.width}x${region.height} (${heightStatus}) [${region.top}-${region.top + region.height}]`)
324
  }
325
 
326
  return segments