libvisiontransfer  10.0.0
input_transfer_example.cpp
1 /*******************************************************************************
2  * Copyright (c) 2022 Nerian Vision GmbH
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *******************************************************************************/
14 
15 /* This example demonstrate the sending of input image data to SceneScan.
16  * For this example, SceneScan must be configured to use the virtual
17  * "Network" camera, and the correct image size and pixel format must be
18  * set.
19  *
20  * It is highly recommended to use TCP instead of UDP in this configuration.
21  */
22 
23 #include <visiontransfer/deviceenumeration.h>
24 #include <visiontransfer/asynctransfer.h>
25 #include <visiontransfer/imageset.h>
26 #include <iostream>
27 #include <exception>
28 #include <vector>
29 #include <cstdio>
30 #include <cstring>
31 #include <thread>
32 
33 #ifdef _WIN32
34 # include <windows.h>
35 #else
36 # include <unistd.h>
37 #endif
38 
39 #ifdef _MSC_VER
40 // Visual studio does not come with snprintf
41 #define snprintf _snprintf_s
42 #endif
43 
44 using namespace std;
45 using namespace visiontransfer;
46 
47 static const int numImages = 10;
48 static const ImageSet::ImageFormat imageFormat = ImageSet::FORMAT_8_BIT_MONO;
49 static const int imageWidth = 640;
50 static const int imageHeight = 480;
51 
52 int receivedFrames = 0;
53 
54 void sendThread(AsyncTransfer* asyncTransfer) {
55  try {
56  // Initialize the image set meta data
57  static ImageSet imageSet; // Data must remain valid while still sending
58  imageSet.setWidth(imageWidth);
59  imageSet.setHeight(imageHeight);
60  // Define the set of contained image types, assigning indices
61  imageSet.setNumberOfImages(2);
62  imageSet.setIndexOf(ImageSet::IMAGE_LEFT, 0);
63  imageSet.setIndexOf(ImageSet::IMAGE_RIGHT, 1);
64  // Initialize data for all constituent images
65  imageSet.setPixelFormat(0, imageFormat);
66  imageSet.setPixelFormat(1, imageFormat);
67  imageSet.setRowStride(0, imageSet.getBytesPerPixel(0)*imageSet.getWidth());
68  imageSet.setRowStride(1, imageSet.getBytesPerPixel(0)*imageSet.getWidth());
69  const int extraBufferSpace = 16; // Leave space some extra data in the buffer
70  static std::vector<unsigned char> pixelData(imageSet.getRowStride(0) * imageSet.getHeight() + extraBufferSpace);
71  imageSet.setPixelData(0, &pixelData[0]);
72  imageSet.setPixelData(1, &pixelData[0]);
73 
74  for(int i=0; i<numImages; i++) {
75  while(i-2 >= receivedFrames) { // Allow a maximum of 2 frames lead for sending
76 #ifdef _WIN32
77  Sleep(10);
78 #else
79  usleep(10000);
80 #endif
81  }
82 
83  // Generate test image data
84  for(int y=0; y<imageSet.getHeight(); y++) {
85  for(int x=0; x<imageSet.getRowStride(0); x++) {
86  pixelData[y*imageSet.getRowStride(0) + x] = (y + x + i) & 0xff;
87  }
88  }
89 
90  // Send the image data
91  std::cout << "Sending image set " << i << std::endl;
92  asyncTransfer->sendImageSetAsync(imageSet);
93  }
94  } catch(const std::exception& ex) {
95  std::cerr << "Exception occurred: " << ex.what() << std::endl;
96  }
97 }
98 
99 void receiveThread(AsyncTransfer* asyncTransfer) {
100  for(int i=0; i<numImages; i++) {
101  std::cout << "Receiving image set " << i << std::endl;
102 
103  // Receive image
104  ImageSet imageSet;
105  while(!asyncTransfer->collectReceivedImageSet(imageSet,
106  0.1 /*timeout*/)) {
107  // Keep on trying until reception is successful
108  }
109 
110  receivedFrames++;
111 
112  // Write all included images one after another
113  for(int imageNumber = 0; imageNumber < imageSet.getNumberOfImages(); imageNumber++) {
114  // Create PGM file
115  char fileName[100];
116  snprintf(fileName, sizeof(fileName), "image%03d_%d.pgm", i,
117  imageNumber);
118 
119  imageSet.writePgmFile(imageNumber, fileName);
120  }
121  }
122 }
123 
124 int main() {
125  try {
126  // Search for Nerian stereo devices
127  DeviceEnumeration deviceEnum;
128  DeviceEnumeration::DeviceList devices = deviceEnum.discoverDevices();
129  if(devices.size() == 0) {
130  std::cout << "No devices discovered!" << std::endl;
131  return -1;
132  }
133 
134  // Create an image transfer object that receives data from
135  // the first detected device
136  AsyncTransfer asyncTransfer(devices[0]);
137 
138  std::thread sndThread(sendThread, &asyncTransfer);
139  std::thread rcvThread(receiveThread, &asyncTransfer);
140 
141  sndThread.join();
142  rcvThread.join();
143  } catch(const std::exception& ex) {
144  std::cerr << "Exception occurred: " << ex.what() << std::endl;
145  }
146 
147  return 0;
148 }
void setNumberOfImages(int number)
Sets the number of valid images in this set.
Definition: imageset.h:414
int getRowStride(int imageNumber) const
Returns the row stride for the pixel data of one image.
Definition: imageset.h:221
void setPixelData(int imageNumber, unsigned char *pixelData)
Sets the pixel data for the given image.
Definition: imageset.h:137
DeviceList discoverDevices()
Discovers new devices and returns the list of all devices that have been found.
void setWidth(int w)
Sets a new width for both images.
Definition: imageset.h:93
void writePgmFile(int imageNumber, const char *fileName) const
Writes one image of the set to a PGM or PPM file.
Definition: imageset.cpp:106
int getNumberOfImages() const
Returns the number of images in this set.
Definition: imageset.h:407
int getHeight() const
Returns the height of each image.
Definition: imageset.h:210
void setHeight(int h)
Sets a new width for both images.
Definition: imageset.h:98
int getBytesPerPixel(int imageNumber) const
Returns the number of bytes that are required to store one image pixel.
Definition: imageset.h:375
void setPixelFormat(int imageNumber, ImageFormat format)
Sets the pixel format for the given image.
Definition: imageset.h:119
void setRowStride(int imageNumber, int stride)
Sets a new row stride for the pixel data of one image.
Definition: imageset.h:107
ImageFormat
Image formats that can be transferred.
Definition: imageset.h:44
A set of one to three images, but usually two (the left camera image and the disparity map)...
Definition: imageset.h:38
Class for asynchronous transfer of image sets.
Definition: asynctransfer.h:33
Allows for the discovery of devices in the network.
void setIndexOf(ImageType what, int idx)
Assign an image index to a specified ImageType, -1 to disable.
Definition: imageset.cpp:240
int getWidth() const
Returns the width of each image.
Definition: imageset.h:205
bool collectReceivedImageSet(ImageSet &imageSet, double timeout=-1)
Collects the asynchronously received image.
void sendImageSetAsync(const ImageSet &imageSet, bool deleteData=false)
Starts an asynchronous transmission of the given image set.
Nerian Vision Technologies