runMACS
 All Data Structures Files Functions Variables Enumerations Enumerator Macros
StatsExtractor.cpp
Go to the documentation of this file.
1 #include <StatsExtractor.h>
2 #include <utils.h>
3 #include <stringtricks.h>
4 
5 #include <config.h>
6 
7 #include <climits> // UINT_MAX
8 #include <json/json.h>
9 
10 #include <caltables.inc>
11 
12 using namespace std;
13 
14 StatsExtractor::StatsExtractor(zmq::context_t & _ctx,
15  const PubSubEndpoint & _source,
16  const PubSubEndpoint & _destination,
17  const std::string & _identifier) :
18  Extractor(_ctx, _source),
19  s_identifier(_identifier),
20  destination(_destination),
21  hdrText(SSTR("ROCS\x01", _identifier, ".hist")),
22  hdrBluenessText(SSTR("ROCS\x01", _identifier, ".blueness")){
23  histBits = 8;
24  if (s_identifier.compare("vnir") == 0) {
25  sensorBits = 12;
26  blHigh.calData = caltables::vnirHighCal;
27  blHigh.roi = {0, 290, caltables::vnirHighCal_spatial_pixels, caltables::vnirHighCal_spectral_pixels};
28  blHigh.dark = 270.;
29  blHigh.acc = new double[caltables::vnirHighCal_spatial_pixels];
30  blLow.calData = caltables::vnirLowCal;
31  blLow.roi = {0, 95, caltables::vnirLowCal_spatial_pixels, caltables::vnirLowCal_spectral_pixels};
32  blLow.dark = 270.;
33  blLow.acc = new double[caltables::vnirHighCal_spatial_pixels];
34  haveCalAvg = true;
35  } else if (s_identifier.compare("swir") == 0) {
36  sensorBits = 14;
37  haveCalAvg = false;
38  } else {
39  sensorBits = 12;
40  haveCalAvg = false;
41  }
42  bitShift = sensorBits - histBits;
43  histCount = 1 << histBits;
44  bitMask = histCount - 1;
45 }
46 
48  if(haveCalAvg) {
49  delete[] blHigh.acc;
50  delete[] blLow.acc;
51  }
52 }
53 
54 std::string StatsExtractor::type() {
55  return "Stats";
56 }
57 
59  return s_identifier;
60 }
61 
62 std::list<std::string> StatsExtractor::parameters() {
63  return {keepGoing?"active":"done"};
64 }
65 
66 /****** PRIVATE *****/
67 
68 void StatsExtractor::extractSetup() {
69  // connect to XSUB
70  destinationSocket = new zmq::socket_t(ctx, ZMQ_PUB);
71  destinationSocket->connect(destination.endpoint.c_str());
72 
73  hist = new uint32_t[histCount]();
74 }
75 
76 void StatsExtractor::extractImpl(unsigned int _width,
77  unsigned int _height,
78  unsigned int _bytesPerPixel,
79  uint64_t highResTime,
80  uint64_t wallTime,
81  zmq::message_t * sourceImage) {
82  (void)highResTime;
83  (void)wallTime;
84  double blueness = 0.;
85 
86  min=UINT_MAX, max=0, avg=0;
87  memset(hist, 0, histCount*sizeof(uint32_t));
88 
89  uint16_t *data = (uint16_t *)sourceImage->data();
90  uint16_t *end = data + sourceImage->size()/sizeof(uint16_t);
91  for(; data != end; ++data) {
92  if((*data)<min) {
93  min = *data;
94  } else if((*data)>max) {
95  max = *data;
96  }
97  avg += *data;
98  ++(hist[((*data)>>bitShift)&bitMask]);
99  }
100  avg /= (unsigned int)(sourceImage->size()/sizeof(uint16_t));
101 
102  /* blueness calculation */
103  if(haveCalAvg) {
104  data = (uint16_t *)sourceImage->data();
105  switch(_bytesPerPixel) {
106  case 1:
107  blHigh.accumulate<uint8_t>((uint8_t *)sourceImage->data(), _width, _height);
108  blLow.accumulate<uint8_t>((uint8_t *)sourceImage->data(), _width, _height);
109  break;
110  case 2:
111  blHigh.accumulate<uint16_t>((uint16_t *)sourceImage->data(), _width, _height);
112  blLow.accumulate<uint16_t>((uint16_t *)sourceImage->data(), _width, _height);
113  break;
114  case 4:
115  blHigh.accumulate<uint32_t>((uint32_t *)sourceImage->data(), _width, _height);
116  blLow.accumulate<uint32_t>((uint32_t *)sourceImage->data(), _width, _height);
117  break;
118  }
119 
120  blueness = 0.;
121  for(unsigned int j = 0; j < blHigh.roi.width; ++j) {
122  blueness += blHigh.acc[j] * blHigh.acc[j] / blLow.acc[j];
123  }
124  blueness /= blHigh.roi.width;
125  }
126 
127  delete sourceImage;
128  // send out status
129  sendStatus();
130  sendHist();
131  if(haveCalAvg) {
132  sendBlueness(blueness);
133  }
134 }
135 
136 void StatsExtractor::extractTeardown() {
137  // close XSUB socket
138  delete destinationSocket;
139  delete[] hist;
140 }
141 
142 void StatsExtractor::sendStatus() {
143  zmq::message_t msgHdr(11+s_identifier.length());
144  char* statusHeaderText = (char*)malloc(12+s_identifier.length());
145  snprintf(statusHeaderText, 12+s_identifier.length(), "ROCS\x01%s.stats", s_identifier.c_str());
146  memcpy((char*)msgHdr.data(), statusHeaderText, 11+s_identifier.length());
147  destinationSocket->send(msgHdr, ZMQ_SNDMORE);
148  free(statusHeaderText);
149 
150  Json::FastWriter writer;
151  Json::Value root;
152  root["min"] = min;
153  root["max"] = max;
154  root["avg"] = avg;
155  std::string data = writer.write(root);
156  zmq::message_t msgData(data.length());
157  memcpy((char *)msgData.data(), data.c_str(), data.length());
158  destinationSocket->send(msgData);
159 }
160 
161 void StatsExtractor::sendHist() {
162  zmq::message_t msgHdr(hdrText.length());
163  memcpy((char*)msgHdr.data(), hdrText.c_str(), hdrText.length());
164  destinationSocket->send(msgHdr, ZMQ_SNDMORE);
165 
166  Json::FastWriter writer;
167  Json::Value root;
168  for(uint32_t i=0; i<histCount; i++) {
169  root.append(hist[i]);
170  }
171  std::string data = writer.write(root);
172  zmq::message_t msgData(data.length());
173  memcpy((char *)msgData.data(), data.c_str(), data.length());
174  destinationSocket->send(msgData);
175 }
176 
177 void StatsExtractor::sendBlueness(double blueness) {
178  zmq::message_t msgHdr(hdrBluenessText.length());
179  memcpy((char*)msgHdr.data(), hdrBluenessText.c_str(), hdrBluenessText.length());
180  destinationSocket->send(msgHdr, ZMQ_SNDMORE);
181 
182  Json::FastWriter writer;
183  Json::Value root;
184  if(blueness != blueness) {
185  root = Json::Value::null;
186  } else {
187  root = blueness;
188  }
189  std::string data = writer.write(root);
190  zmq::message_t msgData(data.length());
191  memcpy((char *)msgData.data(), data.c_str(), data.length());
192  destinationSocket->send(msgData);
193 }
194 
195 
196 template <typename T> void StatsExtractor::CalAvgData::accumulate(T* data, unsigned int w, unsigned int h) {
197  (void)h;
198  double temp;
199  for(unsigned int j = 0; j < roi.width; ++j) {
200  acc[j] = 0.;
201  }
202  for(unsigned int i = 0; i < roi.height; ++i) {
203  for(unsigned int j = 0; j < roi.width; ++j) {
204  temp = data[(i + roi.y) * w + j + roi.x] - dark;
205  if(temp < 0.) {
206  temp = 0;
207  }
208  acc[j] += temp * calData[i * roi.width + j];
209  }
210  }
211 }
StatsExtractor(zmq::context_t &_ctx, const PubSubEndpoint &_source, const PubSubEndpoint &_destination, const std::string &_identifier)
Base class for an image extractor.
Definition: Extractor.h:17
STL namespace.
std::string SSTR(Args &&...components)
Creates a temporary string stream for string concatenation.
Definition: stringtricks.h:21
zmq::context_t & ctx
Definition: Extractor.h:27
std::string endpoint
Definition: utils.h:15
std::list< std::string > parameters()
std::string type()
std::string identifier()
volatile bool keepGoing
Definition: Extractor.h:29