File size: 2,315 Bytes
6c30253
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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;
}