#include "FilterLed.h" #include // memset #include #include // cout #include "Led.h" #include "Ring.h" #include "MGImage.h" using namespace std; class ClusterFinder { private: uint8_t *fImg; uint32_t fW; uint32_t fH; int32_t fX0; int32_t fX1; int32_t fY0; int32_t fY1; uint32_t fLimitingSize; uint32_t fCount; float fSumX; float fSumY; float FindCluster(int32_t x, int32_t y) { // if edge is touched stop finding cluster if (x=fX1 || y=fY1) return -1; if (fCount>fLimitingSize) return -2; // get the value float val = fImg[y*fW+x]; // if its empty we have found the border of the cluster if (val==0) return 0; // mark the point as processed fImg[y*fW+x] = 0; fSumX += x*val; // sumx fSumY += y*val; // sumy fCount++; float rc[4]; rc[0] = FindCluster(x+1, y ); rc[1] = FindCluster(x, y+1); rc[2] = FindCluster(x-1, y ); rc[3] = FindCluster(x, y-1); for (int i=0; i<4; i++) { if (rc[i]<0) // check if edge is touched return rc[i]; val += rc[i]; } return val; } public: ClusterFinder(uint8_t *img, uint32_t w, uint32_t h) : fImg(0), fLimitingSize(999) { fW = w; fH = h; fX0 = 0; fY0 = 0; fX1 = fW; fY1 = fH; fImg = new uint8_t[fW*fH]; memcpy(fImg, img, fW*fH); } ~ClusterFinder() { delete [] fImg; } Double_t GetSumX() const { return fSumX; } Double_t GetSumY() const { return fSumY; } uint32_t GetCount() const { return fCount; } void SetLimitingSize(uint32_t lim) { fLimitingSize=lim; } float FindClusterAt(int32_t x, int32_t y) { fCount = 0; fSumX = 0; fSumY = 0; return FindCluster(x, y); } void SetRange(int32_t x0=0, int32_t y0=0, int32_t x1=0, int32_t y1=0) { fX0 = x0; fY0 = y0; fX1 = x1==0?fW:x1; fY1 = y1==0?fH:y1; } void FindCluster(vector &leds, int32_t x0=0, int32_t y0=0, int32_t x1=0, int32_t y1=0) { fX0 = x0; fY0 = y0; fX1 = x1==0?fW:x1; fY1 = y1==0?fH:y1; for (int32_t x=fX0; x999) { cout << "ERROR - Spot with Size>999 detected..." << endl; return; } if (mag>0 && fCount>4) leds.push_back(Led(fSumX/mag, fSumY/mag, 0, mag)); } //leds.Compress(); } }; void FilterLed::DrawBox(const int x1, const int y1, const int x2, const int y2, const int col) const { MGImage::DrawBox(fImg, 768, 576, x1, y1, x2, y2, col); } void FilterLed::MarkPoint(float px, float py, float mag) const { const int x = (int)(px+.5); const int y = (int)(py+.5); const int m = (int)(mag); DrawBox(x-8, y, x-5, y, m); DrawBox(x, y+5, x, y+8, m); DrawBox(x+5, y, x+8, y, m); DrawBox(x, y-8, x, y-5, m); } void FilterLed::MarkPoint(const Led &led) const { /* int32_t M = (int)(log(led.GetMag())*20); cout << led.GetMag() << endl; if (M>0xff) M=0xff; if (M<0xc0) M=0xc0; */ const int x = (int)(led.GetX()+.5); const int y = (int)(led.GetY()+.5); MarkPoint(x, y, 0xff); } void FilterLed::DrawCircle(float cx, float cy, float r, uint8_t col) const { MGImage::DrawCircle(fImg, 768, 576, cx, cy, r, col); } void FilterLed::DrawHexagon(float cx, float cy, float r, uint8_t col) const { MGImage::DrawHexagon(fImg, 768, 576, cx, cy, r, col); } void FilterLed::DrawCircle(const Ring &l, uint8_t col) const { DrawCircle(l.GetX(), l.GetY(), l.GetR(), col); } void FilterLed::DrawCircle(const Ring &l, double r, uint8_t col) const { DrawCircle(l.GetX(), l.GetY(), r, col); } void FilterLed::DrawHexagon(const Ring &l, double r, uint8_t col) const { DrawHexagon(l.GetX(), l.GetY(), r, col); } void FilterLed::GetMinMax(const int offset, uint8_t *min, uint8_t *max) const { *min = fImg[0]; *max = fImg[0]; uint8_t *s = (uint8_t*)fImg; const uint8_t *e0 = s+fW*fH; // // calculate mean value (speed optimized) // while (s*max) { *max = *s; if (*max-*min==255) return; } if (*s<*min) { *min = *s; if (*max-*min==255) return; } s++; } s+=offset; } } int FilterLed::GetMeanPosition(const int x, const int y, const int boxx, const int boxy, float &mx, float &my, unsigned int &sum) const { unsigned int sumx=0; unsigned int sumy=0; sum=0; for (int dx=x-boxx; dx &leds, int xc, int yc) const { double bright; Execute(leds, xc, yc, bright); } void FilterLed::Execute(vector &leds, int xc, int yc, double &bright) const { const int x0 = max(xc-fBoxX, 0); const int y0 = max(yc-fBoxY, 0); const int x1 = min(xc+fBoxX, fW); const int y1 = min(yc+fBoxY, fH); const int wx = x1-x0; const int hy = y1-y0; double sum = 0; double sq = 0; for (int x=x0; x0xf0) continue; sum += b; sq += b*b; } sum /= wx*hy; sq /= wx*hy; bright=sum; // 254 because b<=max and not b254 ? 254 : (uint8_t)(sum+fCut*sdev); // // clean image from noise // (FIXME: A lookup table could accelerate things... // for (int x=x0; x &leds, int xc, int yc, bool box) const { // fBox: radius of the inner (signal) box // Radius of the outer box is fBox*sqrt(2) // // Define inner box in which to search the signal // const int x0 = max(xc-fBoxX, 0); const int y0 = max(yc-fBoxY, 0); const int x1 = min(xc+fBoxX, fW); const int y1 = min(yc+fBoxY, fH); // // Define outer box (excluding inner box) having almost // the same number of pixels in which the background // is calculated // const double sqrt2 = sqrt(2.); const int xa = max(xc-(int)nearbyint(fBoxX*sqrt2), 0); const int ya = max(yc-(int)nearbyint(fBoxY*sqrt2), 0); const int xb = min(xc+(int)nearbyint(fBoxX*sqrt2), fW); const int yb = min(yc+(int)nearbyint(fBoxY*sqrt2), fH); // // Calculate average and sdev for a square // excluding the inner part were we expect // the signal to be. // double sum = 0; double sq = 0; int n=0; for (int x=xa; x=x0 && x=y0 && y254 ? 254 : (uint8_t)(sum+fCut*sdev); // // clean image from noise // (FIXME: A lookup table could accelerate things... // n=0; for (int x=x0; x=fW*fH || fImg[pos]