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.video.processing.effects;
31
32 import java.util.LinkedList;
33
34 import org.openimaj.image.FImage;
35 import org.openimaj.image.MBFImage;
36 import org.openimaj.image.processing.convolution.FGaussianConvolve;
37 import org.openimaj.image.processing.convolution.FImageConvolveSeparable;
38 import org.openimaj.image.processing.resize.ResizeProcessor;
39 import org.openimaj.video.Video;
40 import org.openimaj.video.processor.VideoProcessor;
41
42
43
44
45
46
47
48
49 public class GreyscaleSlitScanProcessor extends VideoProcessor<MBFImage>
50 {
51
52 private final LinkedList<MBFImage> cache = new LinkedList<MBFImage>();
53
54
55 private final float[] blurKern = FGaussianConvolve.makeKernel( 0.5f );
56
57
58 private int cacheSize = 240;
59
60
61 private FImage timemapImage = null;
62
63
64 private boolean needToFixTimemap = true;
65
66
67
68
69
70
71
72 public GreyscaleSlitScanProcessor( final FImage timemap )
73 {
74 this( timemap, 240 );
75 }
76
77
78
79
80
81
82
83
84 public GreyscaleSlitScanProcessor( final FImage timemap, final int cacheSize )
85 {
86 this.cacheSize = cacheSize;
87 this.timemapImage = timemap;
88 }
89
90
91
92
93
94
95
96
97
98 public GreyscaleSlitScanProcessor( final Video<MBFImage> video, final FImage timemap, final int cacheSize )
99 {
100 super( video );
101 this.cacheSize = cacheSize;
102 this.timemapImage = timemap;
103 }
104
105
106
107
108
109
110
111
112 public GreyscaleSlitScanProcessor( final int cacheSize )
113 {
114 this.cacheSize = cacheSize;
115 }
116
117
118
119
120
121
122
123
124 public GreyscaleSlitScanProcessor( final Video<MBFImage> video, final int cacheSize )
125 {
126 super( video );
127 this.cacheSize = cacheSize;
128 }
129
130 @Override
131 public MBFImage processFrame( final MBFImage frame )
132 {
133 this.addToCache( frame );
134
135 if( this.timemapImage == null || this.timemapImage.getWidth() != frame.getWidth() ||
136 this.timemapImage.getHeight() != frame.getHeight() )
137 this.needToFixTimemap = true;
138
139 if( this.needToFixTimemap )
140 this.fixTimemapImage( frame.getWidth(), frame.getHeight() );
141
142 final int height = frame.getHeight();
143 final int width = frame.getWidth();
144
145 for( int y = 0; y < height; y++ )
146 {
147 for( int x = 0; x < width; x++ )
148 {
149 int index = (int)this.timemapImage.pixels[y][x];
150 if( index >= this.cache.size() )
151 index = this.cache.size()-1;
152
153 final MBFImage cacheImage = this.cache.get( index );
154 frame.setPixel( x, y, cacheImage.getPixel(x,y) );
155 }
156 }
157
158 for( final FImage f : frame.bands )
159 {
160 FImageConvolveSeparable.convolveVertical( f, this.blurKern );
161 }
162
163 if( this.cache.size() >= this.cacheSize ) this.cache.removeLast();
164
165 return frame;
166 }
167
168
169
170
171
172
173
174
175 private void fixTimemapImage( final int width, final int height )
176 {
177
178 this.timemapImage = ResizeProcessor.resample( this.timemapImage, width, height );
179
180
181 for( int y = 0; y < this.timemapImage.getHeight(); y++ )
182 for( int x = 0; x < this.timemapImage.getWidth(); x++ )
183 this.timemapImage.pixels[y][x] = (float)
184 (Math.floor( this.timemapImage.pixels[y][x] * this.cacheSize));
185 this.needToFixTimemap = false;
186 }
187
188 private void addToCache( final MBFImage frame )
189 {
190 final MBFImage f = frame.clone();
191 this.cache.addFirst( f );
192 }
193 }