-
Notifications
You must be signed in to change notification settings - Fork 5
/
Fields.java
110 lines (96 loc) · 3.73 KB
/
Fields.java
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package org.genericsystem.cv.classifier;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.genericsystem.cv.Img;
import org.genericsystem.cv.utils.ParallelTasks;
import org.genericsystem.cv.utils.RectToolsMapper;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.utils.Converters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Fields extends AbstractFields<Field> {
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static ThreadLocalRandom rand = ThreadLocalRandom.current();
private static final int MAX_DELETE_UNMERGED = 5;
private static final int OCR_TIMEOUT = 100;
public void reset() {
fields = new ArrayList<>();
}
public void merge(List<Rect> newRects, Mat fieldsHomography) {
List<Field> oldFields = restabilizeFields(fieldsHomography);
logger.info("oldFields transformed ({})", oldFields.size());
fields = newRects.stream().map(Field::new).collect(Collectors.toList());
Iterator<Field> it = oldFields.iterator();
while (it.hasNext()) {
Field currentOldField = it.next();
List<Field> matches = findMatchingFieldsWithConfidence(currentOldField, 0.7);
// List<Field> matches = findClusteredFields(currentOldField, 0.1);
if (!matches.isEmpty()) {
currentOldField.getConsolidated().ifPresent(s -> logger.info("Merged: {}", s));
if (matches.size() > 1)
logger.error("Multiple matches: {}", matches.size());
matches.forEach(f -> {
double mergeArea = RectToolsMapper.inclusiveArea(f.getRect(), currentOldField.getRect());
logger.info("Merging two fields with {} common area", String.format("%.3f", mergeArea));
f.merge(currentOldField);
f.resetDeadCounter();
});
it.remove();
}
}
// Increment the deadCounter in old fields that were not merged
oldFields.forEach(f -> f.incrementDeadCounter());
oldFields.removeIf(f -> f.deadCounter >= MAX_DELETE_UNMERGED);
// At this stage, add all the remaining fields still in oldFields
fields.addAll(oldFields);
}
private List<Field> restabilizeFields(Mat homography) {
List<Rect> virtualRects = fields.stream().map(AbstractField::getRect).map(rect -> findNewRect(rect, homography)).collect(Collectors.toList());
return IntStream.range(0, fields.size()).mapToObj(i -> {
Field f = new Field(virtualRects.get(i));
f.merge(fields.get(i));
return f;
}).collect(Collectors.toList());
}
private Rect findNewRect(Rect rect, Mat homography) {
List<Point> points = restabilize(Arrays.asList(rect.tl(), rect.br()), homography);
return new Rect(points.get(0), points.get(1));
}
private List<Point> restabilize(List<Point> originals, Mat homography) {
Mat original = Converters.vector_Point2f_to_Mat(originals);
MatOfPoint2f results = new MatOfPoint2f();
Core.perspectiveTransform(original, results, homography);
List<Point> res = results.toList();
return res;
}
@Override
public void consolidateOcr(Img rootImg) {
long TS = System.currentTimeMillis();
while (System.currentTimeMillis() - TS <= OCR_TIMEOUT) {
ParallelTasks tasks = new ParallelTasks();
Set<Integer> indexes = new HashSet<>();
while (indexes.size() < tasks.getCounter()) {
int idx = rand.nextInt(size());
if (indexes.add(idx))
tasks.add(() -> fields.get(idx).ocr(rootImg));
}
try {
tasks.run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}