/Users/lyon/j4p/src/ip/gui/frames/NegateFrame.java
|
1 package ip.gui.frames;
2
3 import gui.Clipper;
4 import ip.gui.dialog.AdaptiveLog;
5 import ip.gui.dialog.ExponentialLog;
6 import ip.gui.dialog.GrayLog;
7 import ip.gui.dialog.RayleighLog;
8 import ip.transforms.TransformTable;
9 import j2d.ShortImageBean;
10 import math.Mat2;
11 import utils.Print;
12
13 import javax.media.jai.KernelJAI;
14 import java.awt.*;
15 import java.awt.event.ActionEvent;
16
17 public class NegateFrame extends GrabFrame {
18
19 private HistogramFrame rh,gh,bh;
20 KernelJAI kj = KernelJAI.GRADIENT_MASK_SOBEL_HORIZONTAL;
21
22 private int min = Integer.MAX_VALUE;
23 private int max = Integer.MIN_VALUE;
24
25 // used for adaptive image enhancement
26 private int mosaicWidth = 2;
27 private int mosaicHeight = 2;
28
29 private double rBar = 0;
30 private double gBar = 0;
31 private double bBar = 0;
32
33 private TransformTable tt =
34 new TransformTable(256);
35
36 private Menu negateMenu = getMenu("Negate");
37 private Menu histogramMenu = getMenu("Histogram");
38
39 private MenuItem negate_mi =
40 addMenuItem(negateMenu, "[E-n]egate");
41 private MenuItem add10_mi =
42 addMenuItem(negateMenu, "[E-1]add 10");
43 private MenuItem brighten_mi =
44 addMenuItem(negateMenu, "[E-b]righten");
45 private MenuItem darken_mi =
46 addMenuItem(negateMenu, "[E-d]arken");
47 private MenuItem linear_mi =
48 addMenuItem(negateMenu, "[E-l]inear transform...");
49
50 private MenuItem histogram_mi =
51 addMenuItem(histogramMenu, "[E-h]istogram");
52 private MenuItem unahe_mi =
53 addMenuItem(histogramMenu,
54 "[E-u]niform non-adaptive histogram equalization");
55 private MenuItem enahe_mi =
56 addMenuItem(histogramMenu, "[E-e]xponential non-adaptive histogram equalization...");
57 private MenuItem rnahe_mi =
58 addMenuItem(histogramMenu,
59 "[E-r]ayleigh non-adaptive histogram equalization...");
60
61 private MenuItem auhe_mi =
62 addMenuItem(histogramMenu, "[E-a]uhe adaptive uniform histogram equalization");
63 private MenuItem drawMosaic_mi =
64 addMenuItem(histogramMenu, "[E-d]raw Mosaic");
65 private MenuItem printTT_mi =
66 addMenuItem(histogramMenu, "[E-T-t]print transform table...");
67 private MenuItem printStats_mi =
68 addMenuItem(histogramMenu, "[E-T-p]rintStats");
69 private MenuItem printPMFs_mi =
70 addMenuItem(histogramMenu, "[E-1]printPMFs");
71 private MenuItem printCMFs_mi =
72 addMenuItem(histogramMenu, "[E-2]printCMF for r");
73
74
75 public void actionPerformed(ActionEvent e) {
76
77 if (match(e, drawMosaic_mi)) {
78 drawMosaic();
79 return;
80 }
81 if (match(e, rnahe_mi)) {
82 rayleighLog();
83 return;
84 }
85 if (match(e, auhe_mi)) {
86 auhe();
87 return;
88 }
89 if (match(e, enahe_mi)) {
90 eponentialLog();
91 return;
92 }
93 if (match(e, printCMFs_mi)) {
94 printCMFs();
95 return;
96 }
97 if (match(e, printPMFs_mi)) {
98 printPMFs();
99 return;
100 }
101 if (match(e, printStats_mi)) {
102 printStats();
103 return;
104 }
105 if (match(e, unahe_mi)) {
106 unahe();
107 return;
108 }
109 if (match(e, printTT_mi)) {
110 printTT();
111 return;
112 }
113 if (match(e, linear_mi)) {
114 linearLog();
115 return;
116 }
117 if (match(e, darken_mi)) {
118 darken();
119 return;
120 }
121 if (match(e, brighten_mi)) {
122 brighten();
123 return;
124 }
125 if (match(e, histogram_mi)) {
126 histogram();
127 return;
128 }
129 if (match(e, add10_mi)) {
130 add10();
131 return;
132 }
133 if (match(e, negate_mi)) {
134 negate();
135 return;
136 }
137 super.actionPerformed(e);
138
139 }
140
141 /**
142 mosaic - transform an array of
143 short into sub-images
144 */
145 public void auhe() {
146 auhe(mosaicWidth, mosaicHeight);
147 }
148
149 public void drawMosaic() {
150 AdaptiveLog.doit(this);
151 }
152
153 /**
154 mosaic - transform an array of
155 short into sub-images
156 ignoring fractional parts.
157 */
158 public void auhe(int blocksHigh, int blocksWide) {
159
160 int pelsWide = getImageWidth() / blocksWide;
161 int pelsHigh = getImageHeight() / blocksHigh;
162 int newWidth = pelsWide * blocksWide;
163 int newHeight = pelsHigh * blocksHigh;
164 NegateFrame nf;
165
166 for (int x1 = 0; x1 < newWidth; x1 += pelsWide)
167 for (int y1 = 0; y1 < newHeight; y1 += pelsHigh) {
168 nf = subFrame(x1, y1, pelsWide, pelsHigh);
169 nf.unahe();
170 assembleMosaic(nf, x1, y1);
171 }
172 short2Image();
173 }
174
175 public void assembleMosaic(NegateFrame nf, int x1, int y1) {
176 int x2 = getImageWidth() + x1;
177 int y2 = getImageHeight() + y1;
178 int xs = 0;
179 int ys = 0;
180 for (int x = x1; x < x2; x++) {
181 for (int y = y1; y < y2; y++) {
182 shortImageBean.getR()[x][y] = shortImageBean.getR()[xs][ys];
183 shortImageBean.getG()[x][y] = shortImageBean.getG()[xs][ys];
184 shortImageBean.getB()[x][y] = shortImageBean.getB()[xs][ys];
185 ys++;
186 }
187 ys = 0;
188 xs++;
189 }
190 }
191
192 public void drawMosaic(int blocksHigh, int blocksWide) {
193 mosaicWidth = blocksWide;
194 mosaicHeight = blocksHigh;
195
196 int pelsWide = getImageWidth() / blocksWide;
197 int pelsHigh = getImageHeight() / blocksHigh;
198 int newWidth = pelsWide * blocksWide;
199 int newHeight = pelsHigh * blocksHigh;
200
201 int x1 = 0, y1 = 0;
202 Print.println("DrawMosaic" +
203 " newWidth=" + newWidth +
204 " newHeight=" + newHeight +
205 " pelsWide=" + pelsWide +
206 " pelsHigh=" + pelsHigh);
207 Graphics gx = getGraphics();
208 for (x1 = 0; x1 < newWidth; x1 += pelsWide)
209 for (y1 = 0; y1 < newHeight; y1 += pelsHigh) {
210 gx.drawRect(x1, y1, pelsWide, pelsHigh);
211 }
212 }
213
214 public NegateFrame subFrame(int x1, int y1, int w, int h) {
215 short _r[][] = new short[w][h];
216 short _g[][] = new short[w][h];
217 short _b[][] = new short[w][h];
218 int x2 = x1 + w;
219 int y2 = y1 + h;
220 // for loop computes source coordinates
221 int xd = 0;
222 int yd = 0;
223
224 Print.println("Subframe" +
225 " x1=" + x1 +
226 " y1=" + y1 +
227 " x2=" + x2 +
228 " y2=" + y2);
229 for (int x = x1; x < x2; x++) {
230 for (int y = y1; y < y2; y++) {
231 _r[xd][yd] = shortImageBean.getR()[x][y];
232 _g[xd][yd] = shortImageBean.getG()[x][y];
233 _b[xd][yd] = shortImageBean.getB()[x][y];
234 yd++;
235 }
236 yd = 0;
237 xd++;
238 }
239 return new
240 NegateFrame(_r, _g, _b, "frame");
241 }
242
243 private void doMenus() {
244 negateMenu.add(histogramMenu);
245 filterMenu.add(negateMenu);
246 }
247
248 public NegateFrame(
249 short _r[][], short _g[][], short _b[][],
250 String title) {
251 super(title);
252 doMenus();
253 System.out.println("New constructor invoked");
254 shortImageBean.setR(_r);
255 setB(_b);
256 setG(_g);
257 // show image ...very slow
258 // but interesting!
259 short2Image();
260 }
261
262 public void printTT() {
263 tt.print();
264 }
265
266 public void add10() {
267 shortImageBean.add(10);
268 short2Image();
269 }
270
271 public void histogram() {
272 rh = new HistogramFrame(shortImageBean.getR(), "Red");
273 gh = new HistogramFrame(shortImageBean.getG(), "Green");
274 bh = new HistogramFrame(shortImageBean.getB(), "Blue");
275 rh.myShow();
276 gh.myShow();
277 bh.myShow();
278 }
279
280 public void negate() {
281 shortImageBean.negate();
282 short2Image();
283 }
284
285 private void brighten() {
286 powImage(this, shortImageBean, 0.9);
287 }
288
289 private void darken() {
290 powImage(this, shortImageBean, 1.5);
291 }
292
293 public static void powImage(ImageFrameInterface ifi, ShortImageBean nf, double p) {
294 for (int x = 0; x < nf.getWidth(); x++)
295 for (int y = 0; y < nf.getHeight(); y++) {
296 nf.getR()[x][y] = (short)
297 (255 * Math.pow((nf.getR()[x][y] / 255.0), p));
298 nf.getG()[x][y] = (short)
299 (255 * Math.pow((nf.getG()[x][y] / 255.0), p));
300 nf.getB()[x][y] = (short)
301 (255 * Math.pow((nf.getB()[x][y] / 255.0), p));
302 }
303 ifi.short2Image();
304 }
305
306 // Uniform Non Adaptive Histogram
307 // Equalization
308 public void unahe() {
309 short lut[] = tt.getLut();
310 double h[] = getAverageCMF();
311 for (short i = 0; i < lut.length; i++)
312 lut[i] = (short) (255 * h[i]);
313 applyLut(lut);
314 }
315
316 // Rayleigh Non Adaptive Histogram
317 // Equalization
318 public void rnahe(double alpha) {
319 short lut[] = tt.getLut();
320 double h[] = getAverageCMF();
321 double alpha2 = 2 * alpha * alpha;
322 double v;
323 double g;
324 for (short i = 0; i < h.length; i++) {
325 g = alpha2 * Math.log(1 / (1.0 - h[i]));
326 v = Math.sqrt(g);
327 lut[i] = (short) (255 * v);
328 }
329 tt.clip();
330 applyLut(lut);
331 }
332
333 // Exponential Non Adaptive Histogram
334 // Equalization
335 public void enahe(double alpha) {
336 short lut[] = tt.getLut();
337 double h[] = getAverageCMF();
338 for (short i = 0; i < 256; i++)
339 lut[i] = (short)
340 (255 * (-Math.log(1.0 - h[i]) / alpha));
341 tt.clip();
342 applyLut(lut);
343 }
344
345
346 public double[] getAverageCMF() {
347 rh = new HistogramFrame(shortImageBean.getR(), "Red");
348 gh = new HistogramFrame(shortImageBean.getG(), "Green");
349 bh = new HistogramFrame(shortImageBean.getB(), "Blue");
350 double CMFr[] = rh.getCMF();
351 double CMFg[] = gh.getCMF();
352 double CMFb[] = bh.getCMF();
353 return Mat2.getAverage(CMFr, CMFg, CMFb);
354 }
355
356 public void applyLut(short lut[]) {
357 wellConditioned(); //Shorts could be out of range;
358 for (int x = 0; x < getImageWidth(); x++)
359 for (int y = 0; y < getImageHeight(); y++) {
360
361 shortImageBean.getR()[x][y] = lut[shortImageBean.getR()[x][y]];
362 shortImageBean.getG()[x][y] = lut[shortImageBean.getG()[x][y]];
363 shortImageBean.getB()[x][y] = lut[shortImageBean.getB()[x][y]];
364 }
365 short2Image();
366 }
367
368 public void applyLut(short lutr[], short lutg[], short lutb[]) {
369 wellConditioned(); //Shorts could be out of range;
370 for (int x = 0; x < getImageWidth(); x++)
371 for (int y = 0; y < getImageHeight(); y++) {
372
373 shortImageBean.getR()[x][y] = lutr[shortImageBean.getR()[x][y]];
374 shortImageBean.getG()[x][y] = lutg[shortImageBean.getG()[x][y]];
375 shortImageBean.getB()[x][y] = lutb[shortImageBean.getB()[x][y]];
376 }
377 short2Image();
378 }
379
380 public void wellConditioned() {
381 for (int x = 0; x < getImageWidth(); x++)
382 for (int y = 0; y < getImageHeight(); y++) {
383 shortImageBean.getR()[x][y] = inRange(shortImageBean.getR()[x][y], x, y);
384 shortImageBean.getG()[x][y] = inRange(shortImageBean.getG()[x][y], x, y);
385 shortImageBean.getB()[x][y] = inRange(shortImageBean.getB()[x][y], x, y);
386 }
387 }
388
389 public short inRange(short v, int x, int y) {
390 if (v > 255) {
391 Print.println(
392 "out of range x=" + x + " y=" + y +
393 "v=" + v + " clipping to 255");
394 return 255;
395 }
396 if (v < 0) {
397 Print.println(
398 "out of range x=" + x + " y=" + y +
399 "v=" + v + " clipping to 0");
400 return 0;
401 }
402 return v;
403 }
404
405 public short linearMap(short v,
406 double c, double b) {
407 // scale gray value to 0..1 range
408 double f = c * v + b;
409 // scale f into 0..255 range
410 // clip f into range
411 if (f > 255) f = 255;
412 if (f < 0) f = 0;
413 return (short) f;
414 }
415
416 public void linearTransform() {
417 computeStats();
418 int Vmin = getMinimum();
419 int Vmax = getMaximum();
420 int Dmin = 0;
421 int Dmax = 255;
422 double deltaV = Vmax - Vmin;
423 double deltaD = Dmax - Dmin;
424 double c = deltaD / deltaV;
425 double b = (Dmin * Vmax - Dmax * Vmin) / deltaV;
426 linearTransform(c, b);
427 }
428
429 public void linearTransform(double c, double br) {
430 linearTransform(c, br, shortImageBean);
431 Clipper clipper = getClipper();
432 clipper.clip(shortImageBean);
433 short2Image();
434 }
435
436 public static void linearTransform(double c, double br, ShortImageBean b) {
437 int w = b.getWidth();
438 int h = b.getHeight();
439 for (int x = 0; x < w; x++)
440 for (int y = 0; y < h; y++) {
441 b.getR()[x][y] = (short) (c * b.getR()[x][y] + br);
442 b.getG()[x][y] = (short) (c * b.getG()[x][y] + br);
443 b.getB()[x][y] = (short) (c * b.getB()[x][y] + br);
444 }
445
446 }
447
448 // The following transform is fast, but
449 // only works on well conditioned input.
450 // I.e., r,g,b [0..255].
451 public void linearTransform2(double c, double br) {
452
453 short lut[] = tt.getLut();
454 for (short i = 0; i < 256; i++)
455 lut[i] = linearMap(i, c, br);
456 for (int x = 0; x < getImageWidth(); x++)
457 for (int y = 0; y < getImageHeight(); y++) {
458 shortImageBean.getR()[x][y] = lut[shortImageBean.getR()[x][y]];
459 shortImageBean.getG()[x][y] = lut[shortImageBean.getG()[x][y]];
460 shortImageBean.getB()[x][y] = lut[shortImageBean.getB()[x][y]];
461 }
462 short2Image();
463 }
464
465 public void computeStats() {
466
467 min = Integer.MAX_VALUE;
468 max = Integer.MIN_VALUE;
469 rBar = 0;
470 gBar = 0;
471 bBar = 0;
472 double N = getImageWidth() * getImageHeight();
473 for (int x = 0; x < getImageWidth(); x++)
474 for (int y = 0; y < getImageHeight(); y++) {
475 rBar += shortImageBean.getR()[x][y];
476 gBar += shortImageBean.getG()[x][y];
477 bBar += shortImageBean.getB()[x][y];
478 min = Math.min(shortImageBean.getR()[x][y], min);
479 min = Math.min(shortImageBean.getG()[x][y], min);
480 min = Math.min(shortImageBean.getB()[x][y], min);
481 max = Math.max(shortImageBean.getR()[x][y], max);
482 max = Math.max(shortImageBean.getG()[x][y], max);
483 max = Math.max(shortImageBean.getB()[x][y], max);
484 }
485 rBar /= N;
486 gBar /= N;
487 bBar /= N;
488 }
489
490 public void printPMFr() {
491 rh = new HistogramFrame(shortImageBean.getR(), "Red");
492 rh.printPMF();
493 }
494
495 public void printCMFs() {
496 rh = new HistogramFrame(shortImageBean.getR(), "Red");
497 rh.printCMF();
498 }
499
500 public void printPMFg() {
501 gh = new HistogramFrame(shortImageBean.getG(), "Green");
502 gh.printPMF();
503
504 }
505
506 public void printPMFb() {
507 bh = new HistogramFrame(shortImageBean.getB(), "Blue");
508 bh.printPMF();
509
510 }
511
512 public void printPMFs() {
513 printPMFr();
514 printPMFg();
515 printPMFb();
516 }
517
518 public void printStats() {
519 computeStats();
520 Print.println(
521 "Min Vij=" + getMinimum() + "\n" +
522 "Max Vij=" + getMaximum() + "\n" +
523 "rBar = " + getRBar() + "\n" +
524 "gBar = " + getGBar() + "\n" +
525 "bBar = " + getBBar()
526 );
527
528 }
529
530 public double getRBar() {
531 return rBar;
532 }
533
534 public double getGBar() {
535 return gBar;
536 }
537
538 public double getBBar() {
539 return bBar;
540 }
541
542 public int getMinimum() {
543 return min;
544 }
545
546 public int getMaximum() {
547 return max;
548 }
549
550 public void eponentialLog() {
551 String prompts[] = {
552 "alpha = "
553 };
554 String defaults[] = {
555 "4.0"};
556 String title = "Exponential Transform Dialog";
557
558
559 new ExponentialLog(
560 this,
561 title,
562 prompts,
563 defaults, 9);
564 }
565
566 public void rayleighLog() {
567 String prompts[] = {
568 "alpha = "
569 };
570 String defaults[] = {
571 "4.0"};
572 String title = "Rayleigh Transform Dialog";
573
574
575 new RayleighLog(
576 this,
577 title,
578 prompts,
579 defaults, 9);
580 }
581
582 public void linearLog() {
583 String prompts[] = {
584 "Contrast = c =",
585 "Brightness = b ="
586 };
587 computeStats();
588 int Vmin = getMinimum();
589 int Vmax = getMaximum();
590 int Dmin = 0;
591 int Dmax = 255;
592 double deltaV = Vmax - Vmin;
593 double deltaD = Dmax - Dmin;
594 double c = deltaD / deltaV;
595 double b = (Dmin * Vmax - Dmax * Vmin) / deltaV;
596 Print.println("C=" + c + " b=" + b);
597
598 String defaults[] = {
599 Double.toString(c),
600 Double.toString(b)};
601 String title = "Linear Grayscale Transform Dialog";
602
603
604 new GrayLog(
605 this,
606 title,
607 prompts,
608 defaults, 9);
609
610 }
611
612 public NegateFrame(String title) {
613 super(title);
614 doMenus();
615 }
616
617 public static void main(String args[]) {
618 new NegateFrame("NegateFrame");
619 }
620 }
621
622