common.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. #ifndef SAMPLE_COMMON_COMMON_HPP_
  2. #define SAMPLE_COMMON_COMMON_HPP_
  3. #include "Utils.hpp"
  4. #include <fstream>
  5. #include <iterator>
  6. #include <opencv2/opencv.hpp>
  7. #include "DepthRender.hpp"
  8. #include "MatViewer.hpp"
  9. #include "TYThread.hpp"
  10. #include "DepthInpainter.hpp"
  11. #include "TyIsp.h"
  12. #include "BayerISP.hpp"
  13. #include "CommandLineParser.hpp"
  14. #include "CommandLineFeatureHelper.hpp"
  15. static inline int decodeCsiRaw10(unsigned char* src, unsigned short* dst, int width, int height)
  16. {
  17. if(width & 0x3) {
  18. return -1;
  19. }
  20. int raw10_line_size = 5 * width / 4;
  21. for(size_t i = 0, j = 0; i < raw10_line_size * height; i+=5, j+=4)
  22. {
  23. //[A2 - A9] | [B2 - B9] | [C2 - C9] | [D2 - D9] | [A0A1-B0B1-C0C1-D0D1]
  24. dst[j + 0] = ((uint16_t)src[i + 0] << 2) | ((src[i + 4] & 0x3) >> 0);
  25. dst[j + 1] = ((uint16_t)src[i + 1] << 2) | ((src[i + 4] & 0xc) >> 2);
  26. dst[j + 2] = ((uint16_t)src[i + 2] << 2) | ((src[i + 4] & 0x30) >> 4);
  27. dst[j + 3] = ((uint16_t)src[i + 3] << 2) | ((src[i + 4] & 0xc0) >> 6);
  28. }
  29. return 0;
  30. }
  31. static inline int decodeCsiRaw12(unsigned char* src, unsigned short* dst, int width, int height)
  32. {
  33. if(width & 0x1) {
  34. return -1;
  35. }
  36. int raw12_line_size = 3 * width / 2;
  37. for(size_t i = 0, j = 0; i < raw12_line_size * height; i+=3, j+=2)
  38. {
  39. //[A4 - A11] | [B4 - B11] | [A0A1A2A3-B0B1B2B3]
  40. dst[j + 0] = ((uint16_t)src[i + 0] << 4) | ((src[i + 2] & 0x0f) >> 0);
  41. dst[j + 1] = ((uint16_t)src[i + 1] << 4) | ((src[i + 2] & 0xf0) >> 4);
  42. }
  43. return 0;
  44. }
  45. static inline int decodeCsiRaw14(unsigned char* src, unsigned short* dst, int width, int height)
  46. {
  47. if(width & 0x3) {
  48. return -1;
  49. }
  50. int raw14_line_size = 7 * width / 4;
  51. for(size_t i = 0, j = 0; i < raw14_line_size * height; i+=7, j+=4)
  52. {
  53. //[A6 - A13] | [B6 - B13] | [C6 - C13] | [D6 - D13] | [A0A1A2A3A4A5-B0B1] | [B2B3B4B5-C0C1C2C3] | [C4C5-D0D1D2D3D4D5]
  54. dst[j + 0] = ((uint16_t)src[i + 0] << 6) | ((src[i + 4] & 0x3f) >> 0);
  55. dst[j + 1] = ((uint16_t)src[i + 1] << 6) | ((src[i + 4] & 0xc0) >> 6) | ((src[i + 5] & 0x0f) << 2);
  56. dst[j + 2] = ((uint16_t)src[i + 2] << 6) | ((src[i + 5] & 0xf0) >> 4) | ((src[i + 6] & 0x03) << 4);
  57. dst[j + 3] = ((uint16_t)src[i + 3] << 6) | ((src[i + 6] & 0xfc) >> 2);
  58. }
  59. return 0;
  60. }
  61. static inline int parseCsiRaw10(unsigned char* src, cv::Mat &dst, int width, int height)
  62. {
  63. cv::Mat m(height, width, CV_16U);
  64. decodeCsiRaw10(src, (ushort*)m.data, width, height);
  65. //convert valid 10bit from lsb to msb, d = s * 64
  66. dst = m * 64;
  67. return 0;
  68. }
  69. static inline int parseCsiRaw12(unsigned char* src, cv::Mat &dst, int width, int height)
  70. {
  71. cv::Mat m(height, width, CV_16U);
  72. decodeCsiRaw12(src, (ushort*)m.data, width, height);
  73. //convert valid 12bit from lsb to msb, d = s * 16
  74. dst = m * 16;
  75. return 0;
  76. }
  77. static inline int parseIrFrame(const TY_IMAGE_DATA* img, cv::Mat* pIR)
  78. {
  79. if (img->pixelFormat == TY_PIXEL_FORMAT_MONO16 || img->pixelFormat==TY_PIXEL_FORMAT_TOF_IR_MONO16){
  80. *pIR = cv::Mat(img->height, img->width, CV_16U, img->buffer).clone();
  81. } else if(img->pixelFormat == TY_PIXEL_FORMAT_CSI_MONO10) {
  82. *pIR = cv::Mat(img->height, img->width, CV_16U);
  83. parseCsiRaw10((uchar*)img->buffer, (*pIR), img->width, img->height);
  84. } else if(img->pixelFormat == TY_PIXEL_FORMAT_MONO) {
  85. *pIR = cv::Mat(img->height, img->width, CV_8U, img->buffer).clone();
  86. } else if(img->pixelFormat == TY_PIXEL_FORMAT_CSI_MONO12) {
  87. *pIR = cv::Mat(img->height, img->width, CV_8U, img->buffer).clone();
  88. parseCsiRaw12((uchar*)img->buffer, (*pIR), img->width, img->height);
  89. }
  90. else {
  91. return -1;
  92. }
  93. return 0;
  94. }
  95. static inline int parseBayer8Frame(const TY_IMAGE_DATA* img, cv::Mat* pColor, TY_ISP_HANDLE color_isp_handle = NULL)
  96. {
  97. int code = cv::COLOR_BayerGB2BGR;
  98. switch (img->pixelFormat)
  99. {
  100. case TY_PIXEL_FORMAT_BAYER8GBRG:
  101. code = cv::COLOR_BayerGR2BGR;
  102. break;
  103. case TY_PIXEL_FORMAT_BAYER8BGGR:
  104. code = cv::COLOR_BayerRG2BGR;
  105. break;
  106. case TY_PIXEL_FORMAT_BAYER8GRBG:
  107. code = cv::COLOR_BayerGB2BGR;
  108. break;
  109. case TY_PIXEL_FORMAT_BAYER8RGGB:
  110. code = cv::COLOR_BayerBG2BGR;
  111. break;
  112. default:
  113. LOGE("Invalid bayer8 fmt!");
  114. return -1;
  115. }
  116. if (!color_isp_handle){
  117. cv::Mat raw(img->height, img->width, CV_8U, img->buffer);
  118. cv::cvtColor(raw, *pColor, code);
  119. }
  120. else{
  121. cv::Mat raw(img->height, img->width, CV_8U, img->buffer);
  122. pColor->create(img->height, img->width, CV_8UC3);
  123. int sz = img->height* img->width * 3;
  124. TY_IMAGE_DATA out_buff = TYInitImageData(sz, pColor->data, img->width, img->height);
  125. out_buff.pixelFormat = TY_PIXEL_FORMAT_BGR;
  126. int res = TYISPProcessImage(color_isp_handle, img, &out_buff);
  127. if (res != TY_STATUS_OK){
  128. //fall back to using opencv api
  129. cv::Mat raw(img->height, img->width, CV_8U, img->buffer);
  130. cv::cvtColor(raw, *pColor, code);
  131. }
  132. }
  133. return 0;
  134. }
  135. static inline int parseBayer10Frame(const TY_IMAGE_DATA* img, cv::Mat* pColor)
  136. {
  137. int code = cv::COLOR_BayerGB2BGR;
  138. switch (img->pixelFormat)
  139. {
  140. case TY_PIXEL_FORMAT_CSI_BAYER10GBRG:
  141. code = cv::COLOR_BayerGR2BGR;
  142. break;
  143. case TY_PIXEL_FORMAT_CSI_BAYER10BGGR:
  144. code = cv::COLOR_BayerRG2BGR;
  145. break;
  146. case TY_PIXEL_FORMAT_CSI_BAYER10GRBG:
  147. code = cv::COLOR_BayerGB2BGR;
  148. break;
  149. case TY_PIXEL_FORMAT_CSI_BAYER10RGGB:
  150. code = cv::COLOR_BayerBG2BGR;
  151. break;
  152. default:
  153. LOGE("Invalid bayer10 fmt!");
  154. return -1;
  155. }
  156. cv::Mat raw16(img->height, img->width, CV_16U);
  157. parseCsiRaw10((uchar*)img->buffer, raw16, img->width, img->height);
  158. cv::cvtColor(raw16, *pColor, code);
  159. return 0;
  160. }
  161. static inline int parseBayer12Frame(const TY_IMAGE_DATA* img, cv::Mat* pColor)
  162. {
  163. int code = cv::COLOR_BayerGB2BGR;
  164. switch (img->pixelFormat)
  165. {
  166. case TY_PIXEL_FORMAT_CSI_BAYER12GBRG:
  167. code = cv::COLOR_BayerGR2BGR;
  168. break;
  169. case TY_PIXEL_FORMAT_CSI_BAYER12BGGR:
  170. code = cv::COLOR_BayerRG2BGR;
  171. break;
  172. case TY_PIXEL_FORMAT_CSI_BAYER12GRBG:
  173. code = cv::COLOR_BayerGB2BGR;
  174. break;
  175. case TY_PIXEL_FORMAT_CSI_BAYER12RGGB:
  176. code = cv::COLOR_BayerBG2BGR;
  177. break;
  178. default:
  179. LOGE("Invalid bayer12 fmt!");
  180. return -1;
  181. }
  182. cv::Mat raw16(img->height, img->width, CV_16U);
  183. parseCsiRaw12((uchar*)img->buffer, raw16, img->width, img->height);
  184. cv::cvtColor(raw16, *pColor, code);
  185. return 0;
  186. }
  187. static inline int parseColorFrame(const TY_IMAGE_DATA* img, cv::Mat* pColor, TY_ISP_HANDLE color_isp_handle = NULL)
  188. {
  189. int ret = 0;
  190. if (img->pixelFormat == TY_PIXEL_FORMAT_JPEG){
  191. std::vector<uchar> _v((uchar*)img->buffer, (uchar*)img->buffer + img->size);
  192. *pColor = cv::imdecode(_v, cv::IMREAD_COLOR);
  193. }
  194. else if (img->pixelFormat == TY_PIXEL_FORMAT_YVYU){
  195. cv::Mat yuv(img->height, img->width, CV_8UC2, img->buffer);
  196. cv::cvtColor(yuv, *pColor, cv::COLOR_YUV2BGR_YVYU);
  197. }
  198. else if (img->pixelFormat == TY_PIXEL_FORMAT_YUYV){
  199. cv::Mat yuv(img->height, img->width, CV_8UC2, img->buffer);
  200. cv::cvtColor(yuv, *pColor, cv::COLOR_YUV2BGR_YUYV);
  201. }
  202. else if (img->pixelFormat == TY_PIXEL_FORMAT_RGB){
  203. cv::Mat rgb(img->height, img->width, CV_8UC3, img->buffer);
  204. cv::cvtColor(rgb, *pColor, cv::COLOR_RGB2BGR);
  205. }
  206. else if (img->pixelFormat == TY_PIXEL_FORMAT_BGR){
  207. *pColor = cv::Mat(img->height, img->width, CV_8UC3, img->buffer);
  208. }
  209. else if (img->pixelFormat == TY_PIXEL_FORMAT_BAYER8GBRG ||
  210. img->pixelFormat == TY_PIXEL_FORMAT_BAYER8BGGR ||
  211. img->pixelFormat == TY_PIXEL_FORMAT_BAYER8GRBG ||
  212. img->pixelFormat == TY_PIXEL_FORMAT_BAYER8RGGB)
  213. {
  214. ret = parseBayer8Frame(img, pColor, color_isp_handle);
  215. }
  216. else if (img->pixelFormat == TY_PIXEL_FORMAT_CSI_BAYER10GBRG ||
  217. img->pixelFormat == TY_PIXEL_FORMAT_CSI_BAYER10BGGR ||
  218. img->pixelFormat == TY_PIXEL_FORMAT_CSI_BAYER10GRBG ||
  219. img->pixelFormat == TY_PIXEL_FORMAT_CSI_BAYER10RGGB)
  220. {
  221. ret = parseBayer10Frame(img, pColor);
  222. }
  223. else if(img->pixelFormat == TY_PIXEL_FORMAT_CSI_BAYER12GBRG ||
  224. img->pixelFormat == TY_PIXEL_FORMAT_CSI_BAYER12BGGR ||
  225. img->pixelFormat == TY_PIXEL_FORMAT_CSI_BAYER12GRBG ||
  226. img->pixelFormat == TY_PIXEL_FORMAT_CSI_BAYER12RGGB)
  227. {
  228. ret = parseBayer12Frame(img, pColor);
  229. }
  230. else if (img->pixelFormat == TY_PIXEL_FORMAT_MONO){
  231. cv::Mat gray(img->height, img->width, CV_8U, img->buffer);
  232. cv::cvtColor(gray, *pColor, cv::COLOR_GRAY2BGR);
  233. }
  234. else if (img->pixelFormat == TY_PIXEL_FORMAT_CSI_MONO10){
  235. cv::Mat gray16(img->height, img->width, CV_16U);
  236. parseCsiRaw10((uchar*)img->buffer, gray16, img->width, img->height);
  237. *pColor = gray16.clone();
  238. }
  239. return ret;
  240. }
  241. static inline int parseFrame(const TY_FRAME_DATA& frame, cv::Mat* pDepth
  242. , cv::Mat* pLeftIR, cv::Mat* pRightIR
  243. , cv::Mat* pColor, TY_ISP_HANDLE color_isp_handle = NULL)
  244. {
  245. for (int i = 0; i < frame.validCount; i++){
  246. if (frame.image[i].status != TY_STATUS_OK) continue;
  247. // get depth image
  248. if (pDepth && frame.image[i].componentID == TY_COMPONENT_DEPTH_CAM){
  249. if (frame.image[i].pixelFormat == TY_PIXEL_FORMAT_XYZ48) {
  250. *pDepth = cv::Mat(frame.image[i].height, frame.image[i].width
  251. , CV_16SC3, frame.image[i].buffer).clone();
  252. }
  253. else {
  254. *pDepth = cv::Mat(frame.image[i].height, frame.image[i].width
  255. , CV_16U, frame.image[i].buffer).clone();
  256. }
  257. }
  258. // get left ir image
  259. if (pLeftIR && frame.image[i].componentID == TY_COMPONENT_IR_CAM_LEFT){
  260. parseIrFrame(&frame.image[i], pLeftIR);
  261. }
  262. // get right ir image
  263. if (pRightIR && frame.image[i].componentID == TY_COMPONENT_IR_CAM_RIGHT){
  264. parseIrFrame(&frame.image[i], pRightIR);
  265. }
  266. // get BGR
  267. if (pColor && frame.image[i].componentID == TY_COMPONENT_RGB_CAM){
  268. parseColorFrame(&frame.image[i], pColor, color_isp_handle);
  269. }
  270. }
  271. return 0;
  272. }
  273. enum{
  274. PC_FILE_FORMAT_XYZ = 0,
  275. };
  276. static void writePC_XYZ(const cv::Point3f* pnts, const cv::Vec3b *color, size_t n, FILE* fp)
  277. {
  278. if (color){
  279. for (size_t i = 0; i < n; i++){
  280. if (!std::isnan(pnts[i].x)){
  281. fprintf(fp, "%f %f %f %d %d %d\n", pnts[i].x, pnts[i].y, pnts[i].z, color[i][0], color[i][1], color[i][2]);
  282. }
  283. }
  284. }
  285. else{
  286. for (size_t i = 0; i < n; i++){
  287. if (!std::isnan(pnts[i].x)){
  288. fprintf(fp, "%f %f %f 0 0 0\n", pnts[i].x, pnts[i].y, pnts[i].z);
  289. }
  290. }
  291. }
  292. }
  293. static void writePointCloud(const cv::Point3f* pnts, const cv::Vec3b *color, size_t n, const char* file, int format)
  294. {
  295. FILE* fp = fopen(file, "w");
  296. if (!fp){
  297. return;
  298. }
  299. switch (format){
  300. case PC_FILE_FORMAT_XYZ:
  301. writePC_XYZ(pnts, color, n, fp);
  302. break;
  303. default:
  304. break;
  305. }
  306. fclose(fp);
  307. }
  308. class CallbackWrapper
  309. {
  310. public:
  311. typedef void(*TY_FRAME_CALLBACK) (TY_FRAME_DATA*, void* userdata);
  312. CallbackWrapper(){
  313. _hDevice = NULL;
  314. _cb = NULL;
  315. _userdata = NULL;
  316. _exit = true;
  317. }
  318. TY_STATUS TYRegisterCallback(TY_DEV_HANDLE hDevice, TY_FRAME_CALLBACK v, void* userdata)
  319. {
  320. _hDevice = hDevice;
  321. _cb = v;
  322. _userdata = userdata;
  323. _exit = false;
  324. _cbThread.create(&workerThread, this);
  325. return TY_STATUS_OK;
  326. }
  327. void TYUnregisterCallback()
  328. {
  329. if (!_exit) {
  330. _exit = true;
  331. _cbThread.destroy();
  332. }
  333. }
  334. private:
  335. static void* workerThread(void* userdata)
  336. {
  337. CallbackWrapper* pWrapper = (CallbackWrapper*)userdata;
  338. TY_FRAME_DATA frame;
  339. while (!pWrapper->_exit)
  340. {
  341. int err = TYFetchFrame(pWrapper->_hDevice, &frame, 100);
  342. if (!err) {
  343. pWrapper->_cb(&frame, pWrapper->_userdata);
  344. }
  345. }
  346. LOGI("frameCallback exit!");
  347. return NULL;
  348. }
  349. TY_DEV_HANDLE _hDevice;
  350. TY_FRAME_CALLBACK _cb;
  351. void* _userdata;
  352. bool _exit;
  353. TYThread _cbThread;
  354. };
  355. #ifdef _WIN32
  356. static int get_fps() {
  357. static int fps_counter = 0;
  358. static clock_t fps_tm = 0;
  359. const int kMaxCounter = 250;
  360. fps_counter++;
  361. if (fps_counter < kMaxCounter) {
  362. return -1;
  363. }
  364. int elapse = (clock() - fps_tm);
  365. int v = (int)(((float)fps_counter) / elapse * CLOCKS_PER_SEC);
  366. fps_tm = clock();
  367. fps_counter = 0;
  368. return v;
  369. }
  370. #else
  371. static int get_fps() {
  372. static int fps_counter = 0;
  373. static clock_t fps_tm = 0;
  374. const int kMaxCounter = 200;
  375. struct timeval start;
  376. fps_counter++;
  377. if (fps_counter < kMaxCounter) {
  378. return -1;
  379. }
  380. gettimeofday(&start, NULL);
  381. int elapse = start.tv_sec * 1000 + start.tv_usec / 1000 - fps_tm;
  382. int v = (int)(((float)fps_counter) / elapse * 1000);
  383. gettimeofday(&start, NULL);
  384. fps_tm = start.tv_sec * 1000 + start.tv_usec / 1000;
  385. fps_counter = 0;
  386. return v;
  387. }
  388. #endif
  389. static std::vector<uint8_t> TYReadBinaryFile(const char* filename)
  390. {
  391. // open the file:
  392. std::ifstream file(filename, std::ios::binary);
  393. if (!file.is_open()){
  394. return std::vector<uint8_t>();
  395. }
  396. // Stop eating new lines in binary mode!!!
  397. file.unsetf(std::ios::skipws);
  398. // get its size:
  399. std::streampos fileSize;
  400. file.seekg(0, std::ios::end);
  401. fileSize = file.tellg();
  402. file.seekg(0, std::ios::beg);
  403. // reserve capacity
  404. std::vector<uint8_t> vec;
  405. vec.reserve(fileSize);
  406. // read the data:
  407. vec.insert(vec.begin(),
  408. std::istream_iterator<uint8_t>(file),
  409. std::istream_iterator<uint8_t>());
  410. return vec;
  411. }
  412. #endif