cloudFPGA (cF) API  1.0
The documentation of the source code of cloudFPGA (cF)
sobel_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 <string.h> // For memcpy()
39 #include "PracticalSockets.h" // For UDPSocket and SocketException
40 #include "config.h"
41 #include "util.hpp"
42 
43 #if !defined(PY_WRAP) || (PY_WRAP == PY_WRAP_SOBEL_FILENAME) || (PY_WRAP == PY_WRAP_SOBEL_NUMPI)
44 #include "opencv2/opencv.hpp"
45 #include "../../../../../../ROLE/vision/hls/sobel/include/xf_ocv_ref.hpp" // For SW reference Sobel from OpenCV
46 using namespace cv;
47 #endif
48 
49 using namespace std;
50 
51 void delay(unsigned int mseconds)
52 {
53  clock_t goal = mseconds + clock();
54  while (goal > clock());
55 }
56 
57 void print_cFpZoo(void)
58 {
59  cout << " " << endl;
60  cout << "...build with: " << endl;
61  cout << " ██████╗███████╗██████╗ ███████╗ ██████╗ ██████╗ " << endl;
62  cout << "██╔════╝██╔════╝██╔══██╗ ╚══███╔╝██╔═══██╗██╔═══██╗ " << endl;
63  cout << "██║ █████╗ ██████╔╝ ███╔╝ ██║ ██║██║ ██║ " << endl;
64  cout << "██║ ██╔══╝ ██╔═══╝ ███╔╝ ██║ ██║██║ ██║ " << endl;
65  cout << "╚██████╗██║ ██║███████╗███████╗╚██████╔╝╚██████╔╝ " << endl;
66  cout << " ╚═════╝╚═╝ ╚═╝╚══════╝╚══════╝ ╚═════╝ ╚═════╝ " << endl;
67  cout << "A cloudFPGA project from IBM ZRL v1.0 " << endl;
68  cout << "Quantitative Finance Monte-Carlo European Pricing Engine " << endl;
69 }
70 
71 
82 void resizeCropSquare(const cv::Mat &input, const cv::Mat &output, const cv::Size &dstSize, int interpolation = INTER_LINEAR)
83 {
84  int h = input.rows;
85  int w = input.cols;
86  int min_size = min(h, w);
87  int x = w/2-min_size/2;
88  int y = h/2-min_size/2;
89  // printf("w=%d, h=%d, min_size=%d, x=%d, y=%d, width=%d, height=%d\n", w, h, min_size, x, y, width, height);
90  cv::Mat crop_img = input(Rect(x, y, min_size, min_size));
91  resize(crop_img, output, Size(dstSize.width, dstSize.height), 0, 0, interpolation);
92 }
93 
94 
95 
96 #ifdef PY_WRAP
97 #if PY_WRAP == PY_WRAP_SOBEL_FILENAME
98 void sobel(char *s_servAddress, char *s_servPort, char *input_str, char *output_img_str, char *output_points_str)
99 #elif PY_WRAP == PY_WRAP_SOBEL_NUMPI
100 void sobel(int total_size, unsigned char *input_img, int total_size2, unsigned char *output_img, char *s_servAddress, char *s_servPort)
101 #endif // PY_WRAP value
102 {
103 #else // !PY_WRAP
108 int main(int argc, char * argv[]) {
109  if ((argc < 3) || (argc > 4)) { // Test for correct number of arguments
110  cerr << "Usage: " << argv[0] << " <Server> <Server Port> <optional input image>\n";
111  exit(1);
112  }
113 #endif // PY_WRAP
114 
115  //------------------------------------------------------
116  //-- STEP-1 : Socket and variables definition
117  //------------------------------------------------------
118 
119  #ifndef PY_WRAP
120  assert ((argc == 3) || (argc == 4));
121  string s_servAddress = argv[1]; // First arg: server address
122  char *s_servPort = argv[2];
123  #endif
124 
125  string servAddress = s_servAddress;
126  unsigned short servPort;
127  bool net_type = NET_TYPE;
128  if (net_type == udp) {
129  servPort = Socket::resolveService(s_servPort, "udp");
130  }
131  else if (net_type == tcp) {
132  servPort = atoi(s_servPort);
133  }
134  else {
135  cout << "ERROR: Invalid type of socket type provided: " << net_type << " Choosed one of (tcp=0 or udp=1)" << endl;
136  }
137 
138  unsigned char buffer[BUF_LEN]; // Buffer for echo string
139  unsigned int recvMsgSize; // Size of received message
140  string input_string;
141 #ifdef INPUT_FROM_CAMERA
142  int input_num;
143 #ifdef PY_WRAP
144 #if PY_WRAP == PY_WRAP_SOBEL_FILENAME
145  input_num = atoi(input_str);
146  input_string = "./cam"+to_string(input_num);
147 #endif // PY_WRAP == PY_WRAP_SOBEL_FILENAME
148 #else // !PY_WRAP
149  if (argc == 3) {
150  input_num = 0;
151  }
152  else if (argc == 4) {
153  input_num = atoi(argv[3]);
154  }
155  input_string = "./cam"+to_string(input_num);
156 #endif // PY_WRAP
157 #else // !INPUT_FROM_CAMERA
158 #ifdef PY_WRAP
159 #if PY_WRAP == PY_WRAP_SOBEL_FILENAME
160  input_string.assign(input_str);
161 #endif // PY_WRAP == PY_WRAP_SOBEL_FILENAME
162 #else // !PY_WRAP
163  if (argc == 3) {
164  // Give a default image
165  input_string.assign("../../../../../../ROLE/vision/hls/sobel/test/8x8.png");
166  }
167  else if (argc == 4) {
168  input_string.assign(argv[3]);
169  }
170 #endif // PY_WRAP
171 #endif // INPUT_FROM_CAMERA
172 
173 
174 #if !defined(PY_WRAP) || (PY_WRAP == PY_WRAP_SOBEL_FILENAME)
175 
176  // ksize: aperture linear size; it must be odd and greater than 1, for example: 3, 5, 7 ...
177  int ksize = WINDOW_SIZE ;
178  string out_img_file;
179  string out_video_file;
180  // Define the codec and create VideoWriter object.The output is stored in 'outcpp.avi' file.
181  //#ifdef PY_WRAP
182  //out_video_file.assign(output_str);
183  //#else // !PY_WRAP
184  out_video_file.assign(input_string);
185  out_video_file += "_fpga_video_out.avi";
186  //#endif // PY_WRAP
187 #if CV_MAJOR_VERSION < 4
188  VideoWriter video(out_video_file,CV_FOURCC('M','J','P','G'),10, Size(FRAME_WIDTH,FRAME_HEIGHT));
189 #else
190  VideoWriter video(out_video_file,cv::VideoWriter::fourcc('M','J','P','G'),10, Size(FRAME_WIDTH,FRAME_HEIGHT));
191 #endif
192 
193 #endif // #if !defined(PY_WRAP) || (PY_WRAP == PY_WRAP_SOBEL_FILENAME)
194 
195  print_cFpZoo();
196 
197  try {
198 
199  //------------------------------------------------------
200  //-- STEP-2 : Initialize socket connection
201  //------------------------------------------------------
202 #if NET_TYPE == udp
203 #ifndef TB_SIM_CFP_VITIS
204  UDPSocket sock(servPort); // NOTE: It is very important to set port here in order to call
205  // bind() in the UDPSocket constructor
206 #else // TB_SIM_CFP_VITIS
207  UDPSocket sock; // NOTE: In HOST TB the port is already binded by sobel_host_fwd_tb.cpp
208 #endif // TB_SIM_CFP_VITIS
209 #else // tcp
210  TCPSocket sock(servAddress, servPort);
211 #endif // udp/tcp
212 
213 
214 #if !defined(PY_WRAP) || (PY_WRAP == PY_WRAP_SOBEL_FILENAME)
215 
216 
217  //------------------------------------------------------------------------------------
218  //-- STEP-3 : Initialize a Greyscale OpenCV Mat either from image or from video/camera
219  //------------------------------------------------------------------------------------
220  Mat frame, send(FRAME_WIDTH, FRAME_HEIGHT, INPUT_TYPE_HOST, Scalar(0)), ocv_out_img;
221  vector < uchar > encoded;
222 
223 #ifdef INPUT_FROM_CAMERA
224 
225  VideoCapture cap(input_num); // Grab the camera
226  if (!cap.isOpened()) {
227  cerr << "OpenCV Failed to open camera " + input_num << endl;
228  exit(1);
229  }
230 
231 #else // INPUT_FROM_CAMERA
232 
233  VideoCapture cap(input_string); // Grab the image
234  if (!cap.isOpened()) {
235  cerr << "OpenCV Failed to open file " + input_string << endl;
236  exit(1);
237  }
238 
239 #endif // INPUT_FROM_CAMERA
240 
241  //frame = cv::imread(argv[3], cv::IMREAD_GRAYSCALE); // reading in the image in grey scale
242  unsigned int num_frame = 0;
243 
244  while (1) {
245  clock_t start_cycle_main = clock();
246  cap >> frame;
247  if (frame.empty()) break; // if input is an image, the loop will be executed once
248  if(frame.size().width==0) continue; //simple integrity check; skip erroneous data...
249  cout << " ___________________________________________________________________ " << endl;
250  cout << "/ \\" << endl;
251  cout << "INFO: Frame # " << ++num_frame << endl;
252 #if CV_MAJOR_VERSION < 4
253  cv::cvtColor(frame,frame,CV_BGR2GRAY);
254 #else
255  cv::cvtColor(frame,frame,cv::COLOR_BGR2GRAY);
256 #endif
257  resizeCropSquare(frame, send, Size(FRAME_WIDTH, FRAME_HEIGHT), INTER_LINEAR);
258  if ((frame.cols != FRAME_WIDTH) || (frame.rows != FRAME_HEIGHT)) {
259  cout << "WARNING: Input frame was resized from " << frame.cols << "x"
260  << frame.rows << " to " << send.cols << "x" << send.rows << endl;
261  }
262  assert(send.total() == FRAME_WIDTH * FRAME_HEIGHT);
263  // Ensure that the selection of MTU is a multiple of 8 (Bytes per transaction)
264  assert(PACK_SIZE % 8 == 0);
265 
266 #ifdef SHOW_WINDOWS
267  namedWindow("host_send", CV_WINDOW_NORMAL);
268  imshow("host_send", send);
269 
270 #endif // SHOW_WINDOWS
271 
272  // Ensure that the send Mat is in continuous memory space. Typically, imread or resize
273  // will return such a continuous Mat, but we should check it.
274  assert(send.isContinuous());
275 
276  unsigned int send_total = send.total();
277  unsigned int send_channels = send.channels();
278 
279 #else // PY_WRAP == PY_WRAP_SOBEL_NUMPI
280 
281  unsigned int send_total = (unsigned int)total_size;
282  unsigned int send_channels = 1; // FIXME: It is ok only for 1-d array, i.e. CV_8UC1
283  unsigned char * sendarr = input_img;
284 #endif // #if !defined(PY_WRAP) || (PY_WRAP == PY_WRAP_SOBEL_FILENAME)
285 
286  unsigned int total_pack = 1 + (send_total * send_channels - 1) / PACK_SIZE;
287  unsigned int total_bytes = total_pack * PACK_SIZE;
288  unsigned int bytes_in_last_pack = send_total * send_channels - (total_pack - 1) * PACK_SIZE;
289  assert(total_pack == TOT_TRANSFERS);
290 
291  //unsigned char * longbuf = new unsigned char[PACK_SIZE * total_pack];
292  unsigned char * longbuf = (unsigned char *) malloc (PACK_SIZE * total_pack * sizeof (unsigned char));
293 
294 // cout << "INFO: FPGA destination : " << servAddress << ":" << servPort << endl;
295 // cout << "INFO: Network socket : " << ((NET_TYPE == tcp) ? "TCP" : "UDP") << endl;
296 // cout << "INFO: Total packets to send/receive = " << total_pack << endl;
297 // cout << "INFO: Total bytes to send/receive = " << send_total * send_channels << endl;
298 // cout << "INFO: Total bytes in " << total_pack << " packets = " << total_bytes << endl;
299 // cout << "INFO: Bytes in last packet = " << bytes_in_last_pack << endl;
300 // cout << "INFO: Packet size (custom MTU) = " << PACK_SIZE << endl;
301 
302 #if !defined(PY_WRAP) || (PY_WRAP == PY_WRAP_SOBEL_FILENAME)
303 
304  //--------------------------------------------------------
305  //-- STEP-4 : RUN SOBEL DETECTOR FROM OpenCV LIBRARY (SW)
306  //--------------------------------------------------------
307  clock_t start_cycle_sobel_sw = clock();
308  ocv_out_img.create(send.rows, send.cols, INPUT_TYPE_HOST); // create memory for opencv output image
309  ocv_ref(send, ocv_out_img, ksize);
310  clock_t end_cycle_sobel_sw = clock();
311  double duration_sobel_sw = (end_cycle_sobel_sw - start_cycle_sobel_sw) /
312  (double) CLOCKS_PER_SEC;
313 // cout << "INFO: SW exec. time:" << duration_sobel_sw << " seconds" << endl;
314 // cout << "INFO: Effective FPS SW:" << (1 / duration_sobel_sw) << " \tkbps:" <<
315 // (PACK_SIZE * total_pack / duration_sobel_sw / 1024 * 8) << endl;
316 
317  //------------------------------------------------------
318  //-- STEP-5 : RUN SOBEL DETECTOR FROM cF (HW)
319  //------------------------------------------------------
320 
321  //------------------------------------------------------
322  //-- STEP-5.1 : Preparation
323  //------------------------------------------------------
324 
325  // Anchor a pointer on cvMat raw data
326  unsigned char * sendarr = send.isContinuous()? send.data: send.clone().data;
327 
328 
329 #endif // !defined(PY_WRAP) || (PY_WRAP == PY_WRAP_SOBEL_FILENAME)
330 
331  clock_t start_cycle_sobel_hw = clock();
332 
333  //------------------------------------------------------
334  //-- STEP-5.2 : TX Loop
335  //------------------------------------------------------
336  clock_t last_cycle_tx = clock();
337  unsigned int sending_now = PACK_SIZE;
338  for (unsigned int i = 0; i < total_pack; i++) {
339  if ( i == total_pack - 1 ) {
340  sending_now = bytes_in_last_pack;
341  }
342  #if NET_TYPE == udp
343  sock.sendTo( & sendarr[i * PACK_SIZE], sending_now, servAddress, servPort);
344  #else
345  sock.send( & sendarr[i * PACK_SIZE], sending_now);
346  #endif
347  //delay(200);
348  }
349 
350  clock_t next_cycle_tx = clock();
351  double duration_tx = (next_cycle_tx - last_cycle_tx) / (double) CLOCKS_PER_SEC;
352 // cout << "INFO: Effective FPS TX:" << (1 / duration_tx) << " \tkbps:" << (PACK_SIZE *
353 // total_pack / duration_tx / 1024 * 8) << endl;
354  last_cycle_tx = next_cycle_tx;
355 
356 
357  //------------------------------------------------------
358  //-- STEP-5.3 : RX Loop
359  //------------------------------------------------------
360  clock_t last_cycle_rx = clock();
361  unsigned int receiving_now = PACK_SIZE;
362 // cout << "INFO: Expecting length of packs:" << total_pack << " from " << servAddress << ":" << servPort << endl;
363  //unsigned char * longbuf = new unsigned char[PACK_SIZE * total_pack];
364  unsigned int loopi=0;
365  for (unsigned int i = 0; i < send_total; ) {
366  //cout << "DEBUG: i=" << i << ", loopi=" << loopi++ << endl;
367  //if ( i == total_pack - 1 ) {
368  // receiving_now = bytes_in_last_pack;
369  //}
370  #if NET_TYPE == udp
371  recvMsgSize = sock.recvFrom(buffer, BUF_LEN, servAddress, servPort);
372  #else
373  recvMsgSize = sock.recv(buffer, BUF_LEN);
374  #endif
375  if (recvMsgSize != receiving_now) {
376  cerr << "WARNING: at i=" << i << " received unexpected size pack:" << recvMsgSize << ". Expected: " <<
377  receiving_now << endl;
378  //continue;
379  }
380  memcpy( & longbuf[i], buffer, recvMsgSize);
381  //cout << "DEBUG: i=" << i << " recvMsgSize=" << recvMsgSize << endl;
382  i += recvMsgSize;
383  //delay(200);
384  }
385 // cout << "INFO: Received packet from " << servAddress << ":" << servPort << endl;
386 
387  clock_t next_cycle_rx = clock();
388  double duration_rx = (next_cycle_rx - last_cycle_rx) / (double) CLOCKS_PER_SEC;
389 // cout << "INFO: Effective FPS RX:" << (1 / duration_rx) << " \tkbps:" << (PACK_SIZE *
390 // total_pack / duration_rx / 1024 * 8) << endl;
391  last_cycle_rx = next_cycle_rx;
392 
393  clock_t end_cycle_sobel_hw = next_cycle_rx;
394 
395  double duration_sobel_hw = (end_cycle_sobel_hw - start_cycle_sobel_hw) /
396  (double) CLOCKS_PER_SEC;
397 // cout << "INFO: HW exec. time:" << duration_sobel_hw << " seconds" << endl;
398 // cout << "INFO: Effective FPS HW:" << (1 / duration_sobel_hw) << " \tkbps:" <<
399 // (PACK_SIZE * total_pack / duration_sobel_hw / 1024 * 8) << endl;
400 
401 #if !defined(PY_WRAP) || (PY_WRAP == PY_WRAP_SOBEL_FILENAME)
402 
403  frame = cv::Mat(FRAME_HEIGHT, FRAME_WIDTH, INPUT_TYPE_HOST, longbuf); // OR vec.data() instead of ptr
404  if (frame.size().width == 0) {
405  cerr << "receive failure!" << endl;
406  continue;
407  }
408 #ifdef SHOW_WINDOWS
409  namedWindow("host_recv", CV_WINDOW_NORMAL);
410  imshow("host_recv", frame);
411 #endif
412 
413  //------------------------------------------------------
414  //-- STEP-6 : Write output files and show in windows
415  //------------------------------------------------------
416 
417  ostringstream oss;
418 // oss << "cFp_Vitis E2E:" << "INFO: Effective FPS HW:" << (1 / duration_sobel_hw) <<
419 // " \tkbps:" << (PACK_SIZE * total_pack / duration_sobel_hw / 1024 * 8);
420  string windowName = "cFp_Vitis End2End"; //oss.str();
421 
422  //moveWindow(windowName, 0, 0);
423 #ifdef WRITE_OUTPUT_FILE
424  if (num_frame == 1) {
425  out_img_file.assign(input_string);
426  out_img_file += "_fpga_image_out_frame_" + to_string(num_frame) + ".png";
427 #if defined(PY_WRAP) && (PY_WRAP == PY_WRAP_SOBEL_FILENAME)
428 
429  if (!strcpy(output_img_str, &out_img_file[0])) {
430  cerr << "ERROR: Cannot write to output image string." << endl;
431  }
432 #endif // defined(PY_WRAP) && (PY_WRAP == PY_WRAP_SOBEL_FILENAME)
433  cout << "INFO: The output image file is stored at : " << out_img_file << endl;
434  // We save the image received from network after being processed by Sobel HW or HOST TB
435  imwrite(out_img_file, frame);
436  }
437  else if (num_frame > 1) {
438  // If the frame is empty, break immediately
439  if (frame.empty()) {
440  break;
441  }
442  cout << "INFO: The output video file is stored at : " << out_video_file << endl;
443  Mat tovideo;
444  if (frame.channels() != 1) {
445  tovideo = frame;
446  }
447  else {
448  cvtColor(frame, tovideo, COLOR_GRAY2BGR);
449  }
450  video.write(tovideo);
451  }
452 #endif // WRITE_OUTPUT_FILE
453  waitKey(FRAME_INTERVAL);
454  double duration_main = (clock() - start_cycle_main) / (double) CLOCKS_PER_SEC;
455 // cout << "INFO: Effective FPS E2E:" << (1 / duration_main) << endl;
456 // cout << "\\___________________________________________________________________/" << endl
457 // << endl;
458  //delete(longbuf);
459  free (longbuf);
460  } // while loop
461 
462  // When everything done, release the video capture and write object
463  cap.release();
464  video.release();
465 
466  // Closes all the windows
467  destroyAllWindows();
468 
469 #else // !defined(PY_WRAP) || (PY_WRAP == PY_WRAP_SOBEL_FILENAME)
470  //output_img = longbuf;
471  memcpy( output_img, longbuf, total_size);
472  free(longbuf);
473 #endif // !defined(PY_WRAP) || (PY_WRAP == PY_WRAP_SOBEL_FILENAME)
474 
475  // Destructor closes the socket
476  } catch (SocketException & e) {
477  cerr << e.what() << endl;
478  exit(1);
479  }
480 
481 #ifndef PY_WRAP
482  return 0;
483 #endif
484 }
485 
486 
487 
488 
cat GET request dos socat stdio tcp
Definition: commands.txt:1
void ocv_ref(cv::Mat img_gray, cv::Mat &ocv_out_img, float Th)
Definition: xf_ocv_ref.hpp:552
#define FRAME_INTERVAL
Definition: config.h:48
#define INPUT_TYPE_HOST
Definition: config.h:68
#define FRAME_HEIGHT
Definition: config.h:43
#define FRAME_WIDTH
Definition: config.h:46
#define TOT_TRANSFERS
Definition: config.h:70
#define WINDOW_SIZE
#define udp
Definition: config.h:66
#define NET_TYPE
Definition: config.h:60
#define BUF_LEN
Definition: config.h:54
#define PACK_SIZE
Definition: config.h:51
void sobel(ap_uint< 32 > *pi_rank, ap_uint< 32 > *pi_size, stream< NetworkWord > &siSHL_This_Data, stream< NetworkWord > &soTHIS_Shl_Data, stream< NetworkMetaStream > &siNrc_meta, stream< NetworkMetaStream > &soNrc_meta, ap_uint< 32 > *po_rx_ports, stream< DmCmd > &soMemWrCmdP0, stream< DmSts > &siMemWrStsP0, stream< Axis< 512 > > &soMemWriteP0, membus_t *lcl_mem0, membus_t *lcl_mem1)
Main process of the Sobel Application directives.
Definition: sobel.cpp:51
void print_cFpZoo(void)
Definition: sobel_host.cpp:57
void resizeCropSquare(const cv::Mat &input, const cv::Mat &output, const cv::Size &dstSize, int interpolation=INTER_LINEAR)
Resize an image and crop if necessary in order to keep a rectangle area in the middle of the image.
Definition: sobel_host.cpp:82
void delay(unsigned int mseconds)
Definition: sobel_host.cpp:51
def send(cFcluster cluster, node_id, data_obj, proto='udp', port=CF_DEFAULT_PORT)
Definition: comm.py:41
string input
Definition: test.py:9
string output
Definition: test.py:10
def clock()
Definition: common.py:174
Common utility functions headers, i.e. timing, printing wrappers.