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

Last change on this file since 6964 was 4865, checked in by rwagner, 20 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
10#include "MGMap.h"
11
12ClassImp(FilterLed);
13
14void FilterLed::DrawBox(const int x1, const int y1,
15 const int x2, const int y2,
16 const int col) const
17{
18 MGMap::DrawBox(fImg, 768, 576, x1, y1, x2, y2, col);
19}
20
21void FilterLed::MarkPoint(Float_t px, Float_t py, Float_t mag) const
22{
23 const int x = (int)(px+.5);
24 const int y = (int)(py+.5);
25 const int m = (int)(mag);
26
27 DrawBox(x-8, y, x-5, y, m);
28 DrawBox(x, y+5, x, y+8, m);
29 DrawBox(x+5, y, x+8, y, m);
30 DrawBox(x, y-8, x, y-5, m);
31}
32
33void FilterLed::MarkPoint(const Led &led) const
34{
35 const int x = (int)(led.GetX()+.5);
36 const int y = (int)(led.GetY()+.5);
37 const int m = (int)(led.GetMag());
38
39 MarkPoint(x, y, m);
40}
41
42void FilterLed::DrawCircle(float cx, float cy, float r, byte col) const
43{
44 MGMap::DrawCircle(fImg, 768, 576, cx, cy, r, col);
45}
46
47void FilterLed::DrawCircle(const Ring &l, byte col) const
48{
49 DrawCircle(l.GetX(), l.GetY(), l.GetR(), col);
50}
51
52void FilterLed::DrawCircle(const Ring &l, double r, byte col) const
53{
54 DrawCircle(l.GetX(), l.GetY(), r, col);
55}
56
57void FilterLed::GetMinMax(const int offset, byte *min, byte *max) const
58{
59 *min = fImg[0];
60 *max = fImg[0];
61
62 byte *s = (byte*)fImg;
63 const byte *e0 = s+fW*fH;
64
65 //
66 // calculate mean value (speed optimized)
67 //
68 while (s<e0)
69 {
70 const byte *e = s+fH-offset;
71 s += offset;
72
73 while (s<e)
74 {
75 if (*s>*max)
76 {
77 *max = *s;
78 if (*max-*min==255)
79 return;
80 }
81 if (*s<*min)
82 {
83 *min = *s;
84 if (*max-*min==255)
85 return;
86 }
87 s++;
88 }
89 s+=offset;
90 }
91}
92
93int FilterLed::GetMeanPosition(const int x, const int y,
94 const int box, float &mx, float &my, unsigned int &sum) const
95{
96 unsigned int sumx=0;
97 unsigned int sumy=0;
98
99 sum=0;
100 for (int dx=x-box; dx<x+box+1; dx++)
101 for (int dy=y-box; dy<y+box+1; dy++)
102 {
103 const byte &m = fImg[dy*fW+dx];
104
105 sumx += m*dx;
106 sumy += m*dy;
107 sum += m;
108 }
109
110 mx = (float)sumx/sum;
111 my = (float)sumy/sum;
112
113 return (int)my*fW + (int)mx;
114}
115
116int FilterLed::GetMeanPosition(const int x, const int y, const int box) const
117{
118 float mx, my;
119 unsigned int sum;
120 return GetMeanPosition(x, y, box, mx, my, sum);
121}
122/*
123void FilterLed::RemoveTwins(Leds &leds, Double_t radius)
124{
125 for (int i=first; i<leds.GetEntriesFast(); i++)
126 {
127 const Led &led1 = leds(i);
128
129 const Double_t x1 = led1.GetX();
130 const Double_t y1 = led1.GetY();
131
132 for (int j=first; j<leds.GetEntriesFast(); j++)
133 {
134 if (j==i)
135 continuel
136
137 const Led &led2 = leds(j);
138
139 const Double_t x2 = led2.GetX();
140 const Double_t y2 = led2.GetY();
141
142 const Double_t dx = x2-x1;
143 const Double_t dy = y2-y1;
144
145 if (dx*dx+dy*dy<radius*radius)
146 {
147 // FIXME: Interpolation
148 leds.Remove(led2);
149 }
150 }
151 }
152}
153*/
154void FilterLed::RemoveTwinsInterpol(Leds &leds, Int_t first, Double_t radius) const
155{
156 const Int_t num=leds.GetEntriesFast();
157
158 for (int i=first; i<num; i++)
159 {
160 Led *led1 = (Led*)leds.UncheckedAt(i);
161 if (!led1)
162 continue;
163
164 const Double_t x1 = led1->GetX();
165 const Double_t y1 = led1->GetY();
166
167 Double_t mag = led1->GetMag();
168 Double_t x = x1*mag;
169 Double_t y = y1*mag;
170
171 Double_t sqm = mag*mag;
172 Double_t sqx = x*x;
173 Double_t sqy = y*y;
174
175 Int_t n=1;
176
177 for (int j=first; j<num; j++)
178 {
179 if (i==j)
180 continue;
181
182 Led *led2 = (Led*)leds.UncheckedAt(j);
183 if (!led2)
184 continue;
185
186 Double_t x2 = led2->GetX();
187 Double_t y2 = led2->GetY();
188
189 const Double_t dx = x2-x1;
190 const Double_t dy = y2-y1;
191
192 if (dx*dx+dy*dy>radius*radius)
193 continue;
194
195 // Multiply with weihgt
196 const Double_t w = led2->GetMag();
197 x2 *= w;
198 y2 *= w;
199
200 x += x2;
201 y += y2;
202 mag += w;
203
204 sqx += x2*x2;
205 sqy += y2*y2;
206 sqm += w*w;
207
208 n++;
209 leds.Remove(led2);
210 }
211
212 x /= mag;
213 y /= mag;
214
215 sqx /= sqm;
216 sqy /= sqm;
217
218 leds.Add(x, y, 0/*sqrt(sqx-x*x)*/, 0/*sqrt(sqy-y*y)*/, mag/n);
219 leds.Remove(led1);
220 }
221 leds.Compress();
222}
223
224void FilterLed::ExecuteAndMark(Leds &leds, int xc, int yc) const
225{
226 const Int_t first = leds.GetEntriesFast();
227
228 Execute(leds, xc, yc);
229
230 // Mark Stars in image
231 for (int i=first; i<leds.GetEntriesFast(); i++)
232 MarkPoint(leds(i));
233}
234
235
236void FilterLed::ExecuteAndMark(Leds &leds, int xc, int yc, double &bright) const
237{
238 const Int_t first = leds.GetEntriesFast();
239
240 Execute(leds, xc, yc, bright);
241
242 // Mark Stars in image
243 for (int i=first; i<leds.GetEntriesFast(); i++)
244 MarkPoint(leds(i));
245}
246
247void FilterLed::Execute(int xc, int yc) const
248{
249 Leds leds;
250 ExecuteAndMark(leds, xc, yc);
251}
252
253void FilterLed::Execute(Leds &leds, int xc, int yc) const
254{
255 double bright;
256 Execute(leds, xc, yc, bright);
257}
258
259
260void FilterLed::Execute(Leds &leds, int xc, int yc, double &bright) const
261{
262 int x0 = xc-fBox;
263 int x1 = xc+fBox;
264 int y0 = yc-fBox;
265 int y1 = yc+fBox;
266
267 if (x0<0) x0=0;
268 if (y0<0) y0=0;
269 if (x1>fW) x1=fW;
270 if (y1>fH) y1=fH;
271
272 const int wx = x1-x0;
273 const int hy = y1-y0;
274
275 double sum = 0;
276 double sq = 0;
277
278 for (int x=x0; x<x1; x++)
279 for (int y=y0; y<y1; y++)
280 {
281 byte &b = fImg[y*fW+x];
282
283 sum += b;
284 sq += b*b;
285 }
286
287 sum /= wx*hy;
288 sq /= wx*hy;
289
290 bright=sum;
291
292
293 // 254 because b<=max and not b<max
294 const double sdev = sqrt(sq-sum*sum);
295 const byte max = sum+fCut*sdev>254 ? 254 : (byte)(sum+fCut*sdev);
296
297 //
298 // clean image from noise
299 // (FIXME: A lookup table could accelerate things...
300 //
301 for (int x=x0; x<x1; x++)
302 for (int y=y0; y<y1; y++)
303 {
304 byte &b = fImg[y*fW+x];
305 if (b<=max)
306 b = 0;
307 }
308
309 //
310 // find mean points
311 //
312 const int maxpnt = wx*hy>0x4000?0x4000:wx*hy;
313
314 int pos[maxpnt]; // (Use 'new' instead for big numbers!)
315 byte mag[maxpnt]; // (Use 'new' instead for big numbers!)
316
317 int cnt = 0;
318 for (int x=x0; x<x1; x++)
319 for (int y=y0; y<y1; y++)
320 {
321 byte &b = fImg[y*fW+x];
322 if (b==0)
323 continue;
324
325 const int ipos = GetMeanPosition(x, y, 5);
326
327 int j;
328 for (j=0; j<cnt; j++)
329 {
330 if (pos[j]==ipos)
331 {
332 if (mag[j] < 0xf0)
333 mag[j] += 0x10;
334 break;
335 }
336 }
337 if (cnt && j<cnt)
338 continue;
339
340 pos[cnt] = ipos;
341 mag[cnt] = 0x10;
342
343 cnt++;
344 if (cnt==0x4000)
345 return;
346 }
347
348 if (cnt>1000)
349 cout << "FIXME: Cnt>1000." << endl;
350
351 //
352 // Add found positions to array
353 //
354 const int first=leds.GetEntriesFast();
355
356 for (int i=0; i<cnt; i++)
357 {
358 if (mag[i]<=0x80) // 0xa0
359 continue;
360
361 Float_t mx, my;
362 unsigned int sum;
363 GetMeanPosition(pos[i]%fW, pos[i]/fW, 5, mx, my, sum);
364
365 leds.Add(mx, my, 0, 0, mag[i]);
366 }
367
368 RemoveTwinsInterpol(leds, first, 5);
369
370
371}
372
373void FilterLed::FindStar(Leds &leds, int xc, int yc) const
374{
375 // fBox: radius of the inner (signal) box
376 // Radius of the outer box is fBox*sqrt(2)
377
378 //
379 // Define inner box in which to search the signal
380 //
381 int x0 = xc-fBox;
382 int x1 = xc+fBox;
383 int y0 = yc-fBox;
384 int y1 = yc+fBox;
385
386 if (x0<0) x0=0;
387 if (y0<0) y0=0;
388 if (x1>fW) x1=fW;
389 if (y1>fH) y1=fH;
390
391 //
392 // Define outer box (excluding inner box) having almost
393 // the same number of pixels in which the background
394 // is calculated
395 //
396 const double sqrt2 = sqrt(2.);
397
398 int xa = xc-(int)rint(fBox*sqrt2);
399 int xb = xc+(int)rint(fBox*sqrt2);
400 int ya = yc-(int)rint(fBox*sqrt2);
401 int yb = yc+(int)rint(fBox*sqrt2);
402
403 if (xa<0) xa=0;
404 if (ya<0) ya=0;
405 if (xb>fW) xb=fW;
406 if (yb>fH) yb=fH;
407
408 //
409 // Calculate average and sdev for a square
410 // excluding the inner part were we expect
411 // the signal to be.
412 //
413 double sum = 0;
414 double sq = 0;
415
416 int n=0;
417 for (int x=xa; x<xb; x++)
418 for (int y=ya; y<yb; y++)
419 {
420 if (x>=x0 && x<x1 && y>=y0 && y<y1)
421 continue;
422
423 byte &b = fImg[y*fW+x];
424
425 sum += b;
426 sq += b*b;
427 n++;
428 }
429
430 sum /= n;
431 sq /= n;
432
433 // 254 because b<=max and not b<max
434 const double sdev = sqrt(sq-sum*sum);
435 const byte max = sum+fCut*sdev>254 ? 254 : (byte)(sum+fCut*sdev);
436
437 //
438 // clean image from noise
439 // (FIXME: A lookup table could accelerate things...
440 //
441 n=0;
442 for (int x=x0; x<x1; x++)
443 for (int y=y0; y<y1; y++)
444 {
445 byte &b = fImg[y*fW+x];
446 if (b<=max)
447 b = 0;
448 else
449 n++;
450 }
451
452 //
453 // Mark the background region
454 //
455 for (int x=xa; x<xb; x+=2)
456 {
457 fImg[ya*fW+x]=0xf0;
458 fImg[yb*fW+x]=0xf0;
459 }
460 for (int y=ya; y<yb; y+=2)
461 {
462 fImg[y*fW+xa]=0xf0;
463 fImg[y*fW+xb]=0xf0;
464 }
465
466 //
467 // Check if any pixel found...
468 //
469 if (n<5)
470 return;
471
472 //
473 // Get the mean position of the star
474 //
475 float mx, my;
476 unsigned int mag;
477 int pos = GetMeanPosition(xc, yc, fBox-1, mx, my, mag);
478
479 if (pos<0 || pos>=fW*fH && fImg[pos]<sum+fCut*sdev)
480 return;
481
482 cout << "Mean=" << sum << " SDev=" << sdev << " : ";
483 cout << "Sum/n = " << sum << "/" << n << " = " << (n==0?0:mag/n) << endl;
484
485 leds.Add(mx, my, 0, 0, -2.5*log10((float)mag)+13.7);
486}
487
488void FilterLed::Stretch() const
489{
490 byte min, max;
491 GetMinMax(25, &min, &max);
492
493 if (min==max || max-min>230) // 255/230=1.1
494 return;
495
496 const float scale = 255./(max-min);
497
498 byte *b = fImg;
499 const byte *e = fImg+fW*fH;
500
501 while (b<e)
502 {
503 if (*b<min)
504 {
505 *b++=0;
506 continue;
507 }
508 if (*b>max)
509 {
510 *b++=255;
511 continue;
512 }
513 *b = (byte)((*b-min)*scale);
514 b++;
515 }
516}
517
Note: See TracBrowser for help on using the repository browser.