/Users/lyon/j4p/src/ip/gui/frames/SpatialFilterFrame.java
|
1 package ip.gui.frames;
2
3 import collections.sortable.Cshort;
4 import ip.gui.dialog.DoubleArrayLog;
5 import ip.transforms.Gauss;
6 import ip.transforms.Kernels;
7 import j2d.ShortImageBean;
8 import math.Mat2;
9 import utils.Timer;
10
11 import java.awt.Menu;
12 import java.awt.MenuBar;
13 import java.awt.MenuItem;
14 import java.awt.event.ActionEvent;
15 import java.util.Vector;
16
17 public class SpatialFilterFrame
18 extends ConvolutionFrame {
19 public SpatialFilterFrame child = null;
20 private Menu SpatialFilterMenu = getMenu(
21 "SpatialFilter");
22
23 private Menu lowPassMenu = getMenu("LowPass");
24 private Menu gaussianMenu = getMenu(
25 "gaussian");
26 private Menu medianMenu = getMenu("Median");
27 private Menu highPassMenu = getMenu(
28 "Hi-pass");
29 private Menu unsharpMenu = getMenu("unsharp");
30
31 private Menu kernalMenu = getMenu(
32 "Convolution Kernal");
33 private MenuItem showConvolutionKernal_mi
34 = addMenuItem(kernalMenu, "show");
35 private MenuItem enterConvolutionKernal33_mi
36 = addMenuItem(kernalMenu, "3x3..");
37 private MenuItem enterConvolutionKernal55_mi
38 = addMenuItem(kernalMenu, "5x5..");
39 private MenuItem enterConvolutionKernal77_mi
40 = addMenuItem(kernalMenu, "7x7..");
41
42 private MenuItem average_mi = addMenuItem(
43 lowPassMenu, "[a]verage");
44 private MenuItem lp1_mi = addMenuItem(
45 lowPassMenu, "[E-1]lp1");
46 private MenuItem lp2_mi = addMenuItem(
47 lowPassMenu, "[E-2]lp2");
48 private MenuItem lp3_mi = addMenuItem(
49 lowPassMenu, "[E-3]lp3");
50 private MenuItem mean3_mi = addMenuItem(
51 lowPassMenu, "[E-4]mean3");
52 private MenuItem mean9_mi = addMenuItem(
53 lowPassMenu, "[E-5]mean9");
54
55 private MenuItem gauss3_mi = addMenuItem(
56 gaussianMenu, "[E-6]gauss 3x3");
57 private MenuItem gauss7_mi = addMenuItem(
58 gaussianMenu, "[E-7]gauss 7x7");
59 private MenuItem gauss15_mi = addMenuItem(
60 gaussianMenu, "[E-9]gauss 15x15");
61 private MenuItem gauss31_mi = addMenuItem(
62 gaussianMenu, "[E-T-G]auss 31x31");
63 private MenuItem gauss31_fast_mi = addMenuItem(
64 gaussianMenu, "Gauss 31x31 fast");
65 private MenuItem gabor_mi = addMenuItem(
66 lowPassMenu, "[T-G]abor");
67
68 private MenuItem medianCross3x3_mi = addMenuItem(
69 medianMenu, "[E-T-+]cross3x3");
70 private MenuItem medianSquare3x3_mi = addMenuItem(
71 medianMenu, "[E-T-s]quare 3x3");
72 private MenuItem medianOctagon5x5_mi = addMenuItem(
73 medianMenu, "[E-T-o]catgon 5x5");
74 private MenuItem medianSquare5x5_mi = addMenuItem(
75 medianMenu, "[E-T-S]quare 5x5");
76 private MenuItem medianDiamond7x7_mi = addMenuItem(
77 medianMenu, "[E-T-D]iamond 7x7");
78 private MenuItem medianCross7x7_mi = addMenuItem(
79 medianMenu, "[E-T-C]ross 7x7");
80 private MenuItem outlierEstimate_mi = addMenuItem(
81 medianMenu,
82 "[E-T-O]utlier estimate");
83 private MenuItem saltAndPepper100_mi = addMenuItem(
84 medianMenu,
85 "[E-T-1]saltAndPepper100");
86 private MenuItem saltAndPepper1000_mi = addMenuItem(
87 medianMenu,
88 "[E-T-2]saltAndPepper1000");
89 private MenuItem saltAndPepper2000_mi = addMenuItem(
90 medianMenu,
91 "[E-T-3]saltAndPepper2000");
92 private MenuItem saltAndPepper4000_mi = addMenuItem(
93 medianMenu,
94 "[E-T-4]saltAndPepper4000");
95
96 private MenuItem hp1_mi = addMenuItem(
97 highPassMenu, "[T-1]hp1");
98 private MenuItem hp2_mi = addMenuItem(
99 highPassMenu, "[T-2]hp2");
100 private MenuItem hp3_mi = addMenuItem(
101 highPassMenu, "[T-3]hp3");
102 private MenuItem hp4_mi = addMenuItem(
103 highPassMenu, "[T-4]hp4");
104 private MenuItem hp5_mi = addMenuItem(
105 highPassMenu, "[T-5]hp5");
106
107 MenuItem shadowMask_mi = addMenuItem(
108 highPassMenu, "[T-6]shadowMask");
109
110 private MenuItem usp1_mi = addMenuItem(
111 unsharpMenu, "[T-7]usp1");
112
113 private MenuItem subtractChild_mi = addMenuItem(
114 getFileMenu(),
115 "[T-8]subtract child");
116
117 private MenuItem short2Image_mi = addMenuItem(
118 getFileMenu(), "[T-9]short2Image");
119 private MenuItem clip_mi = addMenuItem(
120 getFileMenu(), "[T-0]clip");
121
122
123 private boolean computeOutlier = true;
124 private int numberOfOutliers = 0;
125
126
127 public void makeChild() {
128 child = new SpatialFilterFrame("child");
129 ImageFrameInterface frame = child;
130 int width1 = getImageWidth();
131 frame.setImageWidth(width1);
132 ImageFrameInterface frame1 = child;
133 int height1 = getImageHeight();
134 frame1.setImageHeight(height1);
135 short[][] r = Mat2.copyArray(
136 shortImageBean.getR());
137 shortImageBean.setR(r);
138 child.setG(
139 Mat2.copyArray(
140 shortImageBean.getG()));
141 child.setB(
142 Mat2.copyArray(
143 shortImageBean.getB()));
144 }
145
146 public void subtractChild() {
147 subtract(shortImageBean);
148 short2Image();
149 }
150
151 public void subtract(ShortImageBean sibB) {
152
153 ShortImageBean.subtract(shortImageBean,
154 sibB);
155
156 }
157
158 public void outlierEstimate() {
159 setComputeOutlier(!isComputeOutlier());
160
161 System.out.println(
162 "computeOutlier = " +
163 isComputeOutlier());
164 System.out.println(
165 "numberOfOutliers = " +
166 getNumberOfOutliers());
167 setNumberOfOutliers(0);
168 }
169
170 public SpatialFilterFrame(String title) {
171 super(title);
172 MenuBar mb = getMenuBar();
173 SpatialFilterMenu.add(kernalMenu);
174 lowPassMenu.add(gaussianMenu);
175 SpatialFilterMenu.add(lowPassMenu);
176 SpatialFilterMenu.add(medianMenu);
177 highPassMenu.add(unsharpMenu);
178 SpatialFilterMenu.add(highPassMenu);
179 mb.add(SpatialFilterMenu);
180 setMenuBar(mb);
181 }
182
183
184 public void clip() {
185 ShortImageBean.clip(shortImageBean);
186 }
187
188 public void enterConvolutionKernal() {
189 new DoubleArrayLog(this,
190 "Convolution kernal",
191 null,
192 0,
193 0,
194 6);
195 }
196
197 public void enterConvolutionKernal(int r,
198 int c) {
199 new DoubleArrayLog(this,
200 "Convolution kernal",
201 null,
202 r,
203 c,
204 6);
205 }
206
207 public void actionPerformed(ActionEvent e) {
208
209 if (match(e, gabor_mi)) {
210 gabor7();
211 return;
212 }
213 if (match(e,
214 enterConvolutionKernal33_mi)) {
215 enterConvolutionKernal(3, 3);
216 return;
217 }
218
219 if (match(e,
220 enterConvolutionKernal55_mi)) {
221 enterConvolutionKernal(5, 5);
222 return;
223 }
224
225 if (match(e,
226 enterConvolutionKernal77_mi)) {
227 enterConvolutionKernal(7, 7);
228 return;
229 }
230 if (match(e, showConvolutionKernal_mi)) {
231 showConvolutionKernal();
232 return;
233 }
234 if (match(e, clip_mi)) {
235 clip();
236 return;
237 }
238 if (match(e, short2Image_mi)) {
239 short2Image();
240 return;
241 }
242 if (match(e, subtractChild_mi)) {
243 subtractChild();
244 return;
245 }
246 if (match(e, usp1_mi)) {
247 usp1();
248 return;
249 }
250 if (match(e, outlierEstimate_mi)) {
251 outlierEstimate();
252 return;
253 }
254 if (match(e, medianCross7x7_mi)) {
255 medianCross7x7();
256 return;
257 }
258 if (match(e, medianCross3x3_mi)) {
259 medianCross3x3();
260 return;
261 }
262 if (match(e, medianSquare3x3_mi)) {
263 medianSquare3x3();
264 return;
265 }
266 if (match(e, medianOctagon5x5_mi)) {
267 medianOctagon5x5();
268 return;
269 }
270 if (match(e, medianSquare5x5_mi)) {
271 medianSquare5x5();
272 return;
273 }
274 if (match(e, medianDiamond7x7_mi)) {
275 medianDiamond7x7();
276 return;
277 }
278 if (match(e, mean9_mi)) {
279 mean9();
280 return;
281 }
282 if (match(e, mean3_mi)) {
283 mean3();
284 return;
285 }
286 if (match(e, saltAndPepper100_mi)) {
287 saltAndPepper(100);
288 return;
289 }
290 if (match(e, saltAndPepper1000_mi)) {
291 saltAndPepper(1000);
292 return;
293 }
294 if (match(e, saltAndPepper2000_mi)) {
295 saltAndPepper(2000);
296 return;
297 }
298 if (match(e, saltAndPepper4000_mi)) {
299 saltAndPepper(4000);
300 return;
301 }
302 if (match(e, gauss3_mi)) {
303 gauss3();
304 return;
305 }
306 if (match(e, gauss7_mi)) {
307 gauss7();
308 return;
309 }
310 if (match(e, gauss15_mi)) {
311 gauss15();
312 return;
313 }
314 if (match(e, gauss31_mi)) {
315 gauss31();
316 return;
317 }
318 if (match(e, gauss31_fast_mi)) {
319 gauss31Fast();
320 return;
321 }
322
323 if (match(e, lp1_mi)) {
324 lp1();
325 return;
326 }
327 if (match(e, lp2_mi)) {
328 lp2();
329 return;
330 }
331 if (match(e, lp3_mi)) {
332 lp3();
333 return;
334 }
335 if (match(e, hp1_mi)) {
336 hp1();
337 return;
338 }
339 if (match(e, hp2_mi)) {
340 hp2();
341 return;
342 }
343 if (match(e, hp3_mi)) {
344 hp3();
345 return;
346 }
347 if (match(e, hp4_mi)) {
348 hp4();
349 return;
350 }
351 if (match(e, hp5_mi)) {
352 hp5();
353 return;
354 }
355 if (match(e, average_mi)) {
356 average();
357 return;
358 }
359
360 super.actionPerformed(e);
361
362 }
363
364 public void saltAndPepper(int n) {
365 shortImageBean.saltAndPepper(n);
366 short2Image();
367 }
368
369
370 public void average() {
371 float[][] k = Kernels.getAverage3x3();
372 convolve(k);
373 }
374
375
376 public void hp1() {
377 float[][] k = Kernels.getHp1();
378 convolve(k);
379 }
380
381 public void hp2() {
382 float[][] k = Kernels.getHp2();
383 convolve(k);
384 }
385
386 public void hp3() {
387 float[][] k = Kernels.getHp3();
388 convolve(k);
389 }
390
391 public void hp4() {
392 float[][] k = Kernels.getHp4();
393 convolve(k);
394 }
395
396 public void hp5() {
397 float[][] k = Kernels.getHp5();
398 convolve(k);
399 }
400
401
402 public void usp1() {
403 makeChild();
404 child.gauss3();
405 subtract(shortImageBean);
406 short2Image();
407 }
408
409 public void lp1() {
410 float[][] k = Kernels.getLp1();
411 convolve(k);
412 }
413
414 public void lp2() {
415 float[][] k = Kernels.getLp2();
416 convolve(k);
417 }
418
419 public void lp3() {
420 float[][] k = Kernels.getLp3();
421 convolve(k);
422 }
423
424 public void gabor7() {
425 float[][] k = Kernels.getGabor7();
426 convolve(k);
427
428 }
429
430
431 public void mean9() {
432 float[][] k = Kernels.getMean9();
433
434 convolve(k);
435 }
436
437 public void mean3() {
438 float[][] k = Kernels.getMean3();
439 //sum=1.0000000074505806
440 convolve(k);
441 }
442
443 public void gauss3() {
444 float[][] k = Gauss.getGauss3();
445 convolve(k);
446 }
447
448 // computes an MxN kernel using (9.1)
449
450
451 public static double oneOnF(double x,
452 double y,
453 double xc,
454 double yc) {
455 double dx = x - xc;
456 double dy = y - yc;
457 double dx2 = dx * dx;
458 double dy2 = dy * dy;
459 double eps = 1;
460 return
461 1 / Math.sqrt(dx2 + dy2 + eps);
462 }
463
464 public static float[][] getOneOnFKernel(
465 int M, int N) {
466 float k[][] = new float[M][N];
467 int xc = M / 2;
468 int yc = N / 2;
469 for (int x = 0; x < k.length; x++)
470 for (int y = 0; y < k[0].length; y++)
471 k[x][y] =
472 (float) oneOnF(x, y, xc, yc);
473 return k;
474 }
475
476 public void multOneOnF() {
477 int xc = getImageWidth() / 2;
478 int yc = getImageHeight() / 2;
479 for (int x = 0; x < getImageWidth(); x++)
480 for (int y = 0; y < getImageHeight(); y++) {
481 double f = oneOnF(x, y, xc, yc);
482 shortImageBean.getR()[x][y] =
483 (short) (shortImageBean.getR()[x][y] *
484 f);
485 shortImageBean.getG()[x][y] =
486 (short) (shortImageBean.getG()[x][y] *
487 f);
488 shortImageBean.getB()[x][y] =
489 (short) (shortImageBean.getB()[x][y] *
490 f);
491 }
492 short2Image();
493 }
494
495 public void printOneOnFKernel() {
496 float k[][] = getOneOnFKernel(9, 9);
497 Mat2.printKernel(k,
498 "OneOnFKernel" +
499 k.length);
500 }
501
502 public void gauss7() {
503 float[][] k = Gauss.getGauss7();
504 convolve(k);
505 }
506
507 public void gauss15() {
508 float[][] k = Gauss.getGauss15();
509 convolve(k);
510 }
511
512 public void gauss31Fast() {
513 double sigma = 2.0;
514 float k[][] = Gauss.getGaussKernel(31,
515 31,
516 sigma);
517 convolveFast(k);
518 }
519
520 public void gauss31() {
521 double sigma = 2.0;
522 float k[][] = Gauss.getGaussKernel(31,
523 31,
524 sigma);
525 Timer t = new Timer();
526 t.start();
527 convolve(k);
528 t.stop();
529 t.report();
530 }
531
532
533 public void medianSquare3x3() {
534 short[][] k = Kernels.getMedianCross3x3();
535 median(k);
536 }
537
538 public void medianSquare5x5() {
539 short[][] k = Kernels.getMedianCross5x5();
540 median(k);
541 }
542
543 public void medianOctagon5x5() {
544 short[][] k = Kernels.getMedianOctagon5x5();
545 median(k);
546 }
547
548 public void medianDiamond7x7() {
549 short[][] k = Kernels.getMedianDiamond();
550 median(k);
551 }
552
553 public void medianCross7x7() {
554 short[][] k = Kernels.getMedianCross7x7();
555 median(k);
556 }
557
558
559 public void medianSquare7x7() {
560 short[][] k = Kernels.getMedianSquare7x7();
561 median(k);
562 }
563
564 public void medianCross3x3() {
565 short k[][] = Kernels.getMedianCross3x3();
566 median(k);
567 }
568
569
570
571 public void median(short k[] []) {
572 Mat2.printMedian(k, "color median");
573 Timer t = new Timer();
574 t.start();
575 short[][] r = median(
576 shortImageBean.getR(), k);
577 shortImageBean.setR(r);
578 setG(median(shortImageBean.getG(), k));
579 setB(median(shortImageBean.getB(), k));
580 t.print("Median filter time");
581 short2Image();
582 }
583
584 public void medianBottom(short f[][],
585 short k[][],
586 short h[][]) {
587 int windowLength = 0;
588 int window[];
589 int uc = 0;
590 int vc = 0;
591 System.out.println("k=" + k.length);
592 uc = k.length / 2;
593 vc = k[0].length / 2;
594 windowLength = Mat2.numberOfNonZeros(k);
595 window = new int[windowLength];
596
597 //median bottom
598 for (int x = 0; x < getImageWidth() - 1; x++)
599 for (int y = 0; y < vc; y++) {
600 int loc = 0;
601 for (int v = -vc; v <= vc; v++)
602 for (int u = -uc; u <= uc; u++)
603 if (k[u + uc][v + vc] !=
604 0)
605 window[loc++] =
606 f[cx(x - u)][cy(
607 y - v)];
608 h[x][y] = (short) median(window);
609 }
610 }
611
612 public void medianLeft(short f[][],
613 short k[][],
614 short h[][]) {
615 int uc = k.length / 2;
616 int vc = k[0].length / 2;
617
618 int windowLength = Mat2.numberOfNonZeros(
619 k);
620 int window[] = new int[windowLength];
621 //median bottom
622 //median left
623 for (int x = 0; x < uc; x++)
624 for (int y = vc; y <
625 getImageHeight() -
626 vc; y++) {
627 int loc = 0;
628 for (int v = -vc; v <= vc; v++)
629 for (int u = -uc; u <= uc; u++)
630 if (k[u + uc][v + vc] !=
631 0)
632 window[loc++] =
633 f[cx(x - u)][cy(
634 y - v)];
635 h[x][y] = (short) median(window);
636 }
637 }
638
639 public void medianRightAndTop(short f[][],
640 short k[][],
641 short h[][]) {
642 int uc = k.length / 2;
643 int vc = k[0].length / 2;
644
645 int windowLength = Mat2.numberOfNonZeros(
646 k);
647 int window[] = new int[windowLength];
648 //median right
649 for (
650 int x = getImageWidth() - uc;
651 x < getImageWidth() - 1; x++)
652 for (int y = vc; y <
653 getImageHeight() -
654 vc; y++) {
655 int loc = 0;
656 for (int v = -vc; v <= vc; v++)
657 for (int u = -uc; u <= uc; u++)
658 if (k[u + uc][v + vc] !=
659 0)
660 window[loc++] =
661 f[cx(x - u)][cy(
662 y - v)];
663 h[x][y] = (short) median(window);
664 }
665
666 //median top
667 for (int x = 0; x < getImageWidth() - 1; x++) {
668 for (
669 int y = getImageHeight() -
670 vc;
671 y < getImageHeight() - 1; y++) {
672 int loc = 0;
673 for (int v = -vc; v <= vc; v++)
674 for (int u = -uc; u <= uc; u++)
675 if (k[u + uc][v + vc] !=
676 0)
677 window[loc++] =
678 f[cx(x - u)][cy(
679 y - v)];
680 h[x][y] = (short) median(window);
681 }
682 }
683 }
684
685 // median, optimze the edges
686 public short[][] median(short f[][],
687 short k[][]) {
688 short h[][] = medianNoEdge(f, k);
689 medianBottom(f, k, h);
690 medianLeft(f, k, h);
691 medianRightAndTop(f, k, h);
692 return h;
693 }
694
695 public short[][] medianNoEdge(short f[][],
696 short k[][]) {
697 int uc = k.length / 2;
698 int vc = k[0].length / 2;
699 short h[][] = new short[getImageWidth()][getImageHeight()];
700
701 int windowLength = Mat2.numberOfNonZeros(
702 k);
703 int window[] = new int[windowLength];
704
705 for (int x = uc; x <
706 getImageWidth() - uc; x++) {
707 for (int y = vc; y <
708 getImageHeight() -
709 vc; y++) {
710 int loc = 0;
711 for (int v = -vc; v <= vc; v++)
712 for (int u = -uc; u <= uc; u++)
713 if (k[u + uc][v + vc] !=
714 0)
715 window[loc++] =
716 f[x - u][y - v];
717 h[x][y] = (short) median(window);
718 f[x][y] = (short) median(window);
719 }
720
721 }
722 return h;
723 }
724
725 public void testMedian() {
726 int a[] = {1, 2, 3, 5, 4, 3, 2, 5, 6, 7};
727 System.out.println(
728 "The median =" + median(a));
729 }
730
731 public static void main(String args[]) {
732 Mat2.testOutlier();
733 }
734
735 public int median(int a[]) {
736 int mid = a.length / 2 - 1;
737 if (isComputeOutlier()) {
738 if (!Mat2.outlierHere(a)) {
739 return a[mid];
740 }
741 }
742 setNumberOfOutliers(
743 getNumberOfOutliers() + 1);
744 Mat2.intQuickSort(a);
745
746 if ((a.length & 1) == 1)
747 return a[mid];
748 return (int) ((a[mid] + a[mid + 1] + 0.5) /
749 2);
750 }
751 // The sloooww way to do a median filter.
752 // This one uses fancy design patterns,
753 // including the template method.
754 // What are these CS people thinking?
755 // 18 seconds to do a 128x128 grayscale median
756 // filter with quicksort using MRJ 2.0
757 // on a powermac 8100/100.
758 // Gosh!
759 // Simple quicksort based median filter
760 // works in 1/2 second for the same image
761 // yes...36 times faster!
762 public short[][] medianSlow(short f[][],
763 short k[][]) {
764 int uc = k.length / 2;
765 int vc = k[0].length / 2;
766 short h[][] = new short[getImageWidth()][getImageHeight()];
767 Cshort cs = new Cshort(0);
768 Vector window = new Vector();
769 int windowLength = Mat2.numberOfNonZeros(
770 k);
771 for (int i = 0; i < windowLength; i++)
772 window.addElement(new Cshort(0));
773
774 for (int x = uc; x <
775 getImageWidth() - uc; x++) {
776 for (int y = vc; y <
777 getImageHeight() -
778 vc; y++) {
779 int loc = 0;
780 for (int v = -vc; v <= vc; v++)
781 for (int u = -uc; u <= uc; u++)
782 if (k[u + uc][v + vc] !=
783 0.0f) {
784 cs =
785 (Cshort) window.elementAt(
786 loc++);
787 cs.setValue(
788 (f[x - u][y -
789 v]));
790 }
791 h[x][y] = Mat2.median(window);
792 }
793
794 }
795 return h;
796 }
797
798 public boolean isComputeOutlier() {
799 return computeOutlier;
800 }
801
802 public void setComputeOutlier(
803 boolean computeOutlier) {
804 this.computeOutlier = computeOutlier;
805 }
806
807 public int getNumberOfOutliers() {
808 return numberOfOutliers;
809 }
810
811 public void setNumberOfOutliers(
812 int numberOfOutliers) {
813 this.numberOfOutliers = numberOfOutliers;
814 }
815
816 public Menu getSpatialFilterMenu() {
817 return SpatialFilterMenu;
818 }
819 }