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 package org.openimaj.image.colour;
31
32 import org.openimaj.image.FImage;
33 import org.openimaj.image.MBFImage;
34
35
36
37
38
39
40 public enum ColourSpace {
41
42
43
44 RGB {
45 @Override
46 public MBFImage convertFromRGB(final MBFImage input) {
47 return input;
48 }
49
50 @Override
51 public int getNumBands() {
52 return 3;
53 }
54
55 @Override
56 public MBFImage convertToRGB(final MBFImage input) {
57 return input;
58 }
59
60 @Override
61 public float computeIntensity(float[] colour) {
62 return (colour[0] + colour[1] + colour[2]) / 3f;
63 }
64 },
65
66
67
68 HSV {
69 @Override
70 public MBFImage convertFromRGB(final MBFImage input) {
71 return Transforms.RGB_TO_HSV(input);
72 }
73
74 @Override
75 public int getNumBands() {
76 return 3;
77 }
78
79 @Override
80 public MBFImage convertToRGB(final MBFImage input) {
81 return Transforms.HSV_TO_RGB(input);
82 }
83
84 @Override
85 public float computeIntensity(float[] colour) {
86 return colour[2];
87 }
88 },
89
90
91
92 HSI {
93 @Override
94 public MBFImage convertFromRGB(final MBFImage input) {
95 return Transforms.RGB_TO_HSI(input);
96 }
97
98 @Override
99 public int getNumBands() {
100 return 3;
101 }
102
103 @Override
104 public MBFImage convertToRGB(final MBFImage input) {
105 throw new UnsupportedOperationException("colour transform not implemented");
106 }
107
108 @Override
109 public float computeIntensity(float[] colour) {
110 return colour[2];
111 }
112 },
113
114
115
116
117
118 H2SV {
119 @Override
120 public MBFImage convertFromRGB(final MBFImage input) {
121 return Transforms.RGB_TO_H2SV(input);
122 }
123
124 @Override
125 public int getNumBands() {
126 return 4;
127 }
128
129 @Override
130 public MBFImage convertToRGB(final MBFImage input) {
131 return Transforms.HSV_TO_RGB(Transforms.H2SV_TO_HSV_Simple(input));
132 }
133
134 @Override
135 public float computeIntensity(float[] colour) {
136 return colour[3];
137 }
138 },
139
140
141
142
143
144 H2SV_2 {
145 @Override
146 public MBFImage convertFromRGB(final MBFImage input) {
147 return Transforms.RGB_TO_H2SV_2(input);
148 }
149
150 @Override
151 public int getNumBands() {
152 return 4;
153 }
154
155 @Override
156 public MBFImage convertToRGB(final MBFImage input) {
157 return Transforms.HSV_TO_RGB(Transforms.H2SV2_TO_HSV_Simple(input));
158 }
159
160 @Override
161 public float computeIntensity(float[] colour) {
162 return colour[3];
163 }
164 },
165
166
167
168
169
170 H2S {
171 @Override
172 public MBFImage convertFromRGB(final MBFImage input) {
173 return Transforms.RGB_TO_H2S(input);
174 }
175
176 @Override
177 public int getNumBands() {
178 return 3;
179 }
180
181 @Override
182 public MBFImage convertToRGB(final MBFImage input) {
183 throw new UnsupportedOperationException("colour transform not implemented");
184 }
185
186 @Override
187 public float computeIntensity(float[] colour) {
188 return 0;
189 }
190 },
191
192
193
194
195
196 H2S_2 {
197 @Override
198 public MBFImage convertFromRGB(final MBFImage input) {
199 return Transforms.RGB_TO_H2S_2(input);
200 }
201
202 @Override
203 public int getNumBands() {
204 return 3;
205 }
206
207 @Override
208 public MBFImage convertToRGB(final MBFImage input) {
209 throw new UnsupportedOperationException("colour transform not implemented");
210 }
211
212 @Override
213 public float computeIntensity(float[] colour) {
214 return 0;
215 }
216 },
217
218
219
220 LUMINANCE_AVG {
221 @Override
222 public MBFImage convertFromRGB(final MBFImage input) {
223 return new MBFImage(this, Transforms.calculateIntensity(input));
224 }
225
226 @Override
227 public int getNumBands() {
228 return 1;
229 }
230
231 @Override
232 public MBFImage convertToRGB(final MBFImage input) {
233 return new MBFImage(input.bands.get(0).clone(), input.bands.get(0).clone(), input.bands.get(0).clone());
234 }
235
236 @Override
237 public float computeIntensity(float[] colour) {
238 return colour[0];
239 }
240 },
241
242
243
244 LUMINANCE_NTSC {
245 @Override
246 public MBFImage convertFromRGB(final MBFImage input) {
247 return new MBFImage(this, Transforms.calculateIntensityNTSC(input));
248 }
249
250 @Override
251 public int getNumBands() {
252 return 1;
253 }
254
255 @Override
256 public MBFImage convertToRGB(final MBFImage input) {
257 return new MBFImage(input.bands.get(0).clone(), input.bands.get(0).clone(), input.bands.get(0).clone());
258 }
259
260 @Override
261 public float computeIntensity(float[] colour) {
262 return colour[0];
263 }
264 },
265
266
267
268 HUE {
269 @Override
270 public MBFImage convertFromRGB(final MBFImage input) {
271 return new MBFImage(this, Transforms.calculateHue(input));
272 }
273
274 @Override
275 public int getNumBands() {
276 return 1;
277 }
278
279 @Override
280 public MBFImage convertToRGB(final MBFImage input) {
281 return new MBFImage(input.bands.get(0).clone(), input.bands.get(0).clone(), input.bands.get(0).clone());
282 }
283
284 @Override
285 public float computeIntensity(float[] colour) {
286 return 0;
287 }
288 },
289
290
291
292 SATURATION {
293 @Override
294 public MBFImage convertFromRGB(final MBFImage input) {
295 return new MBFImage(this, Transforms.calculateSaturation(input));
296 }
297
298 @Override
299 public int getNumBands() {
300 return 1;
301 }
302
303 @Override
304 public MBFImage convertToRGB(final MBFImage input) {
305 return new MBFImage(input.bands.get(0).clone(), input.bands.get(0).clone(), input.bands.get(0).clone());
306 }
307
308 @Override
309 public float computeIntensity(float[] colour) {
310 return 0;
311 }
312 },
313
314
315
316 RGB_INTENSITY_NORMALISED {
317 @Override
318 public MBFImage convertFromRGB(final MBFImage input) {
319 return Transforms.RGB_TO_RGB_NORMALISED(input);
320 }
321
322 @Override
323 public int getNumBands() {
324 return 3;
325 }
326
327 @Override
328 public MBFImage convertToRGB(final MBFImage input) {
329 return input;
330 }
331
332 @Override
333 public float computeIntensity(float[] colour) {
334 return (colour[0] + colour[1] + colour[2]) / 3f;
335 }
336 },
337
338
339
340 CUSTOM {
341 @Override
342 public MBFImage convertFromRGB(final MBFImage input) {
343 throw new UnsupportedOperationException("Cannot convert to the custom color-space");
344 }
345
346 @Override
347 public int getNumBands() {
348 return 1;
349 }
350
351 @Override
352 public MBFImage convertToRGB(final MBFImage input) {
353 throw new UnsupportedOperationException("colour transform not implemented");
354 }
355
356 @Override
357 public float computeIntensity(float[] colour) {
358 return 0;
359 }
360 },
361
362
363
364 RGBA {
365 @Override
366 public MBFImage convertFromRGB(final MBFImage input) {
367 return new MBFImage(input.bands.get(0), input.bands.get(1), input.bands.get(2), new FImage(
368 input.bands.get(0).width, input.bands.get(0).height).addInplace(1.0f));
369 }
370
371 @Override
372 public int getNumBands() {
373 return 4;
374 }
375
376 @Override
377 public MBFImage convertToRGB(final MBFImage input) {
378 return new MBFImage(input.bands.get(0).clone(), input.bands.get(1).clone(), input.bands.get(2).clone());
379 }
380
381 @Override
382 public float computeIntensity(float[] colour) {
383 return (colour[0] + colour[1] + colour[2]) / 3f;
384 }
385 },
386
387
388
389 HSL {
390 @Override
391 public MBFImage convertFromRGB(final MBFImage input) {
392 return Transforms.RGB_TO_HSL(input);
393 }
394
395 @Override
396 public MBFImage convertToRGB(final MBFImage input) {
397 throw new UnsupportedOperationException("colour transform not implemented");
398 }
399
400 @Override
401 public int getNumBands() {
402 return 3;
403 }
404
405 @Override
406 public float computeIntensity(float[] colour) {
407 return colour[2];
408 }
409 },
410
411
412
413 HSY {
414 @Override
415 public MBFImage convertFromRGB(final MBFImage input) {
416 return Transforms.RGB_TO_HSY(input);
417 }
418
419 @Override
420 public MBFImage convertToRGB(final MBFImage input) {
421 throw new UnsupportedOperationException("colour transform not implemented");
422 }
423
424 @Override
425 public int getNumBands() {
426 return 3;
427 }
428
429 @Override
430 public float computeIntensity(float[] colour) {
431 return colour[2];
432 }
433 },
434
435
436
437 HS {
438 @Override
439 public MBFImage convertFromRGB(final MBFImage input) {
440 return Transforms.RGB_TO_HS(input);
441 }
442
443 @Override
444 public MBFImage convertToRGB(final MBFImage input) {
445 throw new UnsupportedOperationException("colour transform not implemented");
446 }
447
448 @Override
449 public int getNumBands() {
450 return 2;
451 }
452
453 @Override
454 public float computeIntensity(float[] colour) {
455 return 0;
456 }
457 },
458
459
460
461 HS_2 {
462 @Override
463 public MBFImage convertFromRGB(final MBFImage input) {
464 return Transforms.RGB_TO_HS_2(input);
465 }
466
467 @Override
468 public MBFImage convertToRGB(final MBFImage input) {
469 throw new UnsupportedOperationException("colour transform not implemented");
470 }
471
472 @Override
473 public int getNumBands() {
474 return 2;
475 }
476
477 @Override
478 public float computeIntensity(float[] colour) {
479 return 0;
480 }
481 },
482
483
484
485
486
487 H1H2 {
488 @Override
489 public MBFImage convertFromRGB(final MBFImage input) {
490 return Transforms.H_TO_H1H2(Transforms.calculateHue(input));
491 }
492
493 @Override
494 public MBFImage convertToRGB(final MBFImage input) {
495 throw new UnsupportedOperationException("colour transform not implemented");
496 }
497
498 @Override
499 public int getNumBands() {
500 return 2;
501 }
502
503 @Override
504 public float computeIntensity(float[] colour) {
505 return 0;
506 }
507 },
508
509
510
511
512
513 H1H2_2 {
514 @Override
515 public MBFImage convertFromRGB(final MBFImage input) {
516 return Transforms.H_TO_H1H2_2(Transforms.calculateHue(input));
517 }
518
519 @Override
520 public MBFImage convertToRGB(final MBFImage input) {
521 throw new UnsupportedOperationException("colour transform not implemented");
522 }
523
524 @Override
525 public int getNumBands() {
526 return 2;
527 }
528
529 @Override
530 public float computeIntensity(float[] colour) {
531 return 0;
532 }
533 },
534
535
536
537
538
539 CIE_XYZ {
540 @Override
541 public MBFImage convertFromRGB(final MBFImage input) {
542 return Transforms.RGB_TO_CIEXYZ(input);
543 }
544
545 @Override
546 public MBFImage convertToRGB(final MBFImage input) {
547 return Transforms.CIEXYZ_TO_RGB(input);
548 }
549
550 @Override
551 public int getNumBands() {
552 return 3;
553 }
554
555 @Override
556 public float computeIntensity(float[] colour) {
557 return colour[1];
558 }
559 },
560
561
562
563
564
565
566
567
568
569
570 CIE_Lab {
571 @Override
572 public MBFImage convertFromRGB(final MBFImage input) {
573 return Transforms.RGB_TO_CIELab(input);
574 }
575
576 @Override
577 public MBFImage convertToRGB(final MBFImage input) {
578 return Transforms.CIELab_TO_RGB(input);
579 }
580
581 @Override
582 public int getNumBands() {
583 return 3;
584 }
585
586 @Override
587 public float computeIntensity(float[] colour) {
588 return colour[0];
589 }
590 },
591
592
593
594
595
596
597
598
599
600 CIE_Lab_Norm {
601 @Override
602 public MBFImage convertFromRGB(final MBFImage input) {
603 return Transforms.RGB_TO_CIELabNormalised(input);
604 }
605
606 @Override
607 public MBFImage convertToRGB(final MBFImage input) {
608 return Transforms.CIELabNormalised_TO_RGB(input);
609 }
610
611 @Override
612 public int getNumBands() {
613 return 3;
614 }
615
616 @Override
617 public float computeIntensity(float[] colour) {
618 return colour[0];
619 }
620 },
621
622
623
624
625
626
627
628 CIE_Luv {
629
630 @Override
631 public MBFImage convertFromRGB(final MBFImage input) {
632 return Transforms.RGB_TO_CIELUV(input);
633 }
634
635 @Override
636 public MBFImage convertToRGB(final MBFImage input) {
637 return Transforms.CIELUV_TO_RGB(input);
638 }
639
640 @Override
641 public int getNumBands() {
642 return 3;
643 }
644
645 @Override
646 public float computeIntensity(float[] colour) {
647 return colour[0];
648 }
649 },
650
651
652
653
654
655
656 YUV {
657 @Override
658 public MBFImage convertFromRGB(final MBFImage input) {
659 return Transforms.RGB_TO_YUV(input);
660 }
661
662 @Override
663 public MBFImage convertToRGB(final MBFImage input) {
664 return Transforms.YUV_TO_RGB(input);
665 }
666
667 @Override
668 public int getNumBands() {
669 return 3;
670 }
671
672 @Override
673 public float computeIntensity(float[] colour) {
674 return colour[2];
675 }
676 },
677
678
679
680
681
682
683 YUV_Norm {
684 @Override
685 public MBFImage convertFromRGB(final MBFImage input) {
686 return Transforms.RGB_TO_YUVNormalised(input);
687 }
688
689 @Override
690 public MBFImage convertToRGB(final MBFImage input) {
691 return Transforms.YUVNormalised_TO_RGB(input);
692 }
693
694 @Override
695 public int getNumBands() {
696 return 3;
697 }
698
699 @Override
700 public float computeIntensity(float[] colour) {
701 return colour[2];
702 }
703 },
704
705
706
707
708
709
710
711
712
713
714 MODIFIED_OPPONENT {
715 @Override
716 public MBFImage convertFromRGB(MBFImage input) {
717 final FImage intensity = Transforms.calculateIntensityNTSC(input);
718
719 final float alpha = 0.01f;
720 final FImage rg = new FImage(input.getWidth(), input.getHeight());
721 final FImage rb = new FImage(input.getWidth(), input.getHeight());
722
723 final float[][] r = input.bands.get(0).pixels;
724 final float[][] g = input.bands.get(1).pixels;
725 final float[][] b = input.bands.get(2).pixels;
726
727 for (int y = 0; y < input.getHeight(); y++) {
728 for (int x = 0; x < input.getWidth(); x++) {
729 rg.pixels[y][x] = (float) (r[y][x] - g[y][x] / Math.sqrt(2) + alpha * intensity.pixels[y][x]);
730 rb.pixels[y][x] = (float) ((r[y][x] + g[y][x] - 2 * b[y][x]) / Math.sqrt(6) + alpha
731 * intensity.pixels[y][x]);
732 }
733 }
734
735 return new MBFImage(ColourSpace.MODIFIED_OPPONENT, intensity, rg, rb);
736 }
737
738 @Override
739 public MBFImage convertToRGB(MBFImage input) {
740 throw new UnsupportedOperationException("Not supported (yet)");
741 }
742
743 @Override
744 public int getNumBands() {
745 return 3;
746 }
747
748 @Override
749 public float computeIntensity(float[] colour) {
750 return colour[0];
751 }
752 },
753
754
755
756
757
758
759
760 OPPONENT {
761 @Override
762 public MBFImage convertFromRGB(MBFImage input) {
763 final FImage intensity = Transforms.calculateIntensity(input);
764
765 final FImage o1 = new FImage(input.getWidth(), input.getHeight());
766 final FImage o2 = new FImage(input.getWidth(), input.getHeight());
767
768 final float[][] r = input.bands.get(0).pixels;
769 final float[][] g = input.bands.get(1).pixels;
770 final float[][] b = input.bands.get(2).pixels;
771
772 for (int y = 0; y < input.getHeight(); y++) {
773 for (int x = 0; x < input.getWidth(); x++) {
774 o1.pixels[y][x] = (float) (r[y][x] - g[y][x] / Math.sqrt(2));
775 o2.pixels[y][x] = (float) ((r[y][x] + g[y][x] - 2 * b[y][x]) / Math.sqrt(6));
776 }
777 }
778
779 return new MBFImage(ColourSpace.MODIFIED_OPPONENT, intensity, o1, o2);
780 }
781
782 @Override
783 public MBFImage convertToRGB(MBFImage input) {
784 throw new UnsupportedOperationException("Not supported (yet)");
785 }
786
787 @Override
788 public int getNumBands() {
789 return 3;
790 }
791
792 @Override
793 public float computeIntensity(float[] colour) {
794 return colour[0];
795 }
796 };
797
798
799
800
801
802
803
804 public abstract MBFImage convertFromRGB(MBFImage input);
805
806
807
808
809
810
811
812
813 public Float[] convertFromRGB(Float[] input){
814 MBFImage singlePixel = new MBFImage(1,1,ColourSpace.RGB);
815 singlePixel.setPixel(0, 0, input);
816 return convertFromRGB(singlePixel).getPixel(0,0);
817 };
818
819
820
821
822
823
824
825
826 public Float[] convertToRGB(Float[] input){
827 MBFImage singlePixel = new MBFImage(1,1,this);
828 singlePixel.setPixel(0, 0, input);
829 return convertToRGB(singlePixel).getPixel(0,0);
830 };
831
832
833
834
835
836
837
838
839 public abstract MBFImage convertToRGB(MBFImage input);
840
841
842
843
844
845
846
847
848 public MBFImage convert(final MBFImage input) {
849 return this.convertFromRGB(input.getColourSpace().convertToRGB(input));
850 }
851
852
853
854
855
856
857
858
859
860
861 public static MBFImage convert(final MBFImage image, final ColourSpace cs) {
862 return cs.convertFromRGB(image.colourSpace.convertToRGB(image));
863 }
864
865
866
867
868
869
870 public abstract int getNumBands();
871
872
873
874
875
876
877
878
879
880
881
882 public abstract float computeIntensity(float[] colour);
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903 public Float[] sanitise(final Float[] colour)
904 {
905
906
907
908
909 if (colour.length >= this.getNumBands())
910 return colour;
911
912
913
914 if (colour.length == 1)
915 {
916 final Float[] newColour = new Float[this.getNumBands()];
917 for (int i = 0; i < newColour.length; i++)
918 newColour[i] = colour[0];
919 return newColour;
920 }
921
922
923
924 final Float[] newColour = new Float[this.getNumBands()];
925
926
927 for (int i = 0; i < colour.length; i++)
928 newColour[i] = colour[i];
929
930
931 for (int i = colour.length; i < newColour.length; i++)
932 newColour[i] = 1f;
933
934 return newColour;
935 }
936 }