cloudFPGA (cF) API  1.0
The documentation of the source code of cloudFPGA (cF)
gammacorrection_host.cpp
Go to the documentation of this file.
1 
17 
33 #include <stdio.h>
34 #include <iostream> // For cout and cerr
35 #include <cstdlib> // For atoi()
36 #include <assert.h> // For assert()
37 #include <string> // For to_string
38 #include "../../../PracticalSockets/src/PracticalSockets.h" // For UDPSocket and SocketException
39 #include "../include/config.h"
40 #include "opencv2/opencv.hpp"
41 #include "../../../../ROLE/vision/hls/gammacorrection/include/xf_ocv_ref.hpp" // For SW reference Gammacorrection from OpenCV
42 
43 using namespace std;
44 using namespace cv;
45 
46 
47 void delay(unsigned int mseconds)
48 {
49  clock_t goal = mseconds + clock();
50  while (goal > clock());
51 }
52 
53 void print_cFpZoo(void)
54 {
55  cout << " " << endl;
56  cout << "...build with: " << endl;
57  cout << " ██████╗███████╗██████╗ ███████╗ ██████╗ ██████╗ " << endl;
58  cout << "██╔════╝██╔════╝██╔══██╗ ╚══███╔╝██╔═══██╗██╔═══██╗ " << endl;
59  cout << "██║ █████╗ ██████╔╝ ███╔╝ ██║ ██║██║ ██║ " << endl;
60  cout << "██║ ██╔══╝ ██╔═══╝ ███╔╝ ██║ ██║██║ ██║ " << endl;
61  cout << "╚██████╗██║ ██║███████╗███████╗╚██████╔╝╚██████╔╝ " << endl;
62  cout << " ╚═════╝╚═╝ ╚═╝╚══════╝╚══════╝ ╚═════╝ ╚═════╝ " << endl;
63  cout << "A cloudFPGA project from IBM ZRL v1.0 " << endl;
64  cout << "Quantitative Finance Monte-Carlo European Pricing Engine " << endl;
65 }
66 
67 
68 
73 void markPointsOnImage(Mat& imgOutput,
74  Mat& in_img,
75  Mat& out_img,
76  vector<Point>& hw_points)
77 {
78 
79  for (int j = 0; j < imgOutput.rows; j++) {
80  for (int i = 0; i < (imgOutput.cols); i++) {
81  //for CV_8UC1
82  unsigned char pix = imgOutput.at<unsigned char>(j,i); //.read(j * (imgOutput.cols) + i);
83  if (pix != 0) {
84  Point tmp;
85  tmp.x = i;
86  tmp.y = j;
87  if ((tmp.x < in_img.cols) && (tmp.y < in_img.rows) && (j > 0)) {
88  hw_points.push_back(tmp);
89  }
90  short int y, x;
91  y = j;
92  x = i;
93  if (j > 0) circle(out_img, Point(x, y), 2, Scalar(0, 0, 255, 255), 1, 8, 0);
94  }
95  }
96  }
97 }
98 
99 
100 
105 int main(int argc, char * argv[]) {
106  if ((argc < 3) || (argc > 4)) { // Test for correct number of arguments
107  cerr << "Usage: " << argv[0] << " <Server> <Server Port> <optional input image>\n";
108  exit(1);
109  }
110 
111 
112  //------------------------------------------------------
113  //-- STEP-1 : Socket and variables definition
114  //------------------------------------------------------
115  string servAddress = argv[1]; // First arg: server address
116  unsigned short servPort = Socket::resolveService(argv[2], "udp");
117  char buffer[BUF_LEN]; // Buffer for echo string
118  unsigned int recvMsgSize; // Size of received message
119  unsigned int num_frame = 0;
120  float Th;
121  if (FILTER_WIDTH == 3) {
122  Th = 30532960.00;
123  } else if (FILTER_WIDTH == 5) {
124  Th = 902753878016.0;
125  } else if (FILTER_WIDTH == 7) {
126  Th = 41151168289701888.000000;
127  }
128  string out_img_file, out_points_file;
129  string out_video_file;
130  // Define the codec and create VideoWriter object.The output is stored in 'outcpp.avi' file.
131  out_video_file.assign(argv[3]);
132  out_video_file += "_fpga_img_out.avi";
133  VideoWriter video(out_video_file,CV_FOURCC('M','J','P','G'),10, Size(FRAME_WIDTH,FRAME_HEIGHT));
134 
135  print_cFpZoo();
136 
137  try {
138 
139  //------------------------------------------------------
140  //-- STEP-2 : Initialize socket connection
141  //------------------------------------------------------
142  #ifndef TB_SIM_CFP_VITIS
143  UDPSocket sock(servPort); // NOTE: It is very important to set port here in order to call
144  // bind() in the UDPSocket constructor
145  #else
146  UDPSocket sock; // NOTE: In HOST TB the port is already binded by gammacorrection_host_fwd_tb.cpp
147  #endif
148 
149  //------------------------------------------------------------------------------------
150  //-- STEP-3 : Initialize a Greyscale OpenCV Mat either from image or from video/camera
151  //------------------------------------------------------------------------------------
152  Mat frame, send, ocv_out_img;
153  vector < uchar > encoded;
154 
155  VideoCapture cap(argv[3]); // Grab the camera
156  if (!cap.isOpened()) {
157  cerr << "OpenCV Failed to open camera";
158  exit(1);
159  }
160  //frame = cv::imread(argv[3], cv::IMREAD_GRAYSCALE); // reading in the image in grey scale
161 
162  while (1) {
163  clock_t start_cycle_main = clock();
164  cap >> frame;
165  if (frame.empty()) break; // if input is an image, the loop will be executed once
166  if(frame.size().width==0) continue; //simple integrity check; skip erroneous data...
167  cout << " ___________________________________________________________________ " << endl;
168  cout << "/ \\" << endl;
169  cout << "INFO: Frame # " << ++num_frame << endl;
170  cv::cvtColor(frame,frame,CV_BGR2GRAY);
171  resize(frame, send, Size(FRAME_WIDTH, FRAME_HEIGHT), 0, 0, INTER_LINEAR);
172  cout << send.total() << endl;
173  cout << send.total() << endl;
174  if ((frame.cols != FRAME_WIDTH) || (frame.rows != FRAME_HEIGHT)) {
175  cout << "WARNING: Input frame was resized from " << frame.cols << "x"
176  << frame.rows << " to " << send.cols << "x" << send.rows << endl;
177  }
178  assert(send.total() == FRAME_WIDTH * FRAME_HEIGHT);
179 #ifdef SHOW_WINDOWS
180  namedWindow("host_send", CV_WINDOW_NORMAL);
181  imshow("host_send", send);
182 #endif
183  // Ensure that the send Mat is in continuous memory space. Typically, imread or resize
184  // will return such a continuous Mat, but we should check it.
185  assert(send.isContinuous());
186 
187  unsigned int total_pack = 1 + (send.total() * send.channels() - 1) / PACK_SIZE;
188  unsigned int total_bytes = total_pack * PACK_SIZE;
189  unsigned int bytes_in_last_pack = send.total() * send.channels() - (total_pack - 1) * PACK_SIZE;
190  assert(total_pack == TOT_TRANSFERS);
191 
192  cout << "INFO: Total packets to send/receive = " << total_pack << endl;
193  cout << "INFO: Total bytes to send/receive = " << send.total() * send.channels() << endl;
194  cout << "INFO: Total bytes in " << total_pack << " packets = " << total_bytes << endl;
195  cout << "INFO: Bytes in last packet = " << bytes_in_last_pack << endl;
196  cout << "INFO: Packet size (custom MTU) = " << PACK_SIZE << endl;
197 
198  //--------------------------------------------------------
199  //-- STEP-4 : RUN GAMMACORRECTION DETECTOR FROM OpenCV LIBRARY (SW)
200  //--------------------------------------------------------
201  clock_t start_cycle_gammacorrection_sw = clock();
202  ocv_out_img.create(send.rows, send.cols, INPUT_TYPE_HOST); // create memory for opencv output image
203  ocv_ref(send, ocv_out_img, Th);
204  clock_t end_cycle_gammacorrection_sw = clock();
205  double duration_gammacorrection_sw = (end_cycle_gammacorrection_sw - start_cycle_gammacorrection_sw) /
206  (double) CLOCKS_PER_SEC;
207  cout << "INFO: SW exec. time:" << duration_gammacorrection_sw << " seconds" << endl;
208  cout << "INFO: Effective FPS SW:" << (1 / duration_gammacorrection_sw) << " \tkbps:" <<
209  (PACK_SIZE * total_pack / duration_gammacorrection_sw / 1024 * 8) << endl;
210 
211 
212  //------------------------------------------------------
213  //-- STEP-5 : RUN GAMMACORRECTION DETECTOR FROM cF (HW)
214  //------------------------------------------------------
215  clock_t start_cycle_gammacorrection_hw = clock();
216 
217  //------------------------------------------------------
218  //-- STEP-5.1 : TX Loop
219  //------------------------------------------------------
220  clock_t last_cycle_tx = clock();
221  unsigned int sending_now = PACK_SIZE;
222  for (unsigned int i = 0; i < total_pack; i++) {
223  if ( i == total_pack - 1 ) {
224  sending_now = bytes_in_last_pack;
225  }
226  sock.sendTo( & send.data[i * PACK_SIZE], sending_now, servAddress, servPort);
227  delay(1000);
228  }
229 
230  clock_t next_cycle_tx = clock();
231  double duration_tx = (next_cycle_tx - last_cycle_tx) / (double) CLOCKS_PER_SEC;
232  cout << "INFO: Effective FPS TX:" << (1 / duration_tx) << " \tkbps:" << (PACK_SIZE *
233  total_pack / duration_tx / 1024 * 8) << endl;
234  last_cycle_tx = next_cycle_tx;
235 
236 
237  //------------------------------------------------------
238  //-- STEP-5.2 : RX Loop
239  //------------------------------------------------------
240  clock_t last_cycle_rx = clock();
241  unsigned int receiving_now = PACK_SIZE;
242  cout << "INFO: Expecting length of packs:" << total_pack << endl;
243  char * longbuf = new char[PACK_SIZE * total_pack];
244  for (unsigned int i = 0; i < total_pack; i++) {
245  if ( i == total_pack - 1 ) {
246  receiving_now = bytes_in_last_pack;
247  }
248  recvMsgSize = sock.recvFrom(buffer, BUF_LEN, servAddress, servPort);
249  if (recvMsgSize != receiving_now) {
250  cerr << "Received unexpected size pack:" << recvMsgSize << ". Expected: " <<
251  receiving_now << endl;
252  continue;
253 
254  }
255  memcpy( & longbuf[i * PACK_SIZE], buffer, receiving_now);
256  }
257 
258  cout << "INFO: Received packet from " << servAddress << ":" << servPort << endl;
259 
260  frame = cv::Mat(FRAME_HEIGHT, FRAME_WIDTH, INPUT_TYPE_HOST, longbuf); // OR vec.data() instead of ptr
261  if (frame.size().width == 0) {
262  cerr << "receive failure!" << endl;
263  continue;
264 
265  }
266 #ifdef SHOW_WINDOWS
267  namedWindow("host_recv", CV_WINDOW_NORMAL);
268  imshow("host_recv", frame);
269 #endif
270  clock_t next_cycle_rx = clock();
271  double duration_rx = (next_cycle_rx - last_cycle_rx) / (double) CLOCKS_PER_SEC;
272  cout << "INFO: Effective FPS RX:" << (1 / duration_rx) << " \tkbps:" << (PACK_SIZE *
273  total_pack / duration_rx / 1024 * 8) << endl;
274  last_cycle_rx = next_cycle_rx;
275 
276  clock_t end_cycle_gammacorrection_hw = next_cycle_rx;
277 
278  double duration_gammacorrection_hw = (end_cycle_gammacorrection_hw - start_cycle_gammacorrection_hw) /
279  (double) CLOCKS_PER_SEC;
280  cout << "INFO: HW exec. time:" << duration_gammacorrection_hw << " seconds" << endl;
281  cout << "INFO: Effective FPS HW:" << (1 / duration_gammacorrection_hw) << " \tkbps:" <<
282  (PACK_SIZE * total_pack / duration_gammacorrection_hw / 1024 * 8) << endl;
283 
284  //------------------------------------------------------
285  //-- STEP-6 : Write output files and show in windows
286  //------------------------------------------------------
287  Mat out_img;
288  out_img = send.clone();
289  vector<Point> hw_points;
290 
291  /* Mark HLS points on the image */
292  markPointsOnImage(frame, send, out_img, hw_points);
293 
294  ostringstream oss;
295  oss << "cFp_Vitis E2E:" << "INFO: Effective FPS HW:" << (1 / duration_gammacorrection_hw) <<
296  " \tkbps:" << (PACK_SIZE * total_pack / duration_gammacorrection_hw / 1024 * 8);
297  string windowName = "cFp_Vitis End2End"; //oss.str();
298  /*
299  string msg = "cFp_Vitis";
300  Scalar color(255, 0, 0);
301  int fontFace = FONT_HERSHEY_DUPLEX;
302  double fontScale = 0.5;
303  int thickness = 1;
304  putText(out_img,
305  msg, //text
306  Point(10, out_img.rows / 2), //top-left position
307  fontFace,
308  fontScale,
309  color, //font color
310  thickness);
311  */
312 #ifdef SHOW_WINDOWS
313  namedWindow(windowName, CV_WINDOW_NORMAL);
314  imshow(windowName, out_img);
315 #endif
316  //moveWindow(windowName, 0, 0);
317 #ifdef WRITE_OUTPUT_FILE
318  if (num_frame == 1) {
319  out_img_file.assign(argv[3]);
320  out_img_file += "_fpga_img_out_frame_" + to_string(num_frame) + ".png";
321  out_points_file.assign(argv[3]);
322  out_points_file += "_fpga_points_out_frame_" + to_string(num_frame) + ".png";
323  cout << "INFO: The output image file is stored at : " << out_img_file << endl;
324  cout << "INFO: The output points file is stored at : " << out_points_file << endl;
325  // We save the image received from network after being processed by Gammacorrection HW or HOST TB
326  imwrite(out_img_file, out_img);
327  imwrite(out_points_file, frame);
328  }
329  else if (num_frame > 1) {
330  // If the frame is empty, break immediately
331  if (frame.empty()) {
332  break;
333  }
334  cout << "INFO: The output video file is stored at : " << out_video_file << endl;
335  Mat tovideo;
336  if (frame.channels() != 1) {
337  tovideo = frame;
338  }
339  else {
340  cvtColor(frame, tovideo, COLOR_GRAY2BGR);
341  }
342  video.write(tovideo);
343  }
344 #endif
345  waitKey(FRAME_INTERVAL);
346  double duration_main = (clock() - start_cycle_main) / (double) CLOCKS_PER_SEC;
347  cout << "INFO: Effective FPS E2E:" << (1 / duration_main) << endl;
348  cout << "\\___________________________________________________________________/" << endl
349  << endl;
350  } // while loop
351 
352  // When everything done, release the video capture and write object
353  cap.release();
354  video.release();
355 
356  // Closes all the windows
357  destroyAllWindows();
358 
359  // Destructor closes the socket
360  } catch (SocketException & e) {
361  cerr << e.what() << endl;
362  exit(1);
363  }
364 
365  return 0;
366 }
367 
368 
369 
370 
#define FILTER_WIDTH
void ocv_ref(cv::Mat img_gray, cv::Mat &ocv_out_img, float Th)
Definition: xf_ocv_ref.hpp:552
int main(int argc, char *argv[])
void print_cFpZoo(void)
#define FRAME_INTERVAL
Definition: config.h:48
#define INPUT_TYPE_HOST
Definition: config.h:68
#define FRAME_HEIGHT
Definition: config.h:43
void delay(unsigned int mseconds)
void markPointsOnImage(Mat &imgOutput, Mat &in_img, Mat &out_img, vector< Point > &hw_points)
Mark the points found by Gammacorrection into the image.
#define FRAME_WIDTH
Definition: config.h:46
#define TOT_TRANSFERS
Definition: config.h:70
#define BUF_LEN
Definition: config.h:54
#define PACK_SIZE
Definition: config.h:51
def send(cFcluster cluster, node_id, data_obj, proto='udp', port=CF_DEFAULT_PORT)
Definition: comm.py:41
def clock()
Definition: common.py:174