Spaces:
Running
Running
| const COORDINATE = '(\\d+(?:\\.\\d+)?)'; | |
| const HEADER_PATTERN = new RegExp(`^image_index\\s*=\\s*(\\d+)\\s+([^\\[\\]\\n]+?)\\s+\\[\\s*${COORDINATE}\\s*,\\s*${COORDINATE}\\s*,\\s*${COORDINATE}\\s*,\\s*${COORDINATE}\\s*\\]\\s*$`); | |
| function normalizeRegion(match, content, imageCount) { | |
| if (!content) return null; | |
| const [, rawImageIndex, rawLabel, ...rawCoordinates] = match; | |
| const imageId = Number(rawImageIndex); | |
| const label = rawLabel.trim(); | |
| let coordinates = rawCoordinates.map(Number); | |
| if (imageId < 0 || imageId >= imageCount || !label) return null; | |
| if (coordinates.every(value => value >= 0 && value <= 1)) { | |
| coordinates = coordinates.map(value => Math.round(value * 1000)); | |
| } else if (coordinates.some(value => !Number.isInteger(value) || value < 0 || value > 1000)) { | |
| return null; | |
| } | |
| const [xmin, ymin, xmax, ymax] = coordinates; | |
| if (xmax <= xmin || ymax <= ymin) return null; | |
| return { imageId, label, type: 'box', coordinates, content }; | |
| } | |
| export function parseDocumentRegions(text, imageCount) { | |
| if (!Number.isInteger(imageCount) || imageCount < 1 || typeof text !== 'string' || !text.trim()) return null; | |
| const lines = text.trim().replace(/\r\n?/g, '\n').split('\n'); | |
| const regions = []; | |
| let currentMatch = null; | |
| let contentLines = []; | |
| let sawHeader = false; | |
| const finishCurrentRegion = () => { | |
| if (!currentMatch) return; | |
| const region = normalizeRegion(currentMatch, contentLines.join('\n').trim(), imageCount); | |
| if (region) regions.push(region); | |
| }; | |
| for (const line of lines) { | |
| const match = HEADER_PATTERN.exec(line); | |
| if (match) { | |
| if (currentMatch) { | |
| finishCurrentRegion(); | |
| } else if (!sawHeader && contentLines.some(value => value.trim())) { | |
| return null; | |
| } | |
| sawHeader = true; | |
| currentMatch = match; | |
| contentLines = []; | |
| } else if (/^\s*image_index\b/.test(line)) { | |
| finishCurrentRegion(); | |
| sawHeader = true; | |
| currentMatch = null; | |
| contentLines = []; | |
| } else if (currentMatch || !sawHeader) { | |
| contentLines.push(line); | |
| } else { | |
| // Ignore content belonging to an incomplete or malformed region while | |
| // retaining complete regions that were already parsed. | |
| } | |
| } | |
| finishCurrentRegion(); | |
| return regions.length ? regions : null; | |
| } | |