-
Notifications
You must be signed in to change notification settings - Fork 0
/
Extractor.java
273 lines (231 loc) · 8.28 KB
/
Extractor.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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.core.Core;
import org.opencv.core.CvType;
public class Extractor {
private boolean verbose = true;
Size preferedSize = new Size(25,25);
private int paddingSize=2;
public Extractor() {
}
//Sort and align symbols in the source mat
public Mat OrderExpression(Mat source, List<MatOfPoint> contours) {
List<Mat> tRes = new ArrayList<Mat>();
int cols=0, rows=20;
for(int i=0; i< contours.size(); i++) {
Rect r = Imgproc.boundingRect(contours.get(i));
Mat m = new Mat(source, r);
if(m.size()!=preferedSize) {
m = ScaleMat(preferedSize, m);
}
tRes.add(m);
}
Mat Result = new Mat(source.size(),source.type());
Core.hconcat(tRes,Result);
return Result;
}
/*
* @description
* Takes Size preferedsize and Mat as parmeters
* if the axis are uneven, padding is added before scale operation.
* @return Mat, scaled and padded in one direction if necessary.
*/
public Mat ScaleMat(Size prefsize, Mat source) {
Mat result = new Mat();
Mat anew =source;
int diff;
//lite eksperieng som må taes vekk om det ikke fungerer!!! i DAG!
//Hvis bredde er mye større enn høyde, må vi legge til tilsvarende på høyde for å få en skikkelig skalering!!!
System.out.print("source:"+source.size()+" ");
if(source.width()>source.height()) {
diff = source.width()-source.height();
System.out.println("diff:"+diff);
Mat m = new Mat(new Size(source.width(),diff/2),0);
List<Mat> con = new ArrayList<Mat>();
con.add(m);
con.add(source);
con.add(m);
//Mat anew = new Mat();
Core.vconcat(con, anew);
}else if(source.width()>source.height()) {
diff = source.height()-source.width();
System.out.println("diff:"+diff);
Mat m = new Mat(new Size(source.height(),diff/2),0);
List<Mat> con = new ArrayList<Mat>();
con.add(m);
con.add(source);
con.add(m);
Core.hconcat(con, anew);
}
Imgproc.resize(anew, result, prefsize);// denne er ikke interpolert, det finnes en annen version av resize
System.out.println("new size: "+result.size());
return result;
}
public List<MatOfPoint> findContours(Mat contourSource){
List<MatOfPoint> contour = new ArrayList<MatOfPoint>();
Imgproc.GaussianBlur(contourSource, contourSource, new Size(3,3),0);
Imgproc.adaptiveThreshold(contourSource, contourSource, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C,Imgproc.THRESH_BINARY, 75,10);
org.opencv.core.Core.bitwise_not(contourSource, contourSource);
Imgproc.findContours(contourSource, contour,new Mat(), Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);
return contour;
}
public Mat ContourExtraction(Mat frame, List<MatOfPoint> contour) {
Mat target = new Mat();
try {
//contour = FilterContours(contour);
for(int i=0;i < contour.size();i++) {
Rect r = Imgproc.boundingRect(contour.get(i));
Mat mask = Mat.zeros(frame.size(), org.opencv.core.CvType.CV_8UC1);
Imgproc.drawContours(mask, contour, i, new Scalar(255), -1);// -1 CV_FILLED or core.FILLED
frame.copyTo(target, mask);
Imgproc.rectangle(target, r.tl(), r.br(), new Scalar(125));
if(verbose) {
System.out.println("Contour:"+i+" Position(x,y) "+r.x+","+r.y+"... H:"+r.height+" W: "+r.width);
}
}
}catch(Exception e) {
if(verbose) {
toLog("extractor.ContourExtraction-Error:",e.toString());}
}
return target;
}
public Mat addPadding(int pad, Mat toPad) {
Mat target = new Mat(toPad.rows()+pad, toPad.cols()+pad, toPad.depth());
Core.copyMakeBorder(toPad, target, pad, pad, pad, pad, Core.BORDER_ISOLATED);
return target;
}
/*
* Function should be removed, due to duplicate behaviour and functionality
*
*/
public List<Mat> ContourExtractionToListOfMat(Mat frame, List<MatOfPoint> contour, boolean drawSquared,boolean addPadding) {
List<Mat> newlist = new ArrayList<Mat>();
try {
//Mat m = new Mat(source, r);
//contour = FilterContours(contour);
for(int i=0;i < contour.size();i++) {
Rect r = Imgproc.boundingRect(contour.get(i));
System.out.println(String.valueOf(r.width/r.height));
Mat mask = Mat.zeros(frame.size(), org.opencv.core.CvType.CV_8UC1);
Imgproc.drawContours(mask, contour, i, new Scalar(255), -1);// -1 CV_FILLED or core.FILLED
//Mat target = new Mat(new Size(r.width,r.height),CvType.CV_8UC1);
Mat target = new Mat(frame, r);
if(target.size()!=preferedSize) {
target = ScaleMat(preferedSize, target);
}
//frame.copyTo(target, mask);
if(drawSquared) {
Imgproc.rectangle(target, r.tl(), r.br(), new Scalar(125));
}
//add padding pixels on all sides of mat
if(addPadding) {
System.out.print("target width"+target.cols());
Mat co = new Mat(target.rows()+this.paddingSize, target.cols()+this.paddingSize, target.depth());
Core.copyMakeBorder(target, co, paddingSize, paddingSize, paddingSize, paddingSize, Core.BORDER_ISOLATED);
target = co;
System.out.println("target new width"+target.cols());
}
newlist.add(target);
if(verbose) {
System.out.println("Contour:"+i+" Position(x,y) "+r.x+","+r.y+"... H:"+r.height+" W: "+r.width);
}
}
}catch(Exception e) {
if(verbose) {
toLog("extractor.ContourExtraction-Error:",e.toString());}
}
return newlist;
}
public List<Mat> ContoursToListOfMat(Mat frame, List<MatOfPoint> contour) {
List<Mat> target = new ArrayList<Mat>();
try {
for(int i=0;i < contour.size();i++) {
Rect r = Imgproc.boundingRect(contour.get(i));
Mat t = frame.submat(r);
target.add(t);
if(verbose) {
System.out.println("Extracting "+i+" (x,y) "+r.x+","+r.y+"... H:"+r.height+" W: "+r.width);
}
}
}catch(Exception e) {
if(verbose) {
toLog("extractor.ContourExtraction-Error:",e.toString());}
}
return target;
}
void toLog(String source, String message) {
System.out.println("Source:"+source+" :"+message);
}
public static BufferedImage Mat2Img(Mat convert) {
try {
int type=-1;
int size = convert.channels() * convert.cols()*convert.rows();
byte[] buffer = new byte[size];
if(convert.channels()>1) {
type = BufferedImage.TYPE_3BYTE_BGR;
}else {
type = BufferedImage.TYPE_BYTE_GRAY;
}
BufferedImage bi = new BufferedImage(convert.cols(), convert.rows(), type);
final byte[] pixels = ((DataBufferByte)bi.getRaster().getDataBuffer()).getData();
convert.get(0, 0,buffer);
System.arraycopy(buffer, 0, pixels, 0, buffer.length);
return bi;
}catch(Exception e) {
System.out.println("Mat2Img"+e.getMessage());
}
return null;
}
public static BufferedImage Mat2Image(Mat mat) {
System.out.println("channels "+mat.channels());
MatOfByte mob = new MatOfByte();
Imgcodecs.imencode(".jpg", mat, mob);
ByteArrayInputStream bais = new ByteArrayInputStream(mob.toArray());
try {
return ImageIO.read(bais);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
//go through list of contours and remove items that is not likely a symbol based on size
public List<MatOfPoint> FilterContours(List<MatOfPoint> contour){
List<MatOfPoint> newContourList = new ArrayList<MatOfPoint>();
for(int i=0; i<contour.size();i++) {
if(isContourOfPReferedSize(contour.get(i), 17, 18, 5)) {
newContourList.add(contour.get(i));
}
}
return newContourList;
}
//Ettt symbol er passe stort innenfor en hviss variance..
//Dette fungerer ikke helt ett ideen! Glemmer at noen tegn ikke er så brede, eller så lange
public boolean isContourOfPReferedSize(MatOfPoint contour, int prefWidth, int prefHeight, int variance) {
boolean test = true;
if(contour.width() <= prefWidth+variance && contour.width()>= prefWidth-variance) {test=true;}
else {test=false;}
if(test) {
if(contour.height() <= prefHeight+variance && contour.height()>= prefHeight-variance) {test=true;}
else {test=false;}
}
System.out.println("Size test: "+test+ " pfw+v:"+(prefWidth+variance)+" pfw-v:"+(prefWidth-variance)+"act w:"+contour.width()+ " "+contour.height());
return test;
}
public void setVerbose(boolean Verbose) {
this.verbose = Verbose;
}
}