Libraryless. Click here for Pure Java version (8799L/51K).
1 | // The "direct" implementation of an integral image that just |
2 | // stores the whole computed matrix in an array |
3 | // Precision: 8 bit per channel (RGB) |
4 | // Note: There is a better implementation in MinimalRecognizer (#1032199) with flexible channels including grayscale |
5 | final sclass IntegralImage implements IIntegralImage { |
6 | int w, h; |
7 | int[] data; // 3 ints per pixel |
8 | |
9 | *(RGBImage img) { |
10 | init(img); |
11 | } |
12 | |
13 | void init(RGBImage img) { |
14 | w = img.w(); |
15 | h = img.h(); |
16 | if (longMul(w, h) > 8000000) fail("Image too big: " + w + "*" + h); |
17 | data = new int[w*h*3]; |
18 | int i = 0; |
19 | for y to h: { |
20 | int sumR = 0, sumG = 0, sumB = 0; |
21 | for x to w: { |
22 | int rgb = img.getInt(x, y); |
23 | sumR += (rgb >> 16) & 0xFF; |
24 | sumG += (rgb >> 8) & 0xFF; |
25 | sumB += rgb & 0xFF; |
26 | data[i] = y > 0 ? sumR + data[i-w*3] : sumR; |
27 | data[i+1] = y > 0 ? sumG + data[i-w*3+1] : sumG; |
28 | data[i+2] = y > 0 ? sumB + data[i-w*3+2] : sumB; |
29 | i += 3; |
30 | } |
31 | } |
32 | } |
33 | |
34 | *(MakesBufferedImage img) { |
35 | if (img cast RGBImage) |
36 | init(img); |
37 | else |
38 | init(toBufferedImage(img)); |
39 | } |
40 | |
41 | *(BufferedImage img) { |
42 | init(img); |
43 | } |
44 | |
45 | void init(BufferedImage img) { |
46 | w = img.getWidth(); |
47 | h = img.getHeight(); |
48 | if (longMul(w, h) > 8000000) fail("Image too big: " + w + "*" + h); |
49 | int[] pixels = pixelsOfBufferedImage(img); |
50 | data = new int[w*h*3]; |
51 | int i = 0, j = 0, sumR = 0, sumG = 0, sumB = 0; |
52 | for x to w: { |
53 | int rgb = pixels[j++]; |
54 | data[i++] = (sumR += (rgb >> 16) & 0xFF); |
55 | data[i++] = (sumG += (rgb >> 8) & 0xFF); |
56 | data[i++] = (sumB += rgb & 0xFF); |
57 | } |
58 | for (int y = 1; y < h; y++) { |
59 | sumR = sumG = sumB = 0; |
60 | for x to w: { |
61 | int rgb = pixels[j++]; |
62 | sumR += (rgb >> 16) & 0xFF; |
63 | sumG += (rgb >> 8) & 0xFF; |
64 | sumB += rgb & 0xFF; |
65 | data[i] = sumR + data[i-w*3]; |
66 | data[i+1] = sumG + data[i-w*3+1]; |
67 | data[i+2] = sumB + data[i-w*3+2]; |
68 | i += 3; |
69 | } |
70 | } |
71 | } |
72 | |
73 | // precise version [TO TEST!] |
74 | public double getIntegralValue(double x, double y, int channel) { |
75 | int xFloor = ifloor(x), yFloor = ifloor(y); |
76 | double val = getIntegralValue(xFloor, yFloor, channel); |
77 | |
78 | // at integer coordinate? |
79 | if (xFloor == x && yFloor == y) |
80 | ret val; |
81 | |
82 | // at non-integer coordinate, perform subpixel calculation |
83 | double val2 = getIntegralValue(xFloor+1, yFloor, channel); |
84 | double val3 = getIntegralValue(xFloor , yFloor+1, channel); |
85 | double val4 = getIntegralValue(xFloor+1, yFloor+1, channel); |
86 | |
87 | ret blend2D(val, val2, val3, val4, x-xFloor, y-yFloor); |
88 | } |
89 | |
90 | // gets the integral value at x/y for given RGB channel |
91 | public double getIntegralValue aka get(int x, int y, int channel) { |
92 | ret x < 0 || y < 0 ? 0 |
93 | : data[(min(y, h-1)*w+min(x, w-1))*3+channel]; |
94 | } |
95 | |
96 | // gets sum of the 3 channels |
97 | public double getIntegralValue aka get(int x, int y) { |
98 | if (x < 0 || y < 0) ret 0; |
99 | int i = (min(y, h-1)*w+min(x, w-1))*3; |
100 | ret data[i]+data[i+1]+data[i+2]; |
101 | } |
102 | |
103 | toString { |
104 | ret "IntegralImage " + w + "*" + h + ", brightness: " + averageBrightness(); |
105 | } |
106 | |
107 | public BufferedImage getBufferedImage() { ret integralImageToBufferedImage(this); } |
108 | public int getWidth() { ret w; } |
109 | public int getHeight() { ret h; } |
110 | |
111 | // serialization |
112 | |
113 | O _serialize() { ret litobjectarray(w, h, data); } |
114 | static IntegralImage _deserialize(O[] l) { ret IntegralImage((int) l[0], (int) l[1], (int[]) l[2]); } |
115 | *(int *w, int *h, int[] *data) {} |
116 | } |
Began life as a copy of #1009125
download show line numbers debug dex old transpilations
Travelled to 12 computer(s): bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1019588 |
Snippet name: | IntegralImage (RGB, size limit 8 megapixels, uses 12 byte per pixel) |
Eternal ID of this version: | #1019588/44 |
Text MD5: | d847e86b0a8a579b0e80424f22d25327 |
Transpilation MD5: | 3e14e1a733f7d676b432a72db954b112 |
Author: | stefan |
Category: | javax / gui |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2022-03-13 01:45:09 |
Source code size: | 3657 bytes / 116 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 556 / 1312 |
Version history: | 43 change(s) |
Referenced in: | [show references] |