| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 85190bd commit e49c92b
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,193 @@ | |||
| 1 | + // This file is part of VisionCPP, a lightweight C++ template library | ||
| 2 | + // for computer vision and image processing. | ||
| 3 | + // | ||
| 4 | + // Copyright (C) 2016 Codeplay Software Limited. All Rights Reserved. | ||
| 5 | + // | ||
| 6 | + // Contact: visioncpp@codeplay.com | ||
| 7 | + // | ||
| 8 | + // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 9 | + // you may not use this file except in compliance with the License. | ||
| 10 | + // You may obtain a copy of the License at | ||
| 11 | + // | ||
| 12 | + // http://www.apache.org/licenses/LICENSE-2.0 | ||
| 13 | + // | ||
| 14 | + // Unless required by applicable law or agreed to in writing, software | ||
| 15 | + // distributed under the License is distributed on an "AS IS" BASIS, | ||
| 16 | + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 17 | + // See the License for the specific language governing permissions and | ||
| 18 | + // limitations under the License. | ||
| 19 | + | ||
| 20 | + /// \file depth_map_from_2_images.cpp | ||
| 21 | + /// | ||
| 22 | + /// ---------Example--------- | ||
| 23 | + /// Depth Map From 2 images | ||
| 24 | + /// | ||
| 25 | + /// \brief This example implements a Depth Map reconstruction from two images | ||
| 26 | + /// using the block match algorithm | ||
| 27 | + /// \param blockSize - this parameter defines the size of the block to be | ||
| 28 | + /// searched | ||
| 29 | + /// \param maxDisp - this parameter defines the maximum disparity between | ||
| 30 | + /// pixels. It means the max number of pixels it will be used to search for the | ||
| 31 | + /// best match. | ||
| 32 | + | ||
| 33 | + // include OpenCV for camera display | ||
| 34 | + #include <opencv2/opencv.hpp> | ||
| 35 | + | ||
| 36 | + // include VisionCpp | ||
| 37 | + #include <visioncpp.hpp> | ||
| 38 | + | ||
| 39 | + // include limits to define infinity | ||
| 40 | + #include <limits> | ||
| 41 | + | ||
| 42 | + // Tunable parameters for the algorithm | ||
| 43 | + constexpr int blockSize = 11; | ||
| 44 | + constexpr int maxDisp = 25; | ||
| 45 | + | ||
| 46 | + constexpr int halfBlock = blockSize / 2; | ||
| 47 | + | ||
| 48 | + // Stereo block matching algorithm for depth map reconstruction | ||
| 49 | + struct Stereo_BMA { | ||
| 50 | + // function that computers the sum of absolute difference of two blocks | ||
| 51 | + float SAD(const float im1[blockSize * blockSize], | ||
| 52 | + const float im2[blockSize * blockSize]) { | ||
| 53 | + float r = 0; | ||
| 54 | + for (size_t i = 0; i < blockSize * blockSize; i++) { | ||
| 55 | + r += cl::sycl::fabs(im1[i] - im2[i]); | ||
| 56 | + } | ||
| 57 | + return r; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + // Function to get block of size blockSize frin (c,r) pixel | ||
| 61 | + template <typename T> | ||
| 62 | + void getBlock(const T& I, const int& c, const int& r, const int& layer, | ||
| 63 | + float block[blockSize * blockSize]) { | ||
| 64 | + int cnt = 0; | ||
| 65 | + for (int i2 = -halfBlock; i2 <= halfBlock; i2++) { | ||
| 66 | + for (int j2 = -halfBlock; j2 <= halfBlock; j2++) { | ||
| 67 | + block[cnt++] = I.at(c + i2, r + j2)[layer]; | ||
| 68 | + } | ||
| 69 | + } | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + // function that computes the depth map | ||
| 73 | + template <typename T> | ||
| 74 | + visioncpp::pixel::U8C1 operator()(const T& I) { | ||
| 75 | + // get block from left image | ||
| 76 | + float block_l[blockSize * blockSize]; | ||
| 77 | + getBlock(I, I.I_c, I.I_r, 0, block_l); | ||
| 78 | + | ||
| 79 | + // start with best sum of absolute difference equals to infinity | ||
| 80 | + float bestSAD = std::numeric_limits<float>::infinity(); | ||
| 81 | + int bestJ = I.I_c; | ||
| 82 | + | ||
| 83 | + // for loop to find best match | ||
| 84 | + float block_r[blockSize * blockSize]; | ||
| 85 | + for (int m = 0; m < maxDisp; m++) { | ||
| 86 | + // get block from right image | ||
| 87 | + getBlock(I, I.I_c - m, I.I_r, 1, block_r); | ||
| 88 | + | ||
| 89 | + // sum of absolute difference | ||
| 90 | + float temp = SAD(block_l, block_r); | ||
| 91 | + | ||
| 92 | + // store the smallest SAD | ||
| 93 | + if (temp < bestSAD) { | ||
| 94 | + bestSAD = temp; | ||
| 95 | + bestJ = I.I_c - m; | ||
| 96 | + } | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + // Compute disparity value | ||
| 100 | + return visioncpp::pixel::U8C1(I.I_c - bestJ); | ||
| 101 | + } | ||
| 102 | + }; | ||
| 103 | + | ||
| 104 | + // main program | ||
| 105 | + int main(int argc, char** argv) { | ||
| 106 | + // load images left and write in gray scale | ||
| 107 | + cv::Mat input_l = | ||
| 108 | + cv::imread("../data/tsukuba_l.png", CV_LOAD_IMAGE_GRAYSCALE); | ||
| 109 | + cv::Mat input_r = | ||
| 110 | + cv::imread("../data/tsukuba_r.png", CV_LOAD_IMAGE_GRAYSCALE); | ||
| 111 | + | ||
| 112 | + if (!input_l.data || !input_r.data) { // check if we succeeded | ||
| 113 | + std::cout << "Loading image failed." << std::endl; | ||
| 114 | + return -1; | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + // selecting device | ||
| 118 | + auto dev = visioncpp::make_device<visioncpp::backend::sycl, | ||
| 119 | + visioncpp::device::cpu>(); | ||
| 120 | + | ||
| 121 | + // defining the image size constants | ||
| 122 | + constexpr size_t COLS = 640; | ||
| 123 | + constexpr size_t ROWS = 480; | ||
| 124 | + | ||
| 125 | + // resize images | ||
| 126 | + cv::resize(input_l, input_l, cv::Size(COLS, ROWS), 0, 0, cv::INTER_CUBIC); | ||
| 127 | + cv::resize(input_r, input_r, cv::Size(COLS, ROWS), 0, 0, cv::INTER_CUBIC); | ||
| 128 | + | ||
| 129 | + // Shared Memory variable | ||
| 130 | + constexpr size_t SM = 16; | ||
| 131 | + | ||
| 132 | + // creating a pointer to store the results | ||
| 133 | + std::shared_ptr<unsigned char> output( | ||
| 134 | + new unsigned char[COLS * ROWS], | ||
| 135 | + [](unsigned char* dataMem) { delete[] dataMem; }); | ||
| 136 | + | ||
| 137 | + // init output image from OpenCV for displaying results | ||
| 138 | + cv::Mat outputImage(ROWS, COLS, CV_8UC1, output.get()); | ||
| 139 | + | ||
| 140 | + // the node which gets the input data from OpenCV | ||
| 141 | + { | ||
| 142 | + // store the left image in the terminal node | ||
| 143 | + auto in_l = | ||
| 144 | + visioncpp::terminal<visioncpp::pixel::U8C1, COLS, ROWS, | ||
| 145 | + visioncpp::memory_type::Buffer2D>(input_l.data); | ||
| 146 | + | ||
| 147 | + // store the right image in the terminal node | ||
| 148 | + auto in_r = | ||
| 149 | + visioncpp::terminal<visioncpp::pixel::U8C1, COLS, ROWS, | ||
| 150 | + visioncpp::memory_type::Buffer2D>(input_r.data); | ||
| 151 | + | ||
| 152 | + // the node which gets the output data | ||
| 153 | + auto out = | ||
| 154 | + visioncpp::terminal<visioncpp::pixel::U8C1, COLS, ROWS, | ||
| 155 | + visioncpp::memory_type::Buffer2D>(output.get()); | ||
| 156 | + | ||
| 157 | + // convert images to float | ||
| 158 | + auto fgrey_l = visioncpp::point_operation<visioncpp::OP_U8C1ToFloat>(in_l); | ||
| 159 | + auto fgrey_r = visioncpp::point_operation<visioncpp::OP_U8C1ToFloat>(in_r); | ||
| 160 | + | ||
| 161 | + // merge images | ||
| 162 | + auto merge = | ||
| 163 | + visioncpp::point_operation<visioncpp::OP_Merge2Chns>(fgrey_l, fgrey_r); | ||
| 164 | + | ||
| 165 | + // compute depth map | ||
| 166 | + auto depth = visioncpp::neighbour_operation< | ||
| 167 | + Stereo_BMA, halfBlock, halfBlock + maxDisp, halfBlock, halfBlock>( | ||
| 168 | + merge); | ||
| 169 | + | ||
| 170 | + // convert to unsigned char for displaying purposes | ||
| 171 | + // scale threhold to display | ||
| 172 | + auto scale_node = visioncpp::terminal<float, visioncpp::memory_type::Const>( | ||
| 173 | + static_cast<float>(8.0f)); | ||
| 174 | + auto display = | ||
| 175 | + visioncpp::point_operation<visioncpp::OP_Scale>(depth, scale_node); | ||
| 176 | + | ||
| 177 | + // assign to the output | ||
| 178 | + auto exec = visioncpp::assign(out, display); | ||
| 179 | + | ||
| 180 | + // execute expression tree | ||
| 181 | + visioncpp::execute<visioncpp::policy::Fuse, SM, SM, SM, SM>(exec, dev); | ||
| 182 | + } | ||
| 183 | + | ||
| 184 | + // Display results | ||
| 185 | + cv::imshow("Image left", input_l); | ||
| 186 | + cv::imshow("Image right", input_r); | ||
| 187 | + cv::imshow("Depth Map", outputImage); | ||
| 188 | + | ||
| 189 | + // wait key to be pressed to finalize | ||
| 190 | + cv::waitKey(0); | ||
| 191 | + | ||
| 192 | + return 0; | ||
| 193 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments