Openholo  v5.0
Open Source Digital Holographic Library
ophDepthMap.cpp
Go to the documentation of this file.
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install, copy or use the software.
7 //
8 //
9 // License Agreement
10 // For Open Source Digital Holographic Library
11 //
12 // Openholo library is free software;
13 // you can redistribute it and/or modify it under the terms of the BSD 2-Clause license.
14 //
15 // Copyright (C) 2017-2024, Korea Electronics Technology Institute. All rights reserved.
16 // E-mail : contact.openholo@gmail.com
17 // Web : http://www.openholo.org
18 //
19 // Redistribution and use in source and binary forms, with or without modification,
20 // are permitted provided that the following conditions are met:
21 //
22 // 1. Redistribution's of source code must retain the above copyright notice,
23 // this list of conditions and the following disclaimer.
24 //
25 // 2. Redistribution's in binary form must reproduce the above copyright notice,
26 // this list of conditions and the following disclaimer in the documentation
27 // and/or other materials provided with the distribution.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the copyright holder or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 // This software contains opensource software released under GNU Generic Public License,
41 // NVDIA Software License Agreement, or CUDA supplement to Software License Agreement.
42 // Check whether software you use contains licensed software.
43 //
44 //M*/
45 
46 #include "ophDepthMap.h"
47 #include <random>
48 #ifdef _WIN64
49 #include <io.h>
50 #include <direct.h>
51 #else
52 #include <dirent.h>
53 #endif
54 #include "sys.h"
55 #include "tinyxml2.h"
56 #include "include.h"
57 
59  : ophGen()
60  , stream_(nullptr)
61  , m_nProgress(0)
62 {
63  // GPU Variables
64  img_src_gpu = nullptr;
65  dimg_src_gpu = nullptr;
66  depth_index_gpu = nullptr;
67 
68  depth_img = nullptr;
69  m_vecRGB.clear();
70 
71  // CPU Variables
72  dmap_src = nullptr;
73  depth_index = nullptr;
74  dmap = 0;
75  dstep = 0;
76  dlevel.clear();
77 
78  setViewingWindow(false);
79  LOG("*** DEPTH MAP : BUILD DATE: %s %s ***\n\n", __DATE__, __TIME__);
80 }
81 
83 {
84 }
85 
86 void ophDepthMap::setViewingWindow(bool is_ViewingWindow)
87 {
88  this->is_ViewingWindow = is_ViewingWindow;
89 }
90 
91 bool ophDepthMap::readConfig(const char * fname)
92 {
93  if (!ophGen::readConfig(fname))
94  return false;
95 
96  bool bRet = true;
97  /*XML parsing*/
98 
99  using namespace tinyxml2;
100  tinyxml2::XMLDocument xml_doc;
101  XMLNode *xml_node = nullptr;
102 
103  if (!checkExtension(fname, ".xml"))
104  {
105  LOG("<FAILED> Wrong file ext.\n");
106  return false;
107  }
108  auto ret = xml_doc.LoadFile(fname);
109  if (ret != XML_SUCCESS)
110  {
111  LOG("<FAILED> Loading file.\n");
112  return false;
113  }
114 
115 
116  xml_node = xml_doc.FirstChild();
117 
118  char szNodeName[32] = { 0, };
119  sprintf(szNodeName, "FlagChangeDepthQuantization");
120  auto next = xml_node->FirstChildElement(szNodeName);
121  if (!next || XML_SUCCESS != next->QueryBoolText(&dm_config_.change_depth_quantization))
122  {
123  LOG("<FAILED> Not found node : \'%s\' (Boolean) \n", szNodeName);
124  bRet = false;
125  }
126  sprintf(szNodeName, "DefaultDepthQuantization");
127  next = xml_node->FirstChildElement(szNodeName);
128  if (!next || XML_SUCCESS != next->QueryUnsignedText(&dm_config_.default_depth_quantization))
129  {
130  LOG("<FAILED> Not found node : \'%s\' (Unsinged Integer) \n", szNodeName);
131  bRet = false;
132  }
133  sprintf(szNodeName, "NumberOfDepthQuantization");
134  next = xml_node->FirstChildElement(szNodeName);
135  if (!next || XML_SUCCESS != next->QueryUnsignedText(&dm_config_.num_of_depth_quantization))
136  {
137  LOG("<FAILED> Not found node : \'%s\' (Unsinged Integer) \n", szNodeName);
138  bRet = false;
139  }
140 
141  if (dm_config_.change_depth_quantization == 0)
142  dm_config_.num_of_depth = dm_config_.default_depth_quantization;
143  else
144  dm_config_.num_of_depth = dm_config_.num_of_depth_quantization;
145 
146  string render_depth;
147  sprintf(szNodeName, "RenderDepth");
148  next = xml_node->FirstChildElement(szNodeName);
149  if (!next || XML_SUCCESS != next->QueryBoolText(&dm_config_.change_depth_quantization))
150  {
151  LOG("<FAILED> Not found node : \'%s\' (Boolean) \n", szNodeName);
152  bRet = false;
153  }
154  else
155  render_depth = (xml_node->FirstChildElement(szNodeName))->GetText();
156 
157  size_t found = render_depth.find(':');
158  if (found != string::npos)
159  {
160  string s = render_depth.substr(0, found);
161  string e = render_depth.substr(found + 1);
162  int start = stoi(s);
163  int end = stoi(e);
164  dm_config_.render_depth.clear();
165  for (int k = start; k <= end; k++)
166  dm_config_.render_depth.push_back(k);
167  }
168  else
169  {
170  stringstream ss(render_depth);
171  int render;
172 
173  while (ss >> render)
174  dm_config_.render_depth.push_back(render);
175  }
176 
177  if (dm_config_.render_depth.empty()) {
178  LOG("<FAILED> Not found node : \'%s\' (String) \n", szNodeName);
179  bRet = false;
180  }
181 
182  sprintf(szNodeName, "RandomPhase");
183  next = xml_node->FirstChildElement(szNodeName);
184  if (!next || XML_SUCCESS != next->QueryBoolText(&dm_config_.random_phase))
185  {
186  LOG("<FAILED> Not found node : \'%s\' (Boolean) \n", szNodeName);
187  bRet = false;
188  }
189  sprintf(szNodeName, "FieldLength");
190  next = xml_node->FirstChildElement(szNodeName);
191  if (!next || XML_SUCCESS != next->QueryDoubleText(&dm_config_.fieldLength))
192  {
193  LOG("<FAILED> Not found node : \'%s\' (Double) \n", szNodeName);
194  bRet = false;
195  }
196  sprintf(szNodeName, "NearOfDepth");
197  next = xml_node->FirstChildElement(szNodeName);
198  if (!next || XML_SUCCESS != next->QueryDoubleText(&dm_config_.near_depthmap))
199  {
200  LOG("<FAILED> Not found node : \'%s\' (Double) \n", szNodeName);
201  bRet = false;
202  }
203  sprintf(szNodeName, "FarOfDepth");
204  next = xml_node->FirstChildElement(szNodeName);
205  if (!next || XML_SUCCESS != next->QueryDoubleText(&dm_config_.far_depthmap))
206  {
207  LOG("<FAILED> Not found node : \'%s\' (Double) \n", szNodeName);
208  bRet = false;
209  }
210 
211  initialize();
212 
213  LOG("**************************************************\n");
214  LOG(" Read Config (Depth Map) \n");
215  LOG("1) Focal Length : %.5lf ~ %.5lf\n", dm_config_.near_depthmap, dm_config_.far_depthmap);
216  LOG("2) Render Depth : %d:%d\n", dm_config_.render_depth[0], dm_config_.render_depth[dm_config_.render_depth.size() - 1]);
217  LOG("3) Number of Depth Quantization : %d\n", dm_config_.num_of_depth_quantization);
218  LOG("**************************************************\n");
219 
220  return bRet;
221 }
222 
223 bool ophDepthMap::readImage(const char* fname, IMAGE_TYPE type)
224 {
225  auto begin = CUR_TIME;
226  const int pnX = context_.pixel_number[_X];
227  const int pnY = context_.pixel_number[_Y];
228  const int N = pnX * pnY;
229  const uint ch = context_.waveNum;
230 
231  int w, h, bytesperpixel;
232  // get image information
233  bool ret = getImgSize(w, h, bytesperpixel, fname);
234  // load image
235  uchar* pSrc = loadAsImg(fname);
236 
237  if (pSrc == nullptr) {
238  LOG("<FAILED> Load image: %s\n", fname);
239  return false;
240  }
241 
242  if (type == IMAGE_TYPE::COLOR)
243  {
244  for (vector<uchar*>::iterator it = m_vecRGB.begin(); it != m_vecRGB.end(); it++)
245  delete[](*it);
246  m_vecRGB.clear();
247 
248  int nSize = ((w * bytesperpixel + 3) & ~3) * h;
249  uchar* pBuf = new uchar[nSize];
250 
251  for (int i = 0; i < ch; i++)
252  {
253  // step 1. color relocation
254  if (ch == 1) // rgb to greyscale
255  {
256  if (bytesperpixel != 1)
257  convertToFormatGray8(pSrc, pBuf, w, h, bytesperpixel);
258  else
259  memcpy(pBuf, pSrc, nSize);
260  }
261  else if (ch == bytesperpixel)
262  {
263  // [B0,G0,R0,B1,G1,R1...] -> [R0,R1...] [G0,G1...] [B0,B1...]
264  if (!separateColor(i, w, h, pSrc, pBuf))
265  {
266  LOG("<FAILED> separateColor: %d", i);
267  }
268  }
269  else
270  {
271  memcpy(pBuf, pSrc, nSize);
272  }
273 
274  uchar* pDst = new uchar[N];
275 
276  if (w != pnX || h != pnY)
277  {
278  imgScaleBilinear(pBuf, pDst, w, h, pnX, pnY);
279  }
280  else
281  {
282  memcpy(pDst, pBuf, N);
283  }
284  m_vecRGB.push_back(pDst);
285  }
286  delete[] pSrc;
287  delete[] pBuf;
288 
289  // 2019-10-14 mwnam
290  m_vecRGBImg[_X] = pnX;
291  m_vecRGBImg[_Y] = pnY;
292  }
293  else if (type == IMAGE_TYPE::DEPTH)
294  {
295  if (depth_img) delete[] depth_img;
296 
297  depth_img = new uchar[N];
298  memset(depth_img, 0, N);
299 
300  uchar* pBuf = new uchar[((w + 3) & ~3) * h];
301  convertToFormatGray8(pSrc, pBuf, w, h, bytesperpixel);
302 
303  if (w != pnX || h != pnY)
304  imgScaleBilinear(pBuf, depth_img, w, h, pnX, pnY);
305  else
306  memcpy(depth_img, pBuf, N);
307 
308  delete[] pSrc;
309  delete[] pBuf;
310  // 2019-10-14 mwnam
311  m_vecDepthImg[_X] = pnX;
312  m_vecDepthImg[_Y] = pnY;
313  }
314  LOG("Load Image(%s)\n Path: %d\nResolution: %dx%d\nBytePerPixel: %d",
315  type == IMAGE_TYPE::COLOR ? "Color" : "Depth", fname, w, h, bytesperpixel);
316 
317  return true;
318 }
319 
320 bool ophDepthMap::convertImage()
321 {
322  auto begin = CUR_TIME;
323  const int pnX = context_.pixel_number[_X];
324  const int pnY = context_.pixel_number[_Y];
325  const int N = pnX * pnY;
326  const uint ch = context_.waveNum;
327 
328  // process color image.
329  for (int i = 0; i < ch; i++)
330  {
331  uchar* pSrc = m_vecRGB[i];
332  if (m_vecRGBImg != context_.pixel_number)
333  {
334  int nOldSize = ((m_vecRGBImg[_X] + 3) & ~3) * m_vecRGBImg[_Y];
335  int nNewSize = ((pnX + 3) & ~3) * pnY;
336 
337  uchar* pOrg = new uchar[nOldSize];
338  memcpy(pOrg, pSrc, sizeof(uchar) * nOldSize);
339  delete[] pSrc;
340 
341  m_vecRGB[i] = new uchar[nNewSize];
342  imgScaleBilinear(pOrg, m_vecRGB[i], m_vecRGBImg[_X], m_vecRGBImg[_Y], pnX, pnY);
343  delete[] pOrg;
344  LOG("Resized Image: (%dx%d) to (%dx%d)", m_vecRGBImg[_X], m_vecRGBImg[_Y], pnX, pnY);
345  }
346  }
347 
348  uchar* pSrc = depth_img;
349  if (m_vecDepthImg != context_.pixel_number)
350  {
351  int nOldSize = ((m_vecDepthImg[_X] + 3) & ~3) * m_vecDepthImg[_Y];
352  int nNewSize = ((pnX + 3) & ~3) * pnY;
353 
354  uchar* pOrg = new uchar[nOldSize];
355  memcpy(pOrg, pSrc, sizeof(uchar) * nOldSize);
356  delete[] pSrc;
357 
358  depth_img = new uchar[nNewSize];
359  imgScaleBilinear(pOrg, depth_img, m_vecDepthImg[_X], m_vecDepthImg[_Y], pnX, pnY);
360  delete[] pOrg;
361  LOG("Resized Image: (%dx%d) to (%dx%d)", m_vecDepthImg[_X], m_vecDepthImg[_Y], pnX, pnY);
362  }
363 
364  m_vecDepthImg = m_vecRGBImg = context_.pixel_number;
365 
366  return true;
367 }
368 
369 bool ophDepthMap::readImageDepth(const char* source_folder, const char* img_name, const char* depth_img_name)
370 {
371  auto begin = CUR_TIME;
372  const int pnX = context_.pixel_number[_X];
373  const int pnY = context_.pixel_number[_Y];
374  const int N = pnX * pnY;
375 
376  for (size_t i = 0; i < m_vecRGB.size(); i++)
377  {
378  delete[] m_vecRGB[i];
379  }
380  m_vecRGB.clear();
381 
382  // RGB Image
383  char imgPath[FILENAME_MAX] = { 0, };
384 #ifdef _WIN64
385  sprintf(imgPath, "%s\\%s.bmp", source_folder, img_name);
386 #else
387  sprintf(imgPath, "%s/%s.bmp", source_folder, img_name);
388 #endif
389 
390  int w, h, bytesperpixel;
391  bool ret = getImgSize(w, h, bytesperpixel, imgPath);
392 
393  // RGB Image
394  oph::uchar* buf = new uchar[w * h * bytesperpixel]; // 1-Dimension left top
395  ret = loadAsImgUpSideDown(imgPath, buf);
396  if (!ret) {
397  LOG("<FAILED> Image Load: %s\n", imgPath);
398  LOG("%s : %.5lf (sec)\n", __FUNCTION__, ELAPSED_TIME(begin, CUR_TIME));
399  return false;
400  }
401  LOG(" <SUCCEEDED> Image Load: %s\n", imgPath);
402 
403  int ch = context_.waveNum;
404  uchar* img = new uchar[w * h];
405 
406  for (int i = 0; i < ch; i++)
407  {
408  if (ch == 1) // rgb img to grayscale
409  convertToFormatGray8(buf, img, w, h, bytesperpixel);
410  else if (ch == bytesperpixel) // rgb img to rgb
411  {
412  separateColor(i, w, h, buf, img);
413  }
414  else // grayscale img to rgb
415  {
416  memcpy(img, buf, sizeof(char) * w * h);
417  }
418 
419 
420  //resized image
421  uchar *rgb_img = new uchar[N];
422  memset(rgb_img, 0, sizeof(char) * N);
423 
424  if (w != pnX || h != pnY)
425  imgScaleBilinear(img, rgb_img, w, h, pnX, pnY);
426  else
427  memcpy(rgb_img, img, sizeof(char) * N);
428 
429  m_vecRGB.push_back(rgb_img);
430  }
431  delete[] buf;
432  delete[] img;
433 
434  // 2019-10-14 mwnam
435  m_vecRGBImg[_X] = pnX;
436  m_vecRGBImg[_Y] = pnY;
437 
438  // Depth Image
439  //=================================================================================
440  char dimgPath[FILENAME_MAX] = { 0, };
441 #ifdef _WIN64
442  sprintf(dimgPath, "%s\\%s.bmp", source_folder, depth_img_name);
443 #else
444  sprintf(dimgPath, "%s/%s.bmp", source_folder, depth_img_name);
445 #endif
446  ret = getImgSize(w, h, bytesperpixel, dimgPath);
447 
448  // Depth Image
449  uchar* dbuf = new uchar[w * h * bytesperpixel];
450  ret = loadAsImgUpSideDown(dimgPath, dbuf);
451  if (!ret) {
452  LOG("<FAILED> Image Load: %s\n", dimgPath);
453  LOG("%s : %.5lf (sec)\n", __FUNCTION__, ELAPSED_TIME(begin, CUR_TIME));
454  return false;
455  }
456  LOG(" <SUCCEEDED> Image Load: %s\n", dimgPath);
457 
458  // 2019-10-14 mwnam
459  m_vecDepthImg[_X] = w;
460  m_vecDepthImg[_Y] = h;
461 
462  uchar* dimg = new uchar[w * h];
463  convertToFormatGray8(dbuf, dimg, w, h, bytesperpixel);
464 
465  delete[] dbuf;
466 
467  if (depth_img) delete[] depth_img;
468 
469  depth_img = new uchar[N];
470  memset(depth_img, 0, sizeof(char) * N);
471 
472  if (w != pnX || h != pnY)
473  imgScaleBilinear(dimg, depth_img, w, h, pnX, pnY);
474  else
475  memcpy(depth_img, dimg, sizeof(char) * N);
476 
477  // 2019-10-14 mwnam
478  m_vecDepthImg[_X] = pnX;
479  m_vecDepthImg[_Y] = pnY;
480 
481  delete[] dimg;
482 
483  LOG("%s : %.5lf (sec)\n", __FUNCTION__, ELAPSED_TIME(begin, CUR_TIME));
484  return true;
485 }
486 
488 {
489  auto begin = CUR_TIME;
490  LOG("**************************************************\n");
491  LOG(" Generate Hologram \n");
492  LOG("1) Algorithm Method : Depth Map\n");
493  LOG("2) Generate Hologram with %s\n", m_mode & MODE_GPU ?
494  "GPU" :
495 #ifdef _OPENMP
496  "Multi Core CPU"
497 #else
498  "Single Core CPU"
499 #endif
500  );
501  LOG("**************************************************\n");
502 
503 
504  resetBuffer();
505  convertImage();
507  if (m_mode & MODE_GPU)
508  {
509  initGPU();
510  prepareInputdataGPU();
511  getDepthValues();
512  //if (is_ViewingWindow)
513  // transVW();
514  calcHoloGPU();
515  }
516  else
517  {
518  initCPU();
519  prepareInputdataCPU();
520  getDepthValues();
521  //if (is_ViewingWindow)
522  // transVW();
523  calcHoloCPU();
524  }
525  Real elapsed_time = ELAPSED_TIME(begin, CUR_TIME);
526  LOG("Total Elapsed Time: %lf (s)\n", elapsed_time);
527  m_nProgress = 0;
528  return elapsed_time;
529 }
530 
532 {
533  const uint pnX = context_.pixel_number[_X];
534  const uint pnY = context_.pixel_number[_Y];
535  const uint nChannel = context_.waveNum;
536  Complex<Real>* temp = new Complex<Real>[pnX * pnY];
537  for (uint ch = 0; ch < nChannel; ch++) {
538  fft2(complex_H[ch], temp, pnX, pnY, OPH_BACKWARD, true);
540  }
541  delete[] temp;
542 }
543 
544 void ophDepthMap::encoding(unsigned int ENCODE_FLAG, unsigned int SSB_PASSBAND)
545 {
546  auto begin = CUR_TIME;
547  const uint pnX = context_.pixel_number[_X];
548  const uint pnY = context_.pixel_number[_Y];
549  const uint nChannel = context_.waveNum;
550 
551  for (uint ch = 0; ch < nChannel; ch++) {
552 
555  }
556  else
557  {
558  Complex<Real>* dst = new Complex<Real>[pnX * pnY];
560  fft2(complex_H[ch], dst, pnX, pnY, OPH_BACKWARD);
562  delete[] dst;
563  }
564  }
565  auto end = CUR_TIME;
566  LOG("Elapsed Time: %lf(s)\n", ELAPSED_TIME(begin, end));
567 }
568 
569 
570 void ophDepthMap::getDepthValues()
571 {
572  auto begin = CUR_TIME;
573  if (dm_config_.num_of_depth > 1)
574  {
575  dstep = (dm_config_.far_depthmap - dm_config_.near_depthmap) / (dm_config_.num_of_depth - 1);
576  Real val = dm_config_.near_depthmap;
577  while (val <= dm_config_.far_depthmap)
578  {
579  dlevel.push_back(val);
580  val += dstep;
581  }
582  }
583  else {
584 
585  dstep = (dm_config_.far_depthmap + dm_config_.near_depthmap) / 2;
586  dlevel.push_back(dm_config_.near_depthmap);
587  }
588 
589 
590  if (dm_config_.change_depth_quantization == 1)
591  {
592  bool is_CPU = m_mode & MODE_GPU ? false : true;
593  if (is_CPU)
594  changeDepthQuanCPU();
595  else
596  changeDepthQuanGPU();
597  }
598  LOG("%s : %.5lf (sec)\n", __FUNCTION__, ELAPSED_TIME(begin, CUR_TIME));
599 }
600 
601 void ophDepthMap::transVW()
602 {
603  Real val;
604  dlevel_transform.clear();
605  for (size_t p = 0; p < dlevel.size(); p++)
606  {
607  val = -dm_config_.fieldLength * dlevel[p] / (dlevel[p] - dm_config_.fieldLength);
608  dlevel_transform.push_back(val);
609  }
610 }
611 
612 void ophDepthMap::initCPU()
613 {
614  const uint pnX = context_.pixel_number[_X];
615  const uint pnY = context_.pixel_number[_Y];
616  const uint N = pnX * pnY;
617  const uint nChannel = context_.waveNum;
618 
619  dlevel.clear();
620 
621  for (vector<Real *>::iterator it = m_vecImgSrc.begin(); it != m_vecImgSrc.end(); it++)
622  {
623  delete[](*it);
624  }
625  m_vecImgSrc.clear();
626  for (vector<int *>::iterator it = m_vecAlphaMap.begin(); it != m_vecAlphaMap.end(); it++)
627  {
628  delete[](*it);
629  }
630  m_vecAlphaMap.clear();
631 
632  for (uint ch = 0; ch < nChannel; ch++)
633  {
634  Real *img_src = new Real[N];
635  int *alpha_map = new int[N];
636 
637  m_vecImgSrc.push_back(img_src);
638  m_vecAlphaMap.push_back(alpha_map);
639  }
640 
641  if (dmap_src) delete[] dmap_src;
642  dmap_src = new Real[N];
643 
644  if (depth_index) delete[] depth_index;
645  depth_index = new uint[N];
646 
647  if (dmap) delete[] dmap;
648  dmap = new Real[N];
649 
650  fftw_cleanup();
651 }
652 
653 bool ophDepthMap::prepareInputdataCPU()
654 {
655  auto begin = CUR_TIME;
656  const long long int N = context_.pixel_number[_X] * context_.pixel_number[_Y];
657  const uint nChannel = context_.waveNum;
658 
659  memset(depth_index, 0, sizeof(uint) * N);
660 
661  if (depth_img == nullptr) // not used depth
662  {
663  depth_img = new uchar[N];
664  memset(depth_img, 0, N);
665  }
666 
667  Real gapDepth = dm_config_.far_depthmap - dm_config_.near_depthmap;
668  Real nearDepth = dm_config_.near_depthmap;
669 
670  for (uint ch = 0; ch < nChannel; ch++)
671  {
672 #ifdef _OPENMP
673 #pragma omp parallel for firstprivate(gapDepth, nearDepth)
674 #endif
675  for (long long int k = 0; k < N; k++)
676  {
677  m_vecImgSrc[ch][k] = Real(m_vecRGB[ch][k]) / 255.0; // RGB IMG
678  m_vecAlphaMap[ch][k] = (m_vecRGB[ch][k] > 0 ? 1 : 0); // RGB IMG
679 
680  // once
681  if (ch == 0)
682  {
683  dmap_src[k] = Real(depth_img[k]) / 255.0; // DEPTH IMG
684  dmap[k] = (1 - dmap_src[k]) * gapDepth + nearDepth;
685  if (dm_config_.change_depth_quantization == 0) {
686  depth_index[k] = dm_config_.default_depth_quantization - depth_img[k];
687  }
688  }
689  }
690  }
691 
692  LOG("%s : %.5lf (sec)\n", __FUNCTION__, ELAPSED_TIME(begin, CUR_TIME));
693  return true;
694 }
695 
696 void ophDepthMap::changeDepthQuanCPU()
697 {
698  auto begin = CUR_TIME;
699  const long long int N = context_.pixel_number[_X] * context_.pixel_number[_Y];
700 
701  uint num_depth = dm_config_.num_of_depth;
702  Real near_depth = dm_config_.near_depthmap;
703  Real far_depth = dm_config_.far_depthmap;
704 
705  double nearv = dlevel[0];
706  double half_step = dstep / 2.0;
707  depth_fill.clear();
708  depth_fill.resize(dm_config_.render_depth.size() + 1, 0);
709  Real locDstep = dstep;
710 
711 #ifdef _OPENMP
712 #pragma omp parallel for firstprivate(nearv, half_step, locDstep)
713 #endif
714  for (long long int i = 0; i < N; i++)
715  {
716  int idx = int(((dmap[i] - nearv) + half_step) / locDstep);
717  depth_index[i] = idx + 1;
718  depth_fill[idx + 1] = 1;
719  }
720 
721  LOG("%s : %.5lf (sec)\n", __FUNCTION__, ELAPSED_TIME(begin, CUR_TIME));
722 }
723 
724 void ophDepthMap::calcHoloCPU()
725 {
726  auto begin = CUR_TIME;
727 
728  const uint pnX = context_.pixel_number[_X];
729  const uint pnY = context_.pixel_number[_Y];
730  const long long int N = pnX * pnY;
731  const uint nChannel = context_.waveNum;
732 
733  size_t depth_sz = dm_config_.render_depth.size();
734 
735  const bool bRandomPhase = GetRandomPhase();
736  Complex<Real> *input = new Complex<Real>[N];
737 
739 
740  for (uint ch = 0; ch < nChannel; ch++)
741  {
742  Real lambda = context_.wave_length[ch];
743  Real k = context_.k = (2 * M_PI / lambda);
744  Real *img_src = m_vecImgSrc[ch];
745  int *alpha_map = m_vecAlphaMap[ch];
746 
747  for (size_t i = 0; i < depth_sz; i++)
748  {
749  int dtr = dm_config_.render_depth[i];
750  if (depth_fill[dtr])
751  {
752  memset(input, 0, sizeof(Complex<Real>) * N);
753  Real temp_depth = (is_ViewingWindow) ? dlevel_transform[dtr - 1] : dlevel[dtr - 1];
754 
755  Complex<Real> rand_phase_val;
756  GetRandomPhaseValue(rand_phase_val, bRandomPhase);
757 
758  Complex<Real> carrier_phase_delay(0, k * -temp_depth);
759  carrier_phase_delay.exp();
760 #ifdef _OPENMP
761 #pragma omp parallel for firstprivate(dtr, rand_phase_val, carrier_phase_delay)
762 #endif
763  for (long long int j = 0; j < N; j++)
764  {
765  input[j][_RE] = img_src[j] * alpha_map[j] * ((int)depth_index[j] == dtr ? 1.0 : 0.0);
766  input[j] *= rand_phase_val * carrier_phase_delay;
767  }
768 
769  fft2(input, input, pnX, pnY, OPH_FORWARD, false);
770  AngularSpectrumMethod(input, complex_H[ch], lambda, temp_depth);
771 
772  }
773  m_nProgress = (int)((Real)(ch * depth_sz + i) * 100 / (depth_sz * nChannel));
774  }
775  //fft2(complex_H[ch], complex_H[ch], pnX, pnY, OPH_BACKWARD, true);
776  }
777  delete[] input;
778  fftFree();
779  LOG("%s : %.5lf (sec)\n", __FUNCTION__, ELAPSED_TIME(begin, CUR_TIME));
780 }
781 
783 {
784  ophGen::ophFree();
785  if (depth_img) {
786  delete[] depth_img;
787  depth_img = nullptr;
788  }
789 
790 
791  for (vector<uchar *>::iterator it = m_vecRGB.begin(); it != m_vecRGB.end(); it++)
792  {
793  delete[](*it);
794  }
795  m_vecRGB.clear();
796 }
797 
799 {
800  if (context_.pixel_number != resolution) {
801  ophGen::setResolution(resolution);
802  initCPU();
803  initGPU();
804  }
805 }
806 
808 {
810 }
bytesperpixel
Definition: Openholo.cpp:431
#define OPH_BACKWARD
Definition: define.h:67
ENCODE_FLAG
Definition: ophGen.h:84
Real k
Definition: Openholo.h:103
void encodeSideBand(unsigned int passband)
Encode the CGH according to a passband parameter.
Definition: ophGen.cpp:1607
void setViewingWindow(bool is_ViewingWindow)
Set the value of a variable is_ViewingWindow(true or false)
Definition: ophDepthMap.cpp:86
void setResolution(ivec2 resolution)
Function for setting buffer size.
Definition: ophGen.cpp:1806
void fftFree(void)
Resource release method.
Definition: Openholo.cpp:677
Real fieldLength
fieldLength variable for viewing window.
Definition: ophGen.h:605
void AngularSpectrumMethod(Complex< Real > *src, Complex< Real > *dst, Real lambda, Real distance)
Angular spectrum propagation method.
Definition: ophGen.cpp:583
Real * wave_length
Definition: Openholo.h:106
uint num_of_depth
Definition: ophGen.h:615
void GetRandomPhaseValue(Complex< Real > &rand_phase_val, bool rand_phase)
Assign random phase value if random_phase == 1.
Definition: ophGen.cpp:1783
bool readImageDepth(const char *source_folder, const char *img_prefix, const char *depth_img_prefix)
Read image and depth map.
SSB_PASSBAND
Definition: ophGen.h:295
unsigned char uchar
Definition: typedef.h:64
#define MODE_GPU
Definition: define.h:156
Real ** m_lpEncoded
buffer to encoded.
Definition: ophGen.h:338
float Real
Definition: typedef.h:55
void initialize(void)
Initialize variables for Hologram complex field, encoded data, normalized data.
Definition: ophGen.cpp:146
#define CUR_TIME
Definition: function.h:58
bool checkExtension(const char *fname, const char *ext)
Functions for extension checking.
Definition: Openholo.cpp:86
#define OPH_ESTIMATE
Definition: define.h:76
structure for 2-dimensional integer vector and its arithmetic.
Definition: ivec.h:66
bool GetRandomPhase()
Function for getting the random phase.
Definition: ophGen.h:528
const XMLNode * FirstChild() const
Get the first child node, or null if none exists.
Definition: tinyxml2.h:761
ophDepthMap()
Constructor.
Definition: ophDepthMap.cpp:58
void normalize()
#define _Y
Definition: define.h:96
virtual ~ophDepthMap()
Destructor.
Definition: ophDepthMap.cpp:82
void normalize(void)
Normalization function to save as image file after hologram creation.
Definition: ophGen.cpp:654
ivec2 m_vecEncodeSize
Encoded hologram size, varied from encoding type.
Definition: ophGen.h:330
#define _X
Definition: define.h:92
unsigned int m_mode
Definition: ophGen.h:350
Real near_depthmap
near value of depth in object
Definition: ophGen.h:607
bool readConfig(const char *fname)
Read parameters from a config file. (*.xml)
Definition: ophDepthMap.cpp:91
bool separateColor(int idx, int width, int height, uchar *src, uchar *dst)
Function for generate each grayscale image from RGB image.
Definition: Openholo.cpp:119
void imgScaleBilinear(uchar *src, uchar *dst, int w, int h, int neww, int newh, int channels=1)
Function for change image size.
Definition: Openholo.cpp:437
bool getImgSize(int &w, int &h, int &bytesperpixel, const char *fname)
Function for getting the image size.
Definition: Openholo.cpp:402
#define _RE
Definition: complex.h:55
void fft2(ivec2 n, Complex< Real > *in, int sign=OPH_FORWARD, uint flag=OPH_ESTIMATE)
Functions for performing fftw 2-dimension operations inside Openholo.
Definition: Openholo.cpp:559
void convertToFormatGray8(uchar *src, uchar *dst, int w, int h, int bytesperpixel)
Function for convert image format to gray8.
Definition: Openholo.cpp:511
Real far_depthmap
far value of depth in object
Definition: ophGen.h:609
void setResolution(ivec2 resolution)
#define ELAPSED_TIME(x, y)
Definition: function.h:59
void fftInit2D(ivec2 size, int sign, unsigned int flag)
initialize method for 2D FFT
Definition: Openholo.cpp:660
uint waveNum
Definition: Openholo.h:105
ivec2 pixel_number
Definition: Openholo.h:99
bool readConfig(const char *fname)
load to configuration file.
Definition: ophGen.cpp:221
XMLError LoadFile(const char *filename)
Definition: tinyxml2.cpp:2150
void ophFree(void)
Pure virtual function for override in child classes.
virtual uchar * loadAsImg(const char *fname)
Function for loading image files.
Definition: Openholo.cpp:321
bool change_depth_quantization
if true, change the depth quantization from the default value.
Definition: ophGen.h:619
Real generateHologram(void)
Generate a hologram, main funtion. When the calculation is finished, the angular spectrum is performe...
void encoding()
Definition: ophGen.cpp:962
void resetBuffer()
reset buffer
Definition: ophGen.cpp:801
w
Definition: Openholo.cpp:429
bool readImage(const char *fname, IMAGE_TYPE type=COLOR)
Read image and depth map.
OphConfig context_
Definition: Openholo.h:486
#define OPH_FORWARD
Definition: define.h:66
Complex< Real > ** complex_H
Definition: Openholo.h:490
vector< int > render_depth
Used when only few specific depth levels are rendered, usually for test purpose.
Definition: ophGen.h:617
uint default_depth_quantization
default value of the depth quantization - 256
Definition: ophGen.h:621
bool loadAsImgUpSideDown(const char *fname, uchar *dst)
Function for loading image files | Output image data upside down.
Definition: Openholo.cpp:353
const XMLElement * FirstChildElement(const char *name=0) const
Definition: tinyxml2.cpp:940
unsigned int uint
Definition: typedef.h:62
#define M_PI
Definition: define.h:52
h
Definition: Openholo.cpp:430
Definition: ophGen.h:76
virtual void ophFree(void)
Pure virtual function for override in child classes.
Definition: ophGen.cpp:2072