-
Notifications
You must be signed in to change notification settings - Fork 5
/
AbstractField.java
132 lines (106 loc) · 4.73 KB
/
AbstractField.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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package org.genericsystem.cv.classifier;
import java.text.Normalizer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.genericsystem.cv.Img;
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.core.Scalar;
import org.opencv.imgproc.Imgproc;
import org.opencv.utils.Converters;
public abstract class AbstractField {
protected final Rect rect;
protected final Point center;
protected Map<String, Integer> labels;
protected Optional<String> consolidated;
protected long attempts;
public AbstractField(Rect rect) {
this.rect = rect;
this.labels = new HashMap<>();
this.consolidated = Optional.empty();
this.center = new Point(rect.x + rect.width / 2, rect.y + rect.height / 2);
this.attempts = 0;
}
public void merge(AbstractField field) {
field.getLabels().entrySet().forEach(entry -> labels.merge(entry.getKey(), entry.getValue(), Integer::sum));
consolidated = field.getConsolidated(); // TODO: attempt to merge 2 optionals, or compute again the consolidated text from the labels
attempts += field.getAttempts();
}
public void merge(List<AbstractField> fields) {
fields.forEach(f -> this.merge(f));
}
public void draw(Img stabilizedDisplay) {
Imgproc.rectangle(stabilizedDisplay.getSrc(), rect.tl(), rect.br(), new Scalar(0, 0, 255));
}
public void drawOcrPerspectiveInverse(Img display, Mat homography, Scalar color, int thickness) {
if (isOnDisplay(display)) {
List<Point> points = Arrays.asList(center, new Point(rect.x, rect.y), new Point(rect.x + rect.width - 1, rect.y), new Point(rect.x + rect.width - 1, rect.y + rect.height - 1), new Point(rect.x, rect.y + rect.height - 1));
MatOfPoint2f results = new MatOfPoint2f();
Core.perspectiveTransform(Converters.vector_Point2f_to_Mat(points), results, homography);
Point[] targets = results.toArray();
Imgproc.line(display.getSrc(), targets[1], targets[2], color, thickness);
Imgproc.line(display.getSrc(), targets[2], targets[3], color, thickness);
Imgproc.line(display.getSrc(), targets[3], targets[4], color, thickness);
Imgproc.line(display.getSrc(), targets[4], targets[1], color, thickness);
Point topCenter = new Point((targets[1].x + targets[2].x) / 2, (targets[1].y + targets[2].y) / 2);
double l = Math.sqrt(Math.pow(targets[1].x - topCenter.x, 2) + Math.pow(targets[1].y - topCenter.y, 2));
Imgproc.line(display.getSrc(), new Point(topCenter.x, topCenter.y - 2), new Point(topCenter.x, topCenter.y - 20), new Scalar(0, 255, 0), 1);
Imgproc.putText(display.getSrc(), Normalizer.normalize(consolidated.orElse(""), Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", ""), new Point(topCenter.x - l, topCenter.y - 22), Core.FONT_HERSHEY_TRIPLEX, 0.45, new Scalar(0, 255, 0), 1);
}
}
public Rect getLargeRect(Img imgRoot, double deltaW, double deltaH) {
int adjustW = 3 + Double.valueOf(Math.floor(rect.width * deltaW)).intValue();
int adjustH = 3 + Double.valueOf(Math.floor(rect.height * deltaH)).intValue();
Point tl = new Point(rect.tl().x - adjustW > 0 ? rect.tl().x - adjustW : 0, rect.tl().y - adjustH > 0 ? rect.tl().y - adjustH : 0);
Point br = new Point(rect.br().x + adjustW > imgRoot.width() ? imgRoot.width() : rect.br().x + adjustW, rect.br().y + adjustH > imgRoot.height() ? imgRoot.height() : rect.br().y + adjustH);
return new Rect(tl, br);
}
public boolean contains(Point center) {
return Math.sqrt(Math.pow(this.center.x - center.x, 2) + Math.pow(this.center.y - center.y, 2)) <= 10;
}
public boolean isOverlapping(AbstractField other) {
// Consider overlapping as soon as a rectangle contains one of the corners of the other
Rect otherRect = other.getRect();
boolean bool1 = rect.contains(otherRect.tl()) || rect.contains(otherRect.br());
boolean bool2 = otherRect.contains(rect.tl()) || otherRect.contains(rect.br());
return bool1 || bool2;
}
public boolean isOnDisplay(Img display) {
return rect.br().x > 0 && rect.br().y > 0;
}
public boolean needMoreAttempts() {
return getLabelsSize() < 20;
}
public boolean isConsolidated() {
return consolidated.isPresent();
}
public boolean needOcr() {
return !isConsolidated() || needMoreAttempts();
}
public abstract void ocr(Img rootImg);
protected abstract void consolidateOcr();
public Map<String, Integer> getLabels() {
return labels;
}
public int getLabelsSize() {
return labels.entrySet().stream().mapToInt(entry -> entry.getValue()).sum();
}
public Optional<String> getConsolidated() {
return consolidated;
}
public long getAttempts() {
return attempts;
}
public Point getCenter() {
return center;
}
public Rect getRect() {
return rect;
}
}