videocapture_openni.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. #include "opencv2/videoio/videoio.hpp"
  2. #include "opencv2/highgui.hpp"
  3. #include "opencv2/imgproc.hpp"
  4. #include <iostream>
  5. using namespace cv;
  6. using namespace std;
  7. static void help()
  8. {
  9. cout << "\nThis program demonstrates usage of depth sensors (Kinect, XtionPRO,...).\n"
  10. "The user gets some of the supported output images.\n"
  11. "\nAll supported output map types:\n"
  12. "1.) Data given from depth generator\n"
  13. " CAP_OPENNI_DEPTH_MAP - depth values in mm (CV_16UC1)\n"
  14. " CAP_OPENNI_POINT_CLOUD_MAP - XYZ in meters (CV_32FC3)\n"
  15. " CAP_OPENNI_DISPARITY_MAP - disparity in pixels (CV_8UC1)\n"
  16. " CAP_OPENNI_DISPARITY_MAP_32F - disparity in pixels (CV_32FC1)\n"
  17. " CAP_OPENNI_VALID_DEPTH_MASK - mask of valid pixels (not occluded, not shaded etc.) (CV_8UC1)\n"
  18. "2.) Data given from RGB image generator\n"
  19. " CAP_OPENNI_BGR_IMAGE - color image (CV_8UC3)\n"
  20. " CAP_OPENNI_GRAY_IMAGE - gray image (CV_8UC1)\n"
  21. "2.) Data given from IR image generator\n"
  22. " CAP_OPENNI_IR_IMAGE - gray image (CV_16UC1)\n"
  23. << endl;
  24. }
  25. static void colorizeDisparity( const Mat& gray, Mat& rgb, double maxDisp=-1.f)
  26. {
  27. CV_Assert( !gray.empty() );
  28. CV_Assert( gray.type() == CV_8UC1 );
  29. if( maxDisp <= 0 )
  30. {
  31. maxDisp = 0;
  32. minMaxLoc( gray, 0, &maxDisp );
  33. }
  34. rgb.create( gray.size(), CV_8UC3 );
  35. rgb = Scalar::all(0);
  36. if( maxDisp < 1 )
  37. return;
  38. Mat tmp;
  39. convertScaleAbs(gray, tmp, 255.f / maxDisp);
  40. applyColorMap(tmp, rgb, COLORMAP_JET);
  41. }
  42. static float getMaxDisparity( VideoCapture& capture )
  43. {
  44. const int minDistance = 400; // mm
  45. float b = (float)capture.get( CAP_OPENNI_DEPTH_GENERATOR_BASELINE ); // mm
  46. float F = (float)capture.get( CAP_OPENNI_DEPTH_GENERATOR_FOCAL_LENGTH ); // pixels
  47. return b * F / minDistance;
  48. }
  49. static void printCommandLineParams()
  50. {
  51. cout << "-cd= Colorized disparity? (0 or 1; 1 by default) Ignored if disparity map is not selected to show." << endl;
  52. cout << "-fmd= Fixed max disparity? (0 or 1; 0 by default) Ignored if disparity map is not colorized (-cd 0)." << endl;
  53. cout << "-mode= image mode: resolution and fps, supported three values: 0 - CAP_OPENNI_VGA_30HZ, 1 - CAP_OPENNI_SXGA_15HZ," << endl;
  54. cout << " 2 - CAP_OPENNI_SXGA_30HZ (0 by default). Ignored if rgb image or gray image are not selected to show." << endl;
  55. cout << "-m= Mask to set which output images are need. It is a string of size 6. Each element of this is '0' or '1' and" << endl;
  56. cout << " determine: is depth map, disparity map, valid pixels mask, rgb image, gray image need or not (correspondently), ir image" << endl ;
  57. cout << " By default -m=010100 i.e. disparity map and rgb image will be shown." << endl ;
  58. cout << "-r= Filename of .oni video file. The data will grabbed from it." << endl ;
  59. }
  60. static void parseCommandLine( int argc, char* argv[], bool& isColorizeDisp, bool& isFixedMaxDisp, int& imageMode, bool retrievedImageFlags[],
  61. string& filename, bool& isFileReading )
  62. {
  63. filename.clear();
  64. cv::CommandLineParser parser(argc, argv, "{h help||}{cd|1|}{fmd|0|}{mode|-1|}{m|010100|}{r||}");
  65. if (parser.has("h"))
  66. {
  67. help();
  68. printCommandLineParams();
  69. exit(0);
  70. }
  71. isColorizeDisp = (parser.get<int>("cd") != 0);
  72. isFixedMaxDisp = (parser.get<int>("fmd") != 0);
  73. imageMode = parser.get<int>("mode");
  74. int flags = parser.get<int>("m");
  75. isFileReading = parser.has("r");
  76. if (isFileReading)
  77. filename = parser.get<string>("r");
  78. if (!parser.check())
  79. {
  80. parser.printErrors();
  81. help();
  82. exit(-1);
  83. }
  84. if (flags % 1000000 == 0)
  85. {
  86. cout << "No one output image is selected." << endl;
  87. exit(0);
  88. }
  89. for (int i = 0; i < 6; i++)
  90. {
  91. retrievedImageFlags[5 - i] = (flags % 10 != 0);
  92. flags /= 10;
  93. }
  94. }
  95. /*
  96. * To work with Kinect or XtionPRO the user must install OpenNI library and PrimeSensorModule for OpenNI and
  97. * configure OpenCV with WITH_OPENNI flag is ON (using CMake).
  98. */
  99. int main( int argc, char* argv[] )
  100. {
  101. bool isColorizeDisp, isFixedMaxDisp;
  102. int imageMode;
  103. bool retrievedImageFlags[6];
  104. string filename;
  105. bool isVideoReading;
  106. parseCommandLine( argc, argv, isColorizeDisp, isFixedMaxDisp, imageMode, retrievedImageFlags, filename, isVideoReading );
  107. cout << "Device opening ..." << endl;
  108. VideoCapture capture;
  109. if( isVideoReading )
  110. capture.open( filename );
  111. else
  112. {
  113. capture.open( CAP_OPENNI2 );
  114. if( !capture.isOpened() )
  115. capture.open( CAP_OPENNI );
  116. }
  117. cout << "done." << endl;
  118. if( !capture.isOpened() )
  119. {
  120. cout << "Can not open a capture object." << endl;
  121. return -1;
  122. }
  123. if( !isVideoReading && imageMode >= 0 )
  124. {
  125. bool modeRes=false;
  126. switch ( imageMode )
  127. {
  128. case 0:
  129. modeRes = capture.set( CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE, CAP_OPENNI_VGA_30HZ );
  130. break;
  131. case 1:
  132. modeRes = capture.set( CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE, CAP_OPENNI_SXGA_15HZ );
  133. break;
  134. case 2:
  135. modeRes = capture.set( CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE, CAP_OPENNI_SXGA_30HZ );
  136. break;
  137. //The following modes are only supported by the Xtion Pro Live
  138. case 3:
  139. modeRes = capture.set( CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE, CAP_OPENNI_QVGA_30HZ );
  140. break;
  141. case 4:
  142. modeRes = capture.set( CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE, CAP_OPENNI_QVGA_60HZ );
  143. break;
  144. default:
  145. CV_Error( Error::StsBadArg, "Unsupported image mode property.\n");
  146. }
  147. if (!modeRes)
  148. cout << "\nThis image mode is not supported by the device, the default value (CV_CAP_OPENNI_SXGA_15HZ) will be used.\n" << endl;
  149. }
  150. // turn on depth, color and IR if needed
  151. if (retrievedImageFlags[0] || retrievedImageFlags[1] || retrievedImageFlags[2])
  152. capture.set(CAP_OPENNI_DEPTH_GENERATOR_PRESENT, true);
  153. else
  154. capture.set(CAP_OPENNI_DEPTH_GENERATOR_PRESENT, false);
  155. if (retrievedImageFlags[3] || retrievedImageFlags[4])
  156. capture.set(CAP_OPENNI_IMAGE_GENERATOR_PRESENT, true);
  157. else
  158. capture.set(CAP_OPENNI_IMAGE_GENERATOR_PRESENT, false);
  159. if (retrievedImageFlags[5])
  160. capture.set(CAP_OPENNI_IR_GENERATOR_PRESENT, true);
  161. else
  162. capture.set(CAP_OPENNI_IR_GENERATOR_PRESENT, false);
  163. // Print some available device settings.
  164. if (capture.get(CAP_OPENNI_DEPTH_GENERATOR_PRESENT))
  165. {
  166. cout << "\nDepth generator output mode:" << endl <<
  167. "FRAME_WIDTH " << capture.get(CAP_PROP_FRAME_WIDTH) << endl <<
  168. "FRAME_HEIGHT " << capture.get(CAP_PROP_FRAME_HEIGHT) << endl <<
  169. "FRAME_MAX_DEPTH " << capture.get(CAP_PROP_OPENNI_FRAME_MAX_DEPTH) << " mm" << endl <<
  170. "FPS " << capture.get(CAP_PROP_FPS) << endl <<
  171. "REGISTRATION " << capture.get(CAP_PROP_OPENNI_REGISTRATION) << endl;
  172. }
  173. else
  174. {
  175. cout << "\nDevice doesn't contain depth generator or it is not selected." << endl;
  176. }
  177. if( capture.get( CAP_OPENNI_IMAGE_GENERATOR_PRESENT ) )
  178. {
  179. cout <<
  180. "\nImage generator output mode:" << endl <<
  181. "FRAME_WIDTH " << capture.get( CAP_OPENNI_IMAGE_GENERATOR+CAP_PROP_FRAME_WIDTH ) << endl <<
  182. "FRAME_HEIGHT " << capture.get( CAP_OPENNI_IMAGE_GENERATOR+CAP_PROP_FRAME_HEIGHT ) << endl <<
  183. "FPS " << capture.get( CAP_OPENNI_IMAGE_GENERATOR+CAP_PROP_FPS ) << endl;
  184. }
  185. else
  186. {
  187. cout << "\nDevice doesn't contain image generator or it is not selected." << endl;
  188. }
  189. if( capture.get(CAP_OPENNI_IR_GENERATOR_PRESENT) )
  190. {
  191. cout <<
  192. "\nIR generator output mode:" << endl <<
  193. "FRAME_WIDTH " << capture.get(CAP_OPENNI_IR_GENERATOR + CAP_PROP_FRAME_WIDTH) << endl <<
  194. "FRAME_HEIGHT " << capture.get(CAP_OPENNI_IR_GENERATOR + CAP_PROP_FRAME_HEIGHT) << endl <<
  195. "FPS " << capture.get(CAP_OPENNI_IR_GENERATOR + CAP_PROP_FPS) << endl;
  196. }
  197. else
  198. {
  199. cout << "\nDevice doesn't contain IR generator or it is not selected." << endl;
  200. }
  201. for(;;)
  202. {
  203. Mat depthMap;
  204. Mat validDepthMap;
  205. Mat disparityMap;
  206. Mat bgrImage;
  207. Mat grayImage;
  208. Mat irImage;
  209. if( !capture.grab() )
  210. {
  211. cout << "Can not grab images." << endl;
  212. return -1;
  213. }
  214. else
  215. {
  216. if( retrievedImageFlags[0] && capture.retrieve( depthMap, CAP_OPENNI_DEPTH_MAP ) )
  217. {
  218. const float scaleFactor = 0.05f;
  219. Mat show; depthMap.convertTo( show, CV_8UC1, scaleFactor );
  220. imshow( "depth map", show );
  221. }
  222. if( retrievedImageFlags[1] && capture.retrieve( disparityMap, CAP_OPENNI_DISPARITY_MAP ) )
  223. {
  224. if( isColorizeDisp )
  225. {
  226. Mat colorDisparityMap;
  227. colorizeDisparity( disparityMap, colorDisparityMap, isFixedMaxDisp ? getMaxDisparity(capture) : -1 );
  228. Mat validColorDisparityMap;
  229. colorDisparityMap.copyTo( validColorDisparityMap, disparityMap != 0 );
  230. imshow( "colorized disparity map", validColorDisparityMap );
  231. }
  232. else
  233. {
  234. imshow( "original disparity map", disparityMap );
  235. }
  236. }
  237. if( retrievedImageFlags[2] && capture.retrieve( validDepthMap, CAP_OPENNI_VALID_DEPTH_MASK ) )
  238. imshow( "valid depth mask", validDepthMap );
  239. if( retrievedImageFlags[3] && capture.retrieve( bgrImage, CAP_OPENNI_BGR_IMAGE ) )
  240. imshow( "rgb image", bgrImage );
  241. if( retrievedImageFlags[4] && capture.retrieve( grayImage, CAP_OPENNI_GRAY_IMAGE ) )
  242. imshow( "gray image", grayImage );
  243. if( retrievedImageFlags[5] && capture.retrieve( irImage, CAP_OPENNI_IR_IMAGE ) )
  244. {
  245. Mat ir8;
  246. irImage.convertTo(ir8, CV_8U, 256.0 / 3500, 0.0);
  247. imshow("IR image", ir8);
  248. }
  249. }
  250. if( waitKey( 30 ) >= 0 )
  251. break;
  252. }
  253. return 0;
  254. }