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

Last change on this file since 4099 was 4076, checked in by tbretz, 21 years ago
*** empty log message ***
File size: 10.8 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+=2)
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}
67
68void FilterLed::GetMinMax(const int offset, byte *min, byte *max) const
69{
70 *min = fImg[0];
71 *max = fImg[0];
72
73 byte *s = (byte*)fImg;
74 const byte *e0 = s+fW*fH;
75
76 //
77 // calculate mean value (speed optimized)
78 //
79 while (s<e0)
80 {
81 const byte *e = s+fH-offset;
82 s += offset;
83
84 while (s<e)
85 {
86 if (*s>*max)
87 {
88 *max = *s;
89 if (*max-*min==255)
90 return;
91 }
92 if (*s<*min)
93 {
94 *min = *s;
95 if (*max-*min==255)
96 return;
97 }
98 s++;
99 }
100 s+=offset;
101 }
102}
103
104int FilterLed::GetMeanPosition(const int x, const int y,
105 const int box, float &mx, float &my, unsigned int &sum) const
106{
107 unsigned int sumx=0;
108 unsigned int sumy=0;
109
110 sum=0;
111 for (int dx=x-box; dx<x+box+1; dx++)
112 for (int dy=y-box; dy<y+box+1; dy++)
113 {
114 const byte &m = fImg[dy*fW+dx];
115
116 sumx += m*dx;
117 sumy += m*dy;
118 sum += m;
119 }
120
121 mx = (float)sumx/sum;
122 my = (float)sumy/sum;
123
124 return (int)my*fW + (int)mx;
125}
126
127int FilterLed::GetMeanPosition(const int x, const int y, const int box) const
128{
129 float mx, my;
130 unsigned int sum;
131 return GetMeanPosition(x, y, box, mx, my, sum);
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-fBox;
255 int x1 = xc+fBox;
256 int y0 = yc-fBox;
257 int y1 = yc+fBox;
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 // 254 because b<=max and not b<max
283 const double sdev = sqrt(sq-sum*sum);
284 const byte max = sum+fCut*sdev>254 ? 254 : (byte)(sum+fCut*sdev);
285
286 //
287 // clean image from noise
288 // (FIXME: A lookup table could accelerate things...
289 //
290 for (int x=x0; x<x1; x++)
291 for (int y=y0; y<y1; y++)
292 {
293 byte &b = fImg[y*fW+x];
294 if (b<=max)
295 b = 0;
296 }
297
298 //
299 // find mean points
300 //
301 const int maxpnt = wx*hy>0x4000?0x4000:wx*hy;
302
303 int pos[maxpnt]; // (Use 'new' instead for big numbers!)
304 byte mag[maxpnt]; // (Use 'new' instead for big numbers!)
305
306 int cnt = 0;
307 for (int x=x0; x<x1; x++)
308 for (int y=y0; y<y1; y++)
309 {
310 byte &b = fImg[y*fW+x];
311 if (b==0)
312 continue;
313
314 const int ipos = GetMeanPosition(x, y, 5);
315
316 int j;
317 for (j=0; j<cnt; j++)
318 {
319 if (pos[j]==ipos)
320 {
321 if (mag[j] < 0xf0)
322 mag[j] += 0x10;
323 break;
324 }
325 }
326 if (cnt && j<cnt)
327 continue;
328
329 pos[cnt] = ipos;
330 mag[cnt] = 0x10;
331
332 cnt++;
333 if (cnt==0x4000)
334 return;
335 }
336
337 if (cnt>1000)
338 cout << "FIXME: Cnt>1000." << endl;
339
340 //
341 // Add found positions to array
342 //
343 const int first=leds.GetEntriesFast();
344
345 for (int i=0; i<cnt; i++)
346 {
347 if (mag[i]<=0x80) // 0xa0
348 continue;
349
350 Float_t mx, my;
351 unsigned int sum;
352 GetMeanPosition(pos[i]%fW, pos[i]/fW, 5, mx, my, sum);
353
354 leds.Add(mx, my, 0, 0, mag[i]);
355 }
356
357 RemoveTwinsInterpol(leds, first, 5);
358}
359
360void FilterLed::FindStar(Leds &leds, int xc, int yc) const
361{
362 // fBox: radius of the inner (signal) box
363 // Radius of the outer box is fBox*sqrt(2)
364
365 //
366 // Define inner box in which to search the signal
367 //
368 int x0 = xc-fBox;
369 int x1 = xc+fBox;
370 int y0 = yc-fBox;
371 int y1 = yc+fBox;
372
373 if (x0<0) x0=0;
374 if (y0<0) y0=0;
375 if (x1>fW) x1=fW;
376 if (y1>fH) y1=fH;
377
378 //
379 // Define outer box (excluding inner box) having almost
380 // the same nuymber of pixels in which the background
381 // is calculated
382 //
383 const double sqrt2 = sqrt(2.);
384
385 int xa = xc-(int)rint(fBox*sqrt2);
386 int xb = xc+(int)rint(fBox*sqrt2);
387 int ya = yc-(int)rint(fBox*sqrt2);
388 int yb = yc+(int)rint(fBox*sqrt2);
389
390 if (xa<0) xa=0;
391 if (ya<0) ya=0;
392 if (xb>fW) xb=fW;
393 if (yb>fH) yb=fH;
394
395 //
396 // Calculate average and sdev for a square
397 // excluding the inner part were we expect
398 // the signal to be.
399 //
400 double sum = 0;
401 double sq = 0;
402
403 int n=0;
404 for (int x=xa; x<xb+1; x++)
405 for (int y=ya; y<yb+1; y++)
406 {
407 if (x>x0 && x<x1 && y>y0 && y<y1)
408 continue;
409
410 byte &b = fImg[y*fW+x];
411
412 sum += b;
413 sq += b*b;
414 n++;
415 }
416
417 sum /= n;
418 sq /= n;
419
420 // 254 because b<=max and not b<max
421 const double sdev = sqrt(sq-sum*sum);
422 const byte max = sum+fCut*sdev>254 ? 254 : (byte)(sum+fCut*sdev);
423
424 //
425 // clean image from noise
426 // (FIXME: A lookup table could accelerate things...
427 //
428 n=0;
429 for (int x=x0; x<x1; x++)
430 for (int y=y0; y<y1; y++)
431 {
432 byte &b = fImg[y*fW+x];
433 if (b<=max)
434 b = 0;
435 else
436 n++;
437 }
438
439 //
440 // Mark the background region
441 //
442 for (int x=xa; x<xb+1; x+=2)
443 {
444 fImg[ya*fW+x]=0xf0;
445 fImg[yb*fW+x]=0xf0;
446 }
447 for (int y=ya; y<yb+1; y+=2)
448 {
449 fImg[y*fW+xa]=0xf0;
450 fImg[y*fW+xb]=0xf0;
451 }
452
453 //
454 // Check if any pixel found...
455 //
456 if (n<5)
457 return;
458
459 //
460 // Get the mean position of the star
461 //
462 float mx, my;
463 unsigned int mag;
464 int pos = GetMeanPosition(xc, yc, fBox-1, mx, my, mag);
465
466 if (pos<0 || pos>=fW*fH && fImg[pos]<sum+fCut*sdev)
467 return;
468
469 cout << "Mean=" << sum << " SDev=" << sdev << " : ";
470 cout << "Sum/n = " << sum << "/" << n << " = " << (n==0?0:mag/n) << endl;
471
472 leds.Add(mx, my, 0, 0, -2.5*log10((float)mag)+13.7);
473}
474
475void FilterLed::Stretch() const
476{
477 byte min, max;
478 GetMinMax(25, &min, &max);
479
480 if (min==max || max-min>230) // 255/230=1.1
481 return;
482
483 const float scale = 255./(max-min);
484
485 byte *b = fImg;
486 const byte *e = fImg+fW*fH;
487
488 while (b<e)
489 {
490 if (*b<min)
491 {
492 *b++=0;
493 continue;
494 }
495 if (*b>max)
496 {
497 *b++=255;
498 continue;
499 }
500 *b = (byte)((*b-min)*scale);
501 b++;
502 }
503}
504
Note: See TracBrowser for help on using the repository browser.