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

Last change on this file since 4450 was 4105, checked in by tbretz, 21 years ago
*** empty log message ***
File size: 10.3 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
235void FilterLed::Execute(int xc, int yc) const
236{
237 Leds leds;
238 ExecuteAndMark(leds, xc, yc);
239}
240
241void FilterLed::Execute(Leds &leds, int xc, int yc) const
242{
243 int x0 = xc-fBox;
244 int x1 = xc+fBox;
245 int y0 = yc-fBox;
246 int y1 = yc+fBox;
247
248 if (x0<0) x0=0;
249 if (y0<0) y0=0;
250 if (x1>fW) x1=fW;
251 if (y1>fH) y1=fH;
252
253 const int wx = x1-x0;
254 const int hy = y1-y0;
255
256 double sum = 0;
257 double sq = 0;
258
259 for (int x=x0; x<x1; x++)
260 for (int y=y0; y<y1; y++)
261 {
262 byte &b = fImg[y*fW+x];
263
264 sum += b;
265 sq += b*b;
266 }
267
268 sum /= wx*hy;
269 sq /= wx*hy;
270
271 // 254 because b<=max and not b<max
272 const double sdev = sqrt(sq-sum*sum);
273 const byte max = sum+fCut*sdev>254 ? 254 : (byte)(sum+fCut*sdev);
274
275 //
276 // clean image from noise
277 // (FIXME: A lookup table could accelerate things...
278 //
279 for (int x=x0; x<x1; x++)
280 for (int y=y0; y<y1; y++)
281 {
282 byte &b = fImg[y*fW+x];
283 if (b<=max)
284 b = 0;
285 }
286
287 //
288 // find mean points
289 //
290 const int maxpnt = wx*hy>0x4000?0x4000:wx*hy;
291
292 int pos[maxpnt]; // (Use 'new' instead for big numbers!)
293 byte mag[maxpnt]; // (Use 'new' instead for big numbers!)
294
295 int cnt = 0;
296 for (int x=x0; x<x1; x++)
297 for (int y=y0; y<y1; y++)
298 {
299 byte &b = fImg[y*fW+x];
300 if (b==0)
301 continue;
302
303 const int ipos = GetMeanPosition(x, y, 5);
304
305 int j;
306 for (j=0; j<cnt; j++)
307 {
308 if (pos[j]==ipos)
309 {
310 if (mag[j] < 0xf0)
311 mag[j] += 0x10;
312 break;
313 }
314 }
315 if (cnt && j<cnt)
316 continue;
317
318 pos[cnt] = ipos;
319 mag[cnt] = 0x10;
320
321 cnt++;
322 if (cnt==0x4000)
323 return;
324 }
325
326 if (cnt>1000)
327 cout << "FIXME: Cnt>1000." << endl;
328
329 //
330 // Add found positions to array
331 //
332 const int first=leds.GetEntriesFast();
333
334 for (int i=0; i<cnt; i++)
335 {
336 if (mag[i]<=0x80) // 0xa0
337 continue;
338
339 Float_t mx, my;
340 unsigned int sum;
341 GetMeanPosition(pos[i]%fW, pos[i]/fW, 5, mx, my, sum);
342
343 leds.Add(mx, my, 0, 0, mag[i]);
344 }
345
346 RemoveTwinsInterpol(leds, first, 5);
347}
348
349void FilterLed::FindStar(Leds &leds, int xc, int yc) const
350{
351 // fBox: radius of the inner (signal) box
352 // Radius of the outer box is fBox*sqrt(2)
353
354 //
355 // Define inner box in which to search the signal
356 //
357 int x0 = xc-fBox;
358 int x1 = xc+fBox;
359 int y0 = yc-fBox;
360 int y1 = yc+fBox;
361
362 if (x0<0) x0=0;
363 if (y0<0) y0=0;
364 if (x1>fW) x1=fW;
365 if (y1>fH) y1=fH;
366
367 //
368 // Define outer box (excluding inner box) having almost
369 // the same nuymber of pixels in which the background
370 // is calculated
371 //
372 const double sqrt2 = sqrt(2.);
373
374 int xa = xc-(int)rint(fBox*sqrt2);
375 int xb = xc+(int)rint(fBox*sqrt2);
376 int ya = yc-(int)rint(fBox*sqrt2);
377 int yb = yc+(int)rint(fBox*sqrt2);
378
379 if (xa<0) xa=0;
380 if (ya<0) ya=0;
381 if (xb>fW) xb=fW;
382 if (yb>fH) yb=fH;
383
384 //
385 // Calculate average and sdev for a square
386 // excluding the inner part were we expect
387 // the signal to be.
388 //
389 double sum = 0;
390 double sq = 0;
391
392 int n=0;
393 for (int x=xa; x<xb+1; x++)
394 for (int y=ya; y<yb+1; y++)
395 {
396 if (x>x0 && x<x1 && y>y0 && y<y1)
397 continue;
398
399 byte &b = fImg[y*fW+x];
400
401 sum += b;
402 sq += b*b;
403 n++;
404 }
405
406 sum /= n;
407 sq /= n;
408
409 // 254 because b<=max and not b<max
410 const double sdev = sqrt(sq-sum*sum);
411 const byte max = sum+fCut*sdev>254 ? 254 : (byte)(sum+fCut*sdev);
412
413 //
414 // clean image from noise
415 // (FIXME: A lookup table could accelerate things...
416 //
417 n=0;
418 for (int x=x0; x<x1; x++)
419 for (int y=y0; y<y1; y++)
420 {
421 byte &b = fImg[y*fW+x];
422 if (b<=max)
423 b = 0;
424 else
425 n++;
426 }
427
428 //
429 // Mark the background region
430 //
431 for (int x=xa; x<xb+1; x+=2)
432 {
433 fImg[ya*fW+x]=0xf0;
434 fImg[yb*fW+x]=0xf0;
435 }
436 for (int y=ya; y<yb+1; y+=2)
437 {
438 fImg[y*fW+xa]=0xf0;
439 fImg[y*fW+xb]=0xf0;
440 }
441
442 //
443 // Check if any pixel found...
444 //
445 if (n<5)
446 return;
447
448 //
449 // Get the mean position of the star
450 //
451 float mx, my;
452 unsigned int mag;
453 int pos = GetMeanPosition(xc, yc, fBox-1, mx, my, mag);
454
455 if (pos<0 || pos>=fW*fH && fImg[pos]<sum+fCut*sdev)
456 return;
457
458 cout << "Mean=" << sum << " SDev=" << sdev << " : ";
459 cout << "Sum/n = " << sum << "/" << n << " = " << (n==0?0:mag/n) << endl;
460
461 leds.Add(mx, my, 0, 0, -2.5*log10((float)mag)+13.7);
462}
463
464void FilterLed::Stretch() const
465{
466 byte min, max;
467 GetMinMax(25, &min, &max);
468
469 if (min==max || max-min>230) // 255/230=1.1
470 return;
471
472 const float scale = 255./(max-min);
473
474 byte *b = fImg;
475 const byte *e = fImg+fW*fH;
476
477 while (b<e)
478 {
479 if (*b<min)
480 {
481 *b++=0;
482 continue;
483 }
484 if (*b>max)
485 {
486 *b++=255;
487 continue;
488 }
489 *b = (byte)((*b-min)*scale);
490 b++;
491 }
492}
493
Note: See TracBrowser for help on using the repository browser.