source: trunk/MagicSoft/Cosy/videodev/FilterLed.cc@ 2375

Last change on this file since 2375 was 2278, checked in by tbretz, 21 years ago
*** empty log message ***
File size: 8.2 KB
Line 
1#include "FilterLed.h"
2
3#include <memory.h> // memset
4#include <iostream.h> // cout
5
6#include "Led.h"
7#include "Leds.h"
8#include "Ring.h"
9
10ClassImp(FilterLed);
11
12void FilterLed::DrawCircle(float cx, float cy, float rpix, byte col) const
13{
14 if (cx-rpix<1 || cy-rpix<1 || cx+rpix>fW-2 || cy+rpix>fH-2)
15 return;
16
17 for (int dx=-(int)(rpix*0.7); dx<(int)(rpix*0.7); dx++)
18 {
19 const int dy = (int)sqrt(rpix*rpix-dx*dx);
20 fImg[(int)(cx+dx) + (int)(cy-dy)*fW] = col;
21 fImg[(int)(cx+dx) + (int)(cy+dy)*fW] = col;
22 fImg[(int)(cx-dy) + (int)(cy+dx)*fW] = col;
23 fImg[(int)(cx+dy) + (int)(cy+dx)*fW] = col;
24 }
25}
26
27void FilterLed::DrawCircle(const Ring &l, byte col=0x40) const
28{
29 DrawCircle(l.GetX(), l.GetY(), l.GetR(), col);
30}
31
32void FilterLed::DrawCircle(const Ring &l, double r, byte col=0x40) const
33{
34 DrawCircle(l.GetX(), l.GetY(), r, col);
35}
36
37void FilterLed::DrawBox(const int x1, const int y1,
38 const int x2, const int y2,
39 const int col) const
40{
41 for (int x=x1; x<x2+1; x++)
42 for (int y=y1; y<y2+1; y++)
43 if (x>=0 && x<fW-1 && y>=0 && y<fH-1)
44 fImg[y*fW+x] = col;
45}
46
47void FilterLed::MarkPoint(const Led &led) const
48{
49 const int x = (int)(led.GetX()+.5);
50 const int y = (int)(led.GetY()+.5);
51 const int m = (int)(led.GetMag());
52
53 MarkPoint(x, y, m);
54}
55
56void FilterLed::MarkPoint(Float_t px, Float_t py, Float_t mag) const
57{
58 const int x = (int)(px+.5);
59 const int y = (int)(py+.5);
60 const int m = (int)(mag);
61
62 DrawBox(x-8, y, x-5, y, m);
63 DrawBox(x, y+5, x, y+8, m);
64 DrawBox(x+5, y, x+8, y, m);
65 DrawBox(x, y-8, x, y-5, m);
66 return;
67}
68
69void FilterLed::GetMinMax(const int offset, byte *min, byte *max) const
70{
71 *min = fImg[0];
72 *max = fImg[0];
73
74 byte *s = (byte*)fImg;
75 const byte *e0 = s+fW*fH;
76
77 //
78 // calculate mean value
79 //
80 while (s<e0)
81 {
82 const byte *e = s+fH-offset;
83 s += offset;
84
85 while (s<e)
86 {
87 if (*s>*max)
88 {
89 *max = *s;
90 if (*max-*min==255)
91 return;
92 }
93 if (*s<*min)
94 {
95 *min = *s;
96 if (*max-*min==255)
97 return;
98 }
99 s++;
100 }
101 s+=offset;
102 }
103}
104
105int FilterLed::GetMeanPosition(const int x, const int y,
106 const int box, float &mx, float &my) const
107{
108 unsigned int sumx=0;
109 unsigned int sumy=0;
110 unsigned int sum =0;
111
112 for (int dx=x-box; dx<x+box+1; dx++)
113 for (int dy=y-box; dy<y+box+1; dy++)
114 {
115 const byte &m = fImg[dy*fW+dx];
116
117 sumx += m*dx;
118 sumy += m*dy;
119 sum += m;
120 }
121
122 mx = (float)sumx/sum;
123 my = (float)sumy/sum;
124
125 return (int)my*fW + (int)mx;
126}
127
128int FilterLed::GetMeanPosition(const int x, const int y, const int box) const
129{
130 float mx, my;
131 return GetMeanPosition(x, y, box, mx, my);
132}
133/*
134void FilterLed::RemoveTwins(Leds &leds, Double_t radius)
135{
136 for (int i=first; i<leds.GetEntriesFast(); i++)
137 {
138 const Led &led1 = leds(i);
139
140 const Double_t x1 = led1.GetX();
141 const Double_t y1 = led1.GetY();
142
143 for (int j=first; j<leds.GetEntriesFast(); j++)
144 {
145 if (j==i)
146 continuel
147
148 const Led &led2 = leds(j);
149
150 const Double_t x2 = led2.GetX();
151 const Double_t y2 = led2.GetY();
152
153 const Double_t dx = x2-x1;
154 const Double_t dy = y2-y1;
155
156 if (dx*dx+dy*dy<radius*radius)
157 {
158 // FIXME: Interpolation
159 leds.Remove(led2);
160 }
161 }
162 }
163}
164*/
165void FilterLed::RemoveTwinsInterpol(Leds &leds, Int_t first, Double_t radius) const
166{
167 const Int_t num=leds.GetEntriesFast();
168
169 for (int i=first; i<num; i++)
170 {
171 Led *led1 = (Led*)leds.UncheckedAt(i);
172 if (!led1)
173 continue;
174
175 const Double_t x1 = led1->GetX();
176 const Double_t y1 = led1->GetY();
177
178 Double_t mag = led1->GetMag();
179 Double_t x = x1*mag;
180 Double_t y = y1*mag;
181
182 Double_t sqm = mag*mag;
183 Double_t sqx = x*x;
184 Double_t sqy = y*y;
185
186 Int_t n=1;
187
188 for (int j=first; j<num; j++)
189 {
190 if (i==j)
191 continue;
192
193 Led *led2 = (Led*)leds.UncheckedAt(j);
194 if (!led2)
195 continue;
196
197 Double_t x2 = led2->GetX();
198 Double_t y2 = led2->GetY();
199
200 const Double_t dx = x2-x1;
201 const Double_t dy = y2-y1;
202
203 if (dx*dx+dy*dy>radius*radius)
204 continue;
205
206 // Multiply with weihgt
207 const Double_t w = led2->GetMag();
208 x2 *= w;
209 y2 *= w;
210
211 x += x2;
212 y += y2;
213 mag += w;
214
215 sqx += x2*x2;
216 sqy += y2*y2;
217 sqm += w*w;
218
219 n++;
220 leds.Remove(led2);
221 }
222
223 x /= mag;
224 y /= mag;
225
226 sqx /= sqm;
227 sqy /= sqm;
228
229 leds.Add(x, y, 0/*sqrt(sqx-x*x)*/, 0/*sqrt(sqy-y*y)*/, mag/n);
230 leds.Remove(led1);
231 }
232 leds.Compress();
233}
234
235void FilterLed::ExecuteAndMark(Leds &leds, int xc, int yc) const
236{
237 const Int_t first = leds.GetEntriesFast();
238
239 Execute(leds, xc, yc);
240
241 // Mark Stars in image
242 for (int i=first; i<leds.GetEntriesFast(); i++)
243 MarkPoint(leds(i));
244}
245
246void FilterLed::Execute(int xc, int yc) const
247{
248 Leds leds;
249 ExecuteAndMark(leds, xc, yc);
250}
251
252void FilterLed::Execute(Leds &leds, int xc, int yc) const
253{
254 int x0 = xc-fBoxW;
255 int x1 = xc+fBoxW;
256 int y0 = yc-fBoxH;
257 int y1 = yc+fBoxH;
258
259 if (x0<0) x0=0;
260 if (y0<0) y0=0;
261 if (x1>fW) x1=fW;
262 if (y1>fH) y1=fH;
263
264 const int wx = x1-x0;
265 const int hy = y1-y0;
266
267 double sum = 0;
268 double sq = 0;
269
270 for (int x=x0; x<x1; x++)
271 for (int y=y0; y<y1; y++)
272 {
273 byte &b = fImg[y*fW+x];
274
275 sum += b;
276 sq += b*b;
277 }
278
279 sum /= wx*hy;
280 sq /= wx*hy;
281
282 const double sdev = sqrt(sq-sum*sum);
283 const byte max = sum+fCut*sdev>254 ? 254 : (byte)(sum+fCut*sdev);
284
285 //
286 // clean image from noise
287 // (FIXME: A lookup table could accelerate things...
288 //
289 for (int x=x0; x<x1; x++)
290 for (int y=y0; y<y1; y++)
291 {
292 byte &b = fImg[y*fW+x];
293 if (b<=max)
294 b = 0;
295 }
296
297 //
298 // find mean points
299 //
300 const int maxpnt = wx*hy>0x4000?0x4000:wx*hy;
301
302 int pos[maxpnt]; // (Use 'new' instead for big numbers!)
303 byte mag[maxpnt]; // (Use 'new' instead for big numbers!)
304
305 int cnt = 0;
306 for (int x=x0; x<x1; x++)
307 for (int y=y0; y<y1; y++)
308 {
309 byte &b = fImg[y*fW+x];
310 if (b==0)
311 continue;
312
313 const int ipos = GetMeanPosition(x, y, 5);
314
315 int j;
316 for (j=0; j<cnt; j++)
317 {
318 if (pos[j]==ipos)
319 {
320 if (mag[j] < 0xf0)
321 mag[j] += 0x10;
322 break;
323 }
324 }
325 if (cnt && j<cnt)
326 continue;
327
328 pos[cnt] = ipos;
329 mag[cnt] = 0x10;
330
331 cnt++;
332 if (cnt==0x4000)
333 return;
334 }
335
336 if (cnt>1000)
337 cout << "FIXME: Cnt>1000." << endl;
338
339 //
340 // Add found positions to array
341 //
342 const int first=leds.GetEntriesFast();
343
344 for (int i=0; i<cnt; i++)
345 {
346 if (mag[i]<=0x80) // 0xa0
347 continue;
348
349 Float_t mx, my;
350 GetMeanPosition(pos[i]%fW, pos[i]/fW, 5, mx, my);
351
352 leds.Add(mx, my, 0, 0, mag[i]);
353 }
354
355 RemoveTwinsInterpol(leds, first, 5);
356}
357
358void FilterLed::Stretch() const
359{
360 byte min, max;
361 GetMinMax(25, &min, &max);
362
363 if (min==max || max-min>230) // 255/230=1.1
364 return;
365
366 const float scale = 255./(max-min);
367
368 byte *b = fImg;
369 const byte *e = fImg+fW*fH;
370
371 while (b<e)
372 {
373 if (*b<min)
374 {
375 *b++=0;
376 continue;
377 }
378 if (*b>max)
379 {
380 *b++=255;
381 continue;
382 }
383 *b = (byte)((*b-min)*scale);
384 b++;
385 }
386}
387
Note: See TracBrowser for help on using the repository browser.