1 | import eyedev._01.CharacterLearner; |
2 | import eyedev._21.ImageInfo; |
3 | import eyedev._09.Subrecognition; |
4 | import eyedev._01.ImageWithMarkLines; |
5 | import prophecy.common.gui.SingleComponentPanel; |
6 | import drjava.util.Trigger; |
7 | import eyedev._17.MarkLine; |
8 | import eyedev._21.Correction; |
9 | import eyedev._21.Corrections; |
10 | import drjava.util.ObjectUtil; |
11 | import drjava.util.StringUtil; |
12 | import eyedev._01.DebugItem; |
13 | import prophecy.common.image.ImageSurface; |
14 | import prophecy.common.image.RGBImage; |
15 | |
16 | sclass XRecognizableImage extends SingleComponentPanel { |
17 | ImageInfo imageInfo; |
18 | private BufferedImage image; |
19 | private double zoom = 1.0; |
20 | protected Subrecognition markedSubrecognition, lastMarkedSubrecognition; |
21 | protected java.util.List<DebugItem> debugInfo; |
22 | private ImageSurface imageSurface; |
23 | private boolean selectableBoxes; |
24 | private Subrecognition selectedSubrecognition; |
25 | public final Trigger markChangeTrigger = new Trigger(); |
26 | public final Trigger selectionChangeTrigger = new Trigger(); |
27 | private boolean doubleBuffering; |
28 | private boolean drawMarkLines; |
29 | private boolean drawConfidenceBoxes = false; |
30 | private float minConfidence = 0.5f; // anything below this confidence is shown in dark red |
31 | private Corrections corrections = new Corrections(); |
32 | |
33 | *() { |
34 | setImage((BufferedImage) null); |
35 | } |
36 | |
37 | *(RGBImage image) { |
38 | setImage(image); |
39 | } |
40 | |
41 | /* replace image, but keep scroll location if possible */ |
42 | public void updateImage(RGBImage image) { |
43 | updateImage(image.getBufferedImage()); |
44 | } |
45 | |
46 | /* replace image, but keep scroll location if possible */ |
47 | public void updateImage(BufferedImage image) { |
48 | if (this.image != null && image != null |
49 | && this.image.getWidth() == image.getWidth() |
50 | && this.image.getHeight() == image.getHeight()) { |
51 | this.image = image; |
52 | imageSurface.setImage(image); |
53 | } else |
54 | setImage(image); |
55 | } |
56 | |
57 | public void setImage(RGBImage image) { |
58 | setImage(image.getBufferedImage()); |
59 | } |
60 | |
61 | public void setImage(BufferedImage image) { |
62 | this.image = image; |
63 | clearOverlays(); |
64 | if (image == null) { |
65 | setComponent(new JScrollPane()); |
66 | imageSurface = null; |
67 | } else { |
68 | imageSurface = new ImageSurface(image) { |
69 | @Override |
70 | protected void fillPopupMenu(JPopupMenu menu, Point point) { |
71 | super.fillPopupMenu(menu, point); |
72 | XRecognizableImage.this.fillPopupMenu(menu, point); |
73 | } |
74 | |
75 | public void render(int w, int h, Graphics2D g) { |
76 | super.render(w, h, g); |
77 | g.scale(imageSurface.getZoomX(), imageSurface.getZoomY()); |
78 | renderOverlays(g); |
79 | } |
80 | }; |
81 | |
82 | imageSurface.addMouseMotionListener(new MouseMotionListener() { |
83 | public void mouseDragged(MouseEvent e) { |
84 | } |
85 | |
86 | public void mouseMoved(MouseEvent e) { |
87 | surfaceMouseMove(e); |
88 | } |
89 | }); |
90 | |
91 | imageSurface.addMouseListener(new MouseAdapter() { |
92 | public void mouseEntered(MouseEvent e) { |
93 | surfaceMouseMove(e); |
94 | } |
95 | |
96 | public void mouseExited(MouseEvent e) { |
97 | setMarkedSubrecognition(null, false); |
98 | } |
99 | |
100 | @Override |
101 | public void mousePressed(MouseEvent e) { |
102 | surfaceMouseClick(e); |
103 | } |
104 | }); |
105 | |
106 | imageSurface.setZoom(zoom); |
107 | if (doubleBuffering) |
108 | // This makes Surface create a buffer image |
109 | imageSurface.setImageType(2); |
110 | JScrollPane scrollPane = imageSurface.makeScrollPane(); |
111 | scrollPane.getVerticalScrollBar().setUnitIncrement(10); |
112 | setComponent(scrollPane); |
113 | } |
114 | } |
115 | |
116 | private void clearOverlays() { |
117 | markedSubrecognition = null; |
118 | selectedSubrecognition = null; |
119 | debugInfo = null; |
120 | } |
121 | |
122 | private Subrecognition findSubrecognition(MouseEvent e) { |
123 | Point p = new Point((int) (e.getX()/imageSurface.getZoomX()), (int) (e.getY()/imageSurface.getZoomY())); |
124 | if (debugInfo != null) |
125 | for (DebugItem item : debugInfo) |
126 | if (item.data instanceof Subrecognition) { |
127 | Subrecognition s = (Subrecognition) item.data; |
128 | Rectangle r = new Rectangle(s.clip); |
129 | r.grow(1, 1); |
130 | if (r.contains(p)) |
131 | return s; |
132 | } |
133 | return null; |
134 | } |
135 | |
136 | private void surfaceMouseMove(MouseEvent e) { |
137 | setMarkedSubrecognition(findSubrecognition(e), false); |
138 | } |
139 | |
140 | private void surfaceMouseClick(MouseEvent e) { |
141 | Subrecognition s = findSubrecognition(e); |
142 | if (selectableBoxes) |
143 | setSelectedSubrecognition(s); |
144 | else if (s != null) |
145 | subrecognitionClicked(s, e); |
146 | } |
147 | |
148 | // override this |
149 | public void subrecognitionClicked(Subrecognition s, MouseEvent e) { |
150 | if (e.getButton() == MouseEvent.BUTTON1) |
151 | correctCharacter(s); |
152 | } |
153 | |
154 | public void setZoom(double zoom) { |
155 | if (zoom == this.zoom) return; |
156 | this.zoom = zoom; |
157 | if (image != null) |
158 | setImage(image); |
159 | } |
160 | |
161 | protected void renderOverlays(Graphics2D g) { |
162 | if (drawConfidenceBoxes) |
163 | drawConfidenceBoxes(g); |
164 | if (markedSubrecognition != null) |
165 | drawBox(g, markedSubrecognition, Color.yellow, 2); |
166 | if (selectedSubrecognition != null) |
167 | drawBox(g, selectedSubrecognition, Color.blue, 2); |
168 | if (drawMarkLines && debugInfo != null) |
169 | for (DebugItem debugItem : debugInfo) { |
170 | if (debugItem.data instanceof MarkLine) { |
171 | MarkLine markLine = (MarkLine) debugItem.data; |
172 | g.setColor(Color.blue); |
173 | g.setStroke(new BasicStroke(1)); |
174 | int y = markLine.type == MarkLine.Type.base ? markLine.y+1 : markLine.y; |
175 | g.drawLine(markLine.x, y, markLine.x+markLine.width-1, y); |
176 | } |
177 | } |
178 | drawCorrections(g); |
179 | } |
180 | |
181 | private void drawCorrections(Graphics2D g) { |
182 | for (Correction correction : corrections) { |
183 | g.setColor(Color.green); |
184 | g.setStroke(new BasicStroke(1)); |
185 | Rectangle r = correction.getRectangle(); |
186 | g.drawRect(r.x, r.y, r.width, r.height); |
187 | } |
188 | } |
189 | |
190 | private void drawConfidenceBoxes(Graphics2D g) { |
191 | if (debugInfo != null) for (DebugItem debugItem : debugInfo) |
192 | if (debugItem.data instanceof Subrecognition) { |
193 | Subrecognition s = (Subrecognition) debugItem.data; |
194 | //main.print("Drawing confidence box"); |
195 | float adjustedConfidence = Math.max(0, s.confidence-minConfidence)/(1.0f-minConfidence); |
196 | float redness = 1f-adjustedConfidence; |
197 | Color boxColor = new Color(1f, 0f, 0f, redness); |
198 | drawBox(g, s, boxColor, 2); |
199 | } |
200 | } |
201 | |
202 | public void drawBox(Graphics2D g, Subrecognition subrecognition, Color color, int strokeWidth) { |
203 | g.setColor(color); |
204 | g.setStroke(new BasicStroke((float) strokeWidth)); |
205 | Rectangle r = subrecognition.clip; |
206 | g.drawRect(r.x-1, r.y-1, r.width+2, r.height+2); |
207 | } |
208 | |
209 | public void setMarkedSubrecognition(Subrecognition subrecognition, boolean scroll) { |
210 | if (!ObjectUtil.equal(subrecognition, markedSubrecognition)) { |
211 | if (subrecognition != null) |
212 | lastMarkedSubrecognition = subrecognition; |
213 | //System.out.println("subrecognition: " + subrecognition + ", lastMarkedSubrecognition: " + lastMarkedSubrecognition); |
214 | markedSubrecognition = subrecognition; |
215 | S tooltip = null; |
216 | if (subrecognition != null) { |
217 | Correction correction = findCorrection(subrecognition.clip); |
218 | S ct = correction != null ? correction.getText() : null; |
219 | S ch = "(unknown character)"; |
220 | if (subrecognition.text == null) { |
221 | if (ct != null) |
222 | ch = "corrected as " + ct; |
223 | } else { |
224 | ch = subrecognition.text; |
225 | if (ct != null && neq(subrecognition.text, ct)) |
226 | ch += " / corrected as " + ct; |
227 | } |
228 | tooltip = "<html>"; |
229 | tooltip += StringUtil.escapeHtml(ch); |
230 | tooltip += "<br>confidence: " + (int) (subrecognition.confidence*100) + "%"; |
231 | //System.out.println("line: " + subrecognition.line); |
232 | if (subrecognition.line != null) |
233 | tooltip += "<br>" + StringUtil.escapeHtml(subrecognition.line.text); |
234 | tooltip += "</html>"; |
235 | } |
236 | imageSurface.setToolTipText(tooltip); |
237 | repaintImageSurface(); |
238 | if (scroll && subrecognition != null) |
239 | imageSurface.scrollRectToVisible(new Rectangle(subrecognition.clip)); |
240 | markChangeTrigger.trigger(); |
241 | } |
242 | } |
243 | |
244 | public void repaintImageSurface() { |
245 | if (imageSurface != null) |
246 | imageSurface.repaint(); |
247 | } |
248 | |
249 | public void setSelectedSubrecognition(Subrecognition subrecognition) { |
250 | if (!ObjectUtil.equal(subrecognition, selectedSubrecognition)) { |
251 | selectedSubrecognition = subrecognition; |
252 | repaintImageSurface(); |
253 | selectionChangeTrigger.trigger(); |
254 | } |
255 | } |
256 | |
257 | public void setDebugInfo(List<DebugItem> debugInfo) { |
258 | this.debugInfo = debugInfo; |
259 | selectedSubrecognition = null; |
260 | repaintImageSurface(); |
261 | } |
262 | |
263 | public void setSelectableBoxes(boolean selectableBoxes) { |
264 | this.selectableBoxes = selectableBoxes; |
265 | } |
266 | |
267 | public Subrecognition getSelectedSubrecognition() { |
268 | return selectedSubrecognition; |
269 | } |
270 | |
271 | public Subrecognition getMarkedSubrecognition() { |
272 | return markedSubrecognition; |
273 | } |
274 | |
275 | public void setDoubleBuffering(boolean b) { |
276 | doubleBuffering = b; |
277 | setImage(image); |
278 | } |
279 | |
280 | public void setDrawMarkLines(boolean b) { |
281 | if (drawMarkLines != b) { |
282 | drawMarkLines = b; |
283 | repaintImageSurface(); |
284 | } |
285 | } |
286 | |
287 | public boolean getDrawConfidenceBoxes() { |
288 | return drawConfidenceBoxes; |
289 | } |
290 | |
291 | public void setDrawConfidenceBoxes(boolean drawConfidenceBoxes) { |
292 | if (this.drawConfidenceBoxes != drawConfidenceBoxes) { |
293 | this.drawConfidenceBoxes = drawConfidenceBoxes; |
294 | repaintImageSurface(); |
295 | } |
296 | } |
297 | |
298 | public void setCorrections(Corrections corrections) { |
299 | this.corrections = corrections; |
300 | } |
301 | |
302 | Correction findCorrection(Point point) { |
303 | if (imageInfo != null && imageInfo.getCorrections() != null) |
304 | for (final Correction correction : imageInfo.getCorrections()) if (correction.getRectangle().contains(point)) |
305 | ret correction; |
306 | null; |
307 | } |
308 | |
309 | // exact match |
310 | Correction findCorrection(Rectangle r) { |
311 | if (imageInfo != null && imageInfo.getCorrections() != null) |
312 | for (final Correction correction : imageInfo.getCorrections()) if (correction.getRectangle().equals(r)) |
313 | ret correction; |
314 | null; |
315 | } |
316 | |
317 | public void fillPopupMenu(JPopupMenu menu, Point point) { |
318 | prependMenuItem_correctCharacter(menu); |
319 | prependMenuItem_removeCorrection(menu, point); |
320 | } |
321 | |
322 | void prependMenuItem_removeCorrection(JPopupMenu menu, Point point) { |
323 | final Correction correction = findCorrection(point); |
324 | if (correction != null) { |
325 | JMenuItem mi = new JMenuItem("Remove correction"); |
326 | mi.addActionListener(actionListener { |
327 | imageInfo.getCorrections().remove(correction); |
328 | callOpt(mc(), "saveImageInfo"); |
329 | }); |
330 | menu.insert(mi, 0); |
331 | } |
332 | } |
333 | |
334 | private void prependMenuItem_correctCharacter(JPopupMenu menu) { |
335 | final Subrecognition subrecognition = lastMarkedSubrecognition; |
336 | if (subrecognition != null) { |
337 | String text; |
338 | if (subrecognition.text != null) |
339 | text = "Correct character (" + subrecognition.text + ")..."; |
340 | else |
341 | text = "Enter character..."; |
342 | |
343 | JMenuItem mi = new JMenuItem(text); |
344 | //JMenuItem mi = new JMenuItem("Correct character..."); |
345 | mi.addActionListener(actionListener { |
346 | correctCharacter(subrecognition); |
347 | }); |
348 | if (menu.getComponentCount() != 0) |
349 | menu.insert(new JPopupMenu.Separator(), 0); |
350 | menu.insert(mi, 0); |
351 | } |
352 | } |
353 | |
354 | void correctCharacter(Subrecognition subrecognition) { |
355 | S text = "Correct character"; |
356 | //text += " (type x_ if it's the left half of an x)"; |
357 | |
358 | String newText = JOptionPane.showInputDialog(text, |
359 | subrecognition.text == null ? "" : subrecognition.text); |
360 | if (newText != null) |
361 | correctCharacter(subrecognition, newText); |
362 | } |
363 | |
364 | void correctCharacter(Subrecognition subrecognition, String newText) { |
365 | //subrecognition.text = newText; |
366 | ImageWithMarkLines imageWithMarkLines = |
367 | new ImageWithMarkLines(subrecognition.image, |
368 | subrecognition.topLine, subrecognition.baseLine); |
369 | CharacterLearner characterLearner = recognizer.getCharacterLearner(); |
370 | if (characterLearner != null) { |
371 | characterLearner.learnCharacter(imageWithMarkLines, newText); |
372 | callOpt(mc(), "recognizerModified"); |
373 | } |
374 | |
375 | if (imageInfo != null) { |
376 | imageInfo.getCorrections().add(new Correction(subrecognition.clip, newText)); |
377 | callOpt(mc(), "saveImageInfo"); |
378 | } |
379 | } |
380 | |
381 | /*public void subrecognitionClicked(Subrecognition s) { |
382 | if (!quickCaretMove) { |
383 | ++blockImageAndTextUpdates; |
384 | textArea.jumpToLocation(s); |
385 | --blockImageAndTextUpdates; |
386 | } |
387 | }*/ |
388 | } |
download show line numbers debug dex old transpilations
Travelled to 15 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, ddnzoavkxhuk, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1004067 |
Snippet name: | XRecognizableImage |
Eternal ID of this version: | #1004067/1 |
Text MD5: | 95801df7ff1bfa695a92255d7ac0a396 |
Author: | stefan |
Category: | javax / ocr |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2016-08-11 17:31:28 |
Source code size: | 13028 bytes / 388 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 631 / 836 |
Referenced in: | [show references] |