wrappers_video.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  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. yuv = Image::createVirtual(graph, 0, 0, VX_DF_IMAGE_YUV4),
  26. gray = Image::createVirtual(graph),
  27. smoothed = Image::createVirtual(graph),
  28. cannied = Image::createVirtual(graph),
  29. halfImg = Image::create(context, width, height, VX_DF_IMAGE_U8),
  30. halfCanny = Image::create(context, width, height, VX_DF_IMAGE_U8);
  31. // Constants
  32. vx_uint32 threshCannyMin = 127;
  33. vx_uint32 threshCannyMax = 192;
  34. Threshold threshCanny = Threshold::createRange(context, VX_TYPE_UINT8, threshCannyMin, threshCannyMax);
  35. ivx::Scalar alpha = ivx::Scalar::create<VX_TYPE_FLOAT32>(context, 0.5);
  36. // Sequence of some image operations
  37. Node::create(graph, VX_KERNEL_COLOR_CONVERT, inputImage, yuv);
  38. Node::create(graph, VX_KERNEL_CHANNEL_EXTRACT, yuv,
  39. ivx::Scalar::create<VX_TYPE_ENUM>(context, VX_CHANNEL_Y), gray);
  40. //node can also be added in function-like style
  41. nodes::gaussian3x3(graph, gray, smoothed);
  42. Node::create(graph, VX_KERNEL_CANNY_EDGE_DETECTOR, smoothed, threshCanny,
  43. ivx::Scalar::create<VX_TYPE_INT32>(context, 3),
  44. ivx::Scalar::create<VX_TYPE_ENUM>(context, VX_NORM_L2), cannied);
  45. Node::create(graph, VX_KERNEL_ACCUMULATE_WEIGHTED, gray, alpha, halfImg);
  46. Node::create(graph, VX_KERNEL_ACCUMULATE_WEIGHTED, cannied, alpha, halfCanny);
  47. Node::create(graph, VX_KERNEL_ADD, halfImg, halfCanny,
  48. ivx::Scalar::create<VX_TYPE_ENUM>(context, VX_CONVERT_POLICY_SATURATE), outputImage);
  49. graph.verify();
  50. return graph;
  51. }
  52. int ovxDemo(std::string inputPath, UserMemoryMode mode)
  53. {
  54. using namespace cv;
  55. using namespace ivx;
  56. Mat frame;
  57. VideoCapture vc(inputPath);
  58. if (!vc.isOpened())
  59. return -1;
  60. vc >> frame;
  61. if (frame.empty()) return -1;
  62. //check frame format
  63. if (frame.type() != CV_8UC3) return -1;
  64. try
  65. {
  66. Context context = Context::create();
  67. //put user data from cv::Mat to vx_image
  68. vx_df_image color = Image::matTypeToFormat(frame.type());
  69. vx_uint32 width = frame.cols, height = frame.rows;
  70. Image ivxImage;
  71. if (mode == COPY)
  72. {
  73. ivxImage = Image::create(context, width, height, color);
  74. }
  75. else
  76. {
  77. ivxImage = Image::createFromHandle(context, color, Image::createAddressing(frame), frame.data);
  78. }
  79. Image ivxResult;
  80. Mat output;
  81. if (mode == COPY || mode == MAP)
  82. {
  83. //we will copy or map data from vx_image to cv::Mat
  84. ivxResult = ivx::Image::create(context, width, height, VX_DF_IMAGE_U8);
  85. }
  86. else // if (mode == MAP_TO_VX)
  87. {
  88. //create vx_image based on user data, no copying required
  89. output = cv::Mat(height, width, CV_8U, cv::Scalar(0));
  90. ivxResult = Image::createFromHandle(context, Image::matTypeToFormat(CV_8U),
  91. Image::createAddressing(output), output.data);
  92. }
  93. Graph graph = createProcessingGraph(ivxImage, ivxResult);
  94. bool stop = false;
  95. while (!stop)
  96. {
  97. if (mode == COPY) ivxImage.copyFrom(0, frame);
  98. // Graph execution
  99. graph.process();
  100. //getting resulting image in cv::Mat
  101. Image::Patch resultPatch;
  102. std::vector<void*> ptrs;
  103. std::vector<void*> prevPtrs(ivxResult.planes());
  104. if (mode == COPY)
  105. {
  106. ivxResult.copyTo(0, output);
  107. }
  108. else if (mode == MAP)
  109. {
  110. //create cv::Mat based on vx_image mapped data
  111. resultPatch.map(ivxResult, 0, ivxResult.getValidRegion(), VX_READ_AND_WRITE);
  112. //generally this is very bad idea!
  113. //but in our case unmap() won't happen until output is in use
  114. output = resultPatch.getMat();
  115. }
  116. else // if(mode == MAP_TO_VX)
  117. {
  118. #ifdef VX_VERSION_1_1
  119. //we should take user memory back from vx_image before using it (even before reading)
  120. ivxResult.swapHandle(ptrs, prevPtrs);
  121. #endif
  122. }
  123. //here output goes
  124. imshow("press q to quit", output);
  125. if ((char)waitKey(1) == 'q') stop = true;
  126. #ifdef VX_VERSION_1_1
  127. //restore handle
  128. if (mode == USER_MEM)
  129. {
  130. ivxResult.swapHandle(prevPtrs, ptrs);
  131. }
  132. #endif
  133. //this line is unnecessary since unmapping is done on destruction of patch
  134. //resultPatch.unmap();
  135. //grab next frame
  136. Mat temp = frame;
  137. vc >> frame;
  138. if (frame.empty()) stop = true;
  139. if (mode != COPY && frame.data != temp.data)
  140. {
  141. //frame was reallocated, pointer to data changed
  142. frame.copyTo(temp);
  143. }
  144. }
  145. destroyAllWindows();
  146. #ifdef VX_VERSION_1_1
  147. if (mode != COPY)
  148. {
  149. //we should take user memory back before release
  150. //(it's not done automatically according to standard)
  151. ivxImage.swapHandle();
  152. if (mode == USER_MEM) ivxResult.swapHandle();
  153. }
  154. #endif
  155. }
  156. catch (const ivx::RuntimeError& e)
  157. {
  158. std::cerr << "Error: code = " << e.status() << ", message = " << e.what() << std::endl;
  159. return e.status();
  160. }
  161. catch (const ivx::WrapperError& e)
  162. {
  163. std::cerr << "Error: message = " << e.what() << std::endl;
  164. return -1;
  165. }
  166. return 0;
  167. }
  168. int main(int argc, char *argv[])
  169. {
  170. const std::string keys =
  171. "{help h usage ? | | }"
  172. "{video | <none> | video file to be processed}"
  173. "{mode | copy | user memory interaction mode: \n"
  174. "copy: create VX images and copy data to/from them\n"
  175. "user_mem: use handles to user-allocated memory\n"
  176. "map: map resulting VX image to user memory}"
  177. ;
  178. cv::CommandLineParser parser(argc, argv, keys);
  179. parser.about("OpenVX interoperability sample demonstrating OpenVX wrappers usage."
  180. "The application opens a video and processes it with OpenVX graph while outputting result in a window");
  181. if (parser.has("help"))
  182. {
  183. parser.printMessage();
  184. return 0;
  185. }
  186. std::string videoPath = parser.get<std::string>("video");
  187. std::string modeString = parser.get<std::string>("mode");
  188. UserMemoryMode mode;
  189. if(modeString == "copy")
  190. {
  191. mode = COPY;
  192. }
  193. else if(modeString == "user_mem")
  194. {
  195. mode = USER_MEM;
  196. }
  197. else if(modeString == "map")
  198. {
  199. mode = MAP;
  200. }
  201. else
  202. {
  203. std::cerr << modeString << ": unknown memory mode" << std::endl;
  204. return -1;
  205. }
  206. if (!parser.check())
  207. {
  208. parser.printErrors();
  209. return -1;
  210. }
  211. return ovxDemo(videoPath, mode);
  212. }