wrappers.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. #include <iostream>
  2. #include <stdexcept>
  3. //wrappers
  4. #include "ivx.hpp"
  5. //OpenCV includes
  6. #include "opencv2/core.hpp"
  7. #include "opencv2/imgproc.hpp"
  8. #include "opencv2/imgcodecs.hpp"
  9. #include "opencv2/highgui.hpp"
  10. enum UserMemoryMode
  11. {
  12. COPY, USER_MEM, MAP
  13. };
  14. ivx::Graph createProcessingGraph(ivx::Image& inputImage, ivx::Image& outputImage);
  15. int ovxDemo(std::string inputPath, UserMemoryMode mode);
  16. ivx::Graph createProcessingGraph(ivx::Image& inputImage, ivx::Image& outputImage)
  17. {
  18. using namespace ivx;
  19. Context context = inputImage.get<Context>();
  20. Graph graph = Graph::create(context);
  21. vx_uint32 width = inputImage.width();
  22. vx_uint32 height = inputImage.height();
  23. // Intermediate images
  24. Image
  25. smoothed = Image::createVirtual(graph),
  26. cannied = Image::createVirtual(graph),
  27. halfImg = Image::create(context, width, height, VX_DF_IMAGE_U8),
  28. halfCanny = Image::create(context, width, height, VX_DF_IMAGE_U8);
  29. // Constants
  30. vx_uint32 threshCannyMin = 127;
  31. vx_uint32 threshCannyMax = 192;
  32. Threshold threshCanny = Threshold::createRange(context, VX_TYPE_UINT8, threshCannyMin, threshCannyMax);
  33. ivx::Scalar alpha = ivx::Scalar::create<VX_TYPE_FLOAT32>(context, 0.5);
  34. // Sequence of some image operations
  35. // Node can also be added in function-like style
  36. nodes::gaussian3x3(graph, inputImage, smoothed);
  37. Node::create(graph, VX_KERNEL_CANNY_EDGE_DETECTOR, smoothed, threshCanny,
  38. ivx::Scalar::create<VX_TYPE_INT32>(context, 3),
  39. ivx::Scalar::create<VX_TYPE_ENUM>(context, VX_NORM_L2), cannied);
  40. Node::create(graph, VX_KERNEL_ACCUMULATE_WEIGHTED, inputImage, alpha, halfImg);
  41. Node::create(graph, VX_KERNEL_ACCUMULATE_WEIGHTED, cannied, alpha, halfCanny);
  42. Node::create(graph, VX_KERNEL_ADD, halfImg, halfCanny,
  43. ivx::Scalar::create<VX_TYPE_ENUM>(context, VX_CONVERT_POLICY_SATURATE), outputImage);
  44. graph.verify();
  45. return graph;
  46. }
  47. int ovxDemo(std::string inputPath, UserMemoryMode mode)
  48. {
  49. using namespace cv;
  50. using namespace ivx;
  51. Mat image = imread(inputPath, IMREAD_GRAYSCALE);
  52. if (image.empty()) return -1;
  53. //check image format
  54. if (image.depth() != CV_8U || image.channels() != 1) return -1;
  55. try
  56. {
  57. Context context = Context::create();
  58. //put user data from cv::Mat to vx_image
  59. vx_df_image color = Image::matTypeToFormat(image.type());
  60. vx_uint32 width = image.cols, height = image.rows;
  61. Image ivxImage;
  62. if (mode == COPY)
  63. {
  64. ivxImage = Image::create(context, width, height, color);
  65. ivxImage.copyFrom(0, image);
  66. }
  67. else
  68. {
  69. ivxImage = Image::createFromHandle(context, color, Image::createAddressing(image), image.data);
  70. }
  71. Image ivxResult;
  72. Image::Patch resultPatch;
  73. Mat output;
  74. if (mode == COPY || mode == MAP)
  75. {
  76. //we will copy or map data from vx_image to cv::Mat
  77. ivxResult = ivx::Image::create(context, width, height, VX_DF_IMAGE_U8);
  78. }
  79. else // if (mode == MAP_TO_VX)
  80. {
  81. //create vx_image based on user data, no copying required
  82. output = cv::Mat(height, width, CV_8U, cv::Scalar(0));
  83. ivxResult = Image::createFromHandle(context, Image::matTypeToFormat(CV_8U),
  84. Image::createAddressing(output), output.data);
  85. }
  86. Graph graph = createProcessingGraph(ivxImage, ivxResult);
  87. // Graph execution
  88. graph.process();
  89. //getting resulting image in cv::Mat
  90. if (mode == COPY)
  91. {
  92. ivxResult.copyTo(0, output);
  93. }
  94. else if (mode == MAP)
  95. {
  96. //create cv::Mat based on vx_image mapped data
  97. resultPatch.map(ivxResult, 0, ivxResult.getValidRegion());
  98. //generally this is very bad idea!
  99. //but in our case unmap() won't happen until output is in use
  100. output = resultPatch.getMat();
  101. }
  102. else // if (mode == MAP_TO_VX)
  103. {
  104. #ifdef VX_VERSION_1_1
  105. //we should take user memory back from vx_image before using it (even before reading)
  106. ivxResult.swapHandle();
  107. #endif
  108. }
  109. //here output goes
  110. cv::imshow("processing result", output);
  111. cv::waitKey(0);
  112. cv::destroyAllWindows();
  113. #ifdef VX_VERSION_1_1
  114. if (mode != COPY)
  115. {
  116. //we should take user memory back before release
  117. //(it's not done automatically according to standard)
  118. ivxImage.swapHandle();
  119. if (mode == USER_MEM) ivxResult.swapHandle();
  120. }
  121. #endif
  122. //the line is unnecessary since unmapping is done on destruction of patch
  123. //resultPatch.unmap();
  124. }
  125. catch (const ivx::RuntimeError& e)
  126. {
  127. std::cerr << "Error: code = " << e.status() << ", message = " << e.what() << std::endl;
  128. return e.status();
  129. }
  130. catch (const ivx::WrapperError& e)
  131. {
  132. std::cerr << "Error: message = " << e.what() << std::endl;
  133. return -1;
  134. }
  135. return 0;
  136. }
  137. int main(int argc, char *argv[])
  138. {
  139. const std::string keys =
  140. "{help h usage ? | | }"
  141. "{image | <none> | image to be processed}"
  142. "{mode | copy | user memory interaction mode: \n"
  143. "copy: create VX images and copy data to/from them\n"
  144. "user_mem: use handles to user-allocated memory\n"
  145. "map: map resulting VX image to user memory}"
  146. ;
  147. cv::CommandLineParser parser(argc, argv, keys);
  148. parser.about("OpenVX interoperability sample demonstrating OpenVX wrappers usage."
  149. "The application loads an image, processes it with OpenVX graph and outputs result in a window");
  150. if (parser.has("help"))
  151. {
  152. parser.printMessage();
  153. return 0;
  154. }
  155. std::string imgPath = parser.get<std::string>("image");
  156. std::string modeString = parser.get<std::string>("mode");
  157. UserMemoryMode mode;
  158. if(modeString == "copy")
  159. {
  160. mode = COPY;
  161. }
  162. else if(modeString == "user_mem")
  163. {
  164. mode = USER_MEM;
  165. }
  166. else if(modeString == "map")
  167. {
  168. mode = MAP;
  169. }
  170. else
  171. {
  172. std::cerr << modeString << ": unknown memory mode" << std::endl;
  173. return -1;
  174. }
  175. if (!parser.check())
  176. {
  177. parser.printErrors();
  178. return -1;
  179. }
  180. return ovxDemo(imgPath, mode);
  181. }