├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── doc ├── 7bit-binary-reflected.png ├── 7bit-large-gap.png └── min_max_gaps.png └── src ├── CMakeLists.txt ├── LargeGapGrayCode.cpp ├── LargeGapGrayCode.h ├── examples.cpp └── imagePatterns.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | *~ 31 | build/ 32 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | project (LargeGap-GrayCode) 3 | 4 | add_subdirectory(src) 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Kent Hansen and Jeppe Pedersen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # What is this? 2 | This project constructs Large-Gap Gray codes (LGGC), which is a special type of Gray code with the additional property that it contains large bit runs along the tracks. LGGC was introduced by [1], where the mathematical derivation of the codes is described. More description of LGGC can be found in [2, section 5.2]. 3 | 4 | A comparison of *Binary Reflected Gray code* and *Large-Gap Gray code* is shown below: 5 | 6 | ##### 7-bit Binary Reflected Gray code 7 | ![7-bit Binary Reflected Gray code](doc/7bit-binary-reflected.png "7-bit Binary Reflected Gray code") 8 | 9 | ##### 7-bit Large-Gap Gray code 10 | ![7-bit Large-Gap Gray code](doc/7bit-large-gap.png "7-bit Large-Gap Gray code") 11 | 12 | They are both cyclic Gray codes with one bit changing between two successive values, however the LGGC is constructed in a way to obtain higher minimum run lengths and lower maximum run lengths along the bit tracks. 13 | 14 | ##### Comparison of min/max gaps 15 | ![Comparison of min/max gaps for BRGC and LGGC for various bit widths](doc/min_max_gaps.png) 16 | 17 | # Utilization in structured light application 18 | The codes have been used in a structured light application [2]. The LGGC pattern was projected to a scene and captured by cameras. Afterwards, the pattern was decoded and used for reconstruction of 3D information. 19 | 20 | In comparison to traditional BRGC, the properties of LGGC makes it more robust towards defocusing, subsurface scattering and interreflections, which are common challenges in scenes with active illumination. For more information, see [2] and [3]. 21 | 22 | # How to use it 23 | The project is tested on Linux using CMake and make: 24 | ``` 25 | mkdir build 26 | cd build 27 | cmake .. 28 | make 29 | ``` 30 | 31 | Two applications are provided, which can be executed by running; 32 | ``` 33 | ./src/examples 34 | ./src/imagePatterns 35 | ``` 36 | 37 | # References 38 | * [1] Luis Goddyn, George M Lawrence, and Evi Nemeth. Gray codes with optimized run lengths. Utilitas Mathematica, 34:179–192, 1988 39 | * [2] Pedersen, J. and Hansen, K. (2014). Robot Mountable Embedded Vision Platform for Multimodal Point Cloud Acquisition in Industrial Applications. Master Thesis, University of Southern Denmark. [Online version](http://caro.sdu.dk/index.php/publications/master-theses?view=publication&task=show&id=2048) 40 | * [3] Hansen, K.; Pedersen, J.; Sølund, T.; Aanæs, H.; Kraft, D., "A Structured Light Scanner for Hyper Flexible Industrial Automation", 3D Vision - 3DV 2014 41 | -------------------------------------------------------------------------------- /doc/7bit-binary-reflected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tckent/largegap-graycode/1eb6de3a450e1d1cdb493efc5394324df079288c/doc/7bit-binary-reflected.png -------------------------------------------------------------------------------- /doc/7bit-large-gap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tckent/largegap-graycode/1eb6de3a450e1d1cdb493efc5394324df079288c/doc/7bit-large-gap.png -------------------------------------------------------------------------------- /doc/min_max_gaps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tckent/largegap-graycode/1eb6de3a450e1d1cdb493efc5394324df079288c/doc/min_max_gaps.png -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | SET(CMAKE_CXX_FLAGS "-std=c++0x") 4 | 5 | add_executable (examples examples.cpp LargeGapGrayCode.cpp) 6 | 7 | find_package(OpenCV QUIET) 8 | if(OpenCV_FOUND) 9 | add_executable(imagePatterns imagePatterns.cpp LargeGapGrayCode.cpp) 10 | target_link_libraries(imagePatterns ${OpenCV_LIBS}) 11 | endif() 12 | 13 | -------------------------------------------------------------------------------- /src/LargeGapGrayCode.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file LargeGapGrayCode.cpp 3 | * @author Kent Hansen 4 | * @date 8 Jan 2015 5 | * @brief File for constructing Large-Gap Gray codes (LGGC) 6 | * 7 | * LGGC is a special type of Gray code with the additional 8 | * property that it contains large run lengths. 9 | * 10 | * For more information about LGGC construction, see: 11 | * http://www.github.com/tckent/largegap-graycode 12 | */ 13 | 14 | #include "LargeGapGrayCode.h" 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | const int maxBitWidth = 20; 21 | 22 | LargeGapGrayCode::LargeGapGrayCode() { 23 | m_transitionSequences.resize(maxBitWidth); 24 | m_creationMethod.resize(maxBitWidth); 25 | 26 | m_transitionSequences[0] = {0, 0}; 27 | m_creationMethod[0] = "by hand"; 28 | 29 | m_transitionSequences[1] = {0, 1, 0, 1}; 30 | m_creationMethod[1] = "by hand"; 31 | 32 | m_transitionSequences[2] = {0, 1, 0, 2, 0, 1, 0, 2}; 33 | m_creationMethod[2] = "by hand"; 34 | 35 | m_transitionSequences[3] = {0, 1, 2, 3, 2, 1, 0, 2, 0, 3, 0, 1, 3, 2, 3, 1}; 36 | m_creationMethod[3] = "by hand"; 37 | 38 | m_transitionSequences[5] = {0, 1, 2, 3, 4, 5, 0, 2, 4, 1, 3, 2, 0, 5, 4, 2, 3, 1, 4, 0, 2, 5, 3 ,4, 2, 1, 0, 4, 3 ,5 ,2, 4, 0, 1, 2, 3, 4, 5, 0, 2, 4, 1, 3, 2, 0, 5, 4, 2, 3, 1, 4, 0, 2, 5, 3 ,4, 2, 1, 0, 4, 3 ,5 ,2, 4}; 39 | m_creationMethod[5] = "backtrack"; 40 | 41 | createCodeFromTheorem2(2, 2, 1, 1, 1); 42 | createCodeFromTheorem1(5, 2, 3, 1); 43 | createCodeFromTheorem1(6, 2, 3, 1); 44 | createCodeFromTheorem1(7, 2, 3, 1); 45 | createCodeFromTheorem1(5, 5, 17, 15); 46 | createCodeFromTheorem1(9, 2, 3, 1); 47 | createCodeFromTheorem1(7, 5, 17, 15); 48 | createCodeFromTheorem1(8, 5, 19, 13); 49 | createCodeFromTheorem1(7, 7, 65, 63); 50 | createCodeFromTheorem1(10, 5, 21, 11); 51 | createCodeFromTheorem1(11, 5, 21, 11); 52 | createCodeFromTheorem1(10, 7, 73, 55); 53 | createCodeFromTheorem1(11, 7, 75, 53); 54 | createCodeFromTheorem1(14, 5, 23, 9); 55 | createCodeFromTheorem1(10, 10, 513, 511); 56 | } 57 | 58 | LargeGapGrayCode::~LargeGapGrayCode() { 59 | } 60 | 61 | 62 | std::vector LargeGapGrayCode::getTransitionSequence(int bitWidth) 63 | { 64 | if(bitWidth <= maxBitWidth) { 65 | return m_transitionSequences[bitWidth-1]; 66 | } 67 | else { 68 | std::vector empty; 69 | return empty; 70 | } 71 | } 72 | 73 | std::vector > LargeGapGrayCode::getBinaryCode(int bitWidth) 74 | { 75 | std::vector > binaryCode; 76 | 77 | std::vector ts = getTransitionSequence(bitWidth); 78 | std::bitset<20> bs(0); 79 | 80 | for(int i = 0; i < pow(2, bitWidth); i++) 81 | { 82 | binaryCode.push_back(bs); 83 | bs.flip(ts[i]); 84 | } 85 | 86 | return binaryCode; 87 | } 88 | 89 | 90 | void LargeGapGrayCode::printAllStatistics() 91 | { 92 | printStatisticsHeader(); 93 | for(int i = 3; i <= maxBitWidth; ++i) { 94 | printStatistics(i); 95 | } 96 | } 97 | 98 | 99 | void LargeGapGrayCode::printStatisticsHeader() 100 | { 101 | std::cout << std::setw(5) << "n" 102 | << std::setw(12) << "Method" 103 | << std::setw(12) << "MinGap" 104 | << std::setw(12) << "MaxGap" 105 | << std::setw(12) << "MinCount" 106 | << std::setw(12) << "MaxCount" 107 | << std::setw(14) << "GapVariance" << std::endl; 108 | std::cout << "------------------------------------------------------------------------------------" << std::endl; 109 | } 110 | 111 | 112 | void LargeGapGrayCode::printStatistics(int bitWidth) 113 | { 114 | std::map runLengths = computeRunLengths(bitWidth); 115 | int minGap, minCount, maxGap, maxCount; 116 | computeMinGap(runLengths, minGap, minCount); 117 | computeMaxGap(runLengths, maxGap, maxCount); 118 | double gapVariance = computeGapVariance(runLengths); 119 | std::cout << std::setw(5) << bitWidth 120 | << std::setw(12) << m_creationMethod[bitWidth-1] 121 | << std::setw(12) << minGap 122 | << std::setw(12) << maxGap 123 | << std::setw(12) << minCount 124 | << std::setw(12) << maxCount 125 | << std::setw(14) << gapVariance << std::endl; 126 | } 127 | 128 | 129 | void LargeGapGrayCode::createCodeFromTheorem1(int n, int m, int s, int t) 130 | { 131 | if(n >= m && m >= 1 && isOddPositive(s) && isOddPositive(t) && (s+t) == pow(2,m) && (n+m <= maxBitWidth)) { 132 | std::vector P = createPVector(s, t); 133 | std::vector Z = multiCopyVector(P, pow(2, n)); 134 | std::vector t = createTransitionSequenceTheorem1(n, m, Z); 135 | m_transitionSequences[n+m-1] = t; 136 | std::stringstream ss; 137 | ss << "(" << n << " + " << m << ")"; 138 | m_creationMethod[n+m-1] = ss.str(); 139 | } 140 | else { 141 | std::cout << "Constraints for Theorem 1 are not satisfied." << std::endl; 142 | } 143 | } 144 | 145 | 146 | void LargeGapGrayCode::createCodeFromTheorem2(int n, int m, int r, int s, int t) 147 | { 148 | if(n >= m && m >= r && r >= 1 && isOddPositive(s) && isOddPositive(t) && (s+t) == pow(2,r) && (n+m+r <= maxBitWidth)) { 149 | std::vector P = createPVector(s, t); 150 | std::vector Q = multiCopyVector(P, pow(2, n)); 151 | replaceLastBWithC(Q); 152 | std::vector Z = multiCopyVector(Q, pow(2, m)); 153 | std::vector t = createTransitionSequenceTheorem2(n, m, r, Z); 154 | m_transitionSequences[n+m+r-1] = t; 155 | std::stringstream ss; 156 | ss << "(" << n << " + " << m << " + " << r << ")"; 157 | m_creationMethod[n+m+r-1] = ss.str(); 158 | } 159 | else { 160 | std::cout << "Constraints for Theorem 2 are not satisfied." << std::endl; 161 | } 162 | } 163 | 164 | 165 | std::map LargeGapGrayCode::computeRunLengths(int bitWidth) 166 | { 167 | std::vector t = m_transitionSequences[bitWidth-1]; 168 | std::vector transitionLastSeen(bitWidth, -1); 169 | 170 | std::map numRunLengths; 171 | 172 | for(int runThrough = 1; runThrough <= 2; ++runThrough) { 173 | for(int i = 0; i < t.size(); ++i) { 174 | if(transitionLastSeen[t[i]] == -1) { 175 | transitionLastSeen[t[i]] = i; 176 | } 177 | else { 178 | int runLength = runThrough*t.size()+i-transitionLastSeen[t[i]]; 179 | transitionLastSeen[t[i]] = runThrough*t.size()+i; 180 | 181 | if(runThrough == 2) { 182 | std::map::iterator it = numRunLengths.find(runLength); 183 | if (it != numRunLengths.end()) { 184 | it->second += 1; 185 | } 186 | else { 187 | numRunLengths.insert(std::make_pair(runLength, 1)); 188 | } 189 | } 190 | } 191 | } 192 | } 193 | 194 | return numRunLengths; 195 | } 196 | 197 | 198 | void LargeGapGrayCode::computeMinGap(const std::map& runLengths, int& minGap, int& minCount) 199 | { 200 | minGap = 999; 201 | 202 | for(std::map::const_iterator it = runLengths.begin(); it != runLengths.end(); ++it) { 203 | if(it->first < minGap) { 204 | minGap = it->first; 205 | minCount = it->second; 206 | } 207 | } 208 | } 209 | 210 | 211 | void LargeGapGrayCode::computeMaxGap(const std::map& runLengths, int& maxGap, int& maxCount) 212 | { 213 | maxGap = 0; 214 | 215 | for(std::map::const_iterator it = runLengths.begin(); it != runLengths.end(); ++it) { 216 | if(it->first > maxGap) { 217 | maxGap = it->first; 218 | maxCount = it->second; 219 | } 220 | } 221 | } 222 | 223 | 224 | double LargeGapGrayCode::computeGapVariance(const std::map& runLengths) 225 | { 226 | int sum = 0; 227 | int runs = 0; 228 | 229 | for(std::map::const_iterator it = runLengths.begin(); it != runLengths.end(); ++it) { 230 | sum += it->first * it->second; 231 | runs += it->second; 232 | } 233 | 234 | double mean = (double)sum/runs; 235 | 236 | int squaredDiff = 0; 237 | for(std::map::const_iterator it = runLengths.begin(); it != runLengths.end(); ++it) { 238 | squaredDiff += (it->first-mean)*(it->first-mean) * it->second; 239 | } 240 | 241 | double variance = (double)squaredDiff/runs; 242 | 243 | return variance; 244 | } 245 | 246 | 247 | 248 | bool LargeGapGrayCode::isOddPositive(int value) 249 | { 250 | bool ret = false; 251 | if(value > 0 && value%2 == 1) { 252 | ret = true; 253 | } 254 | return ret; 255 | } 256 | 257 | 258 | std::vector LargeGapGrayCode::createPVector(int s, int t) 259 | { 260 | double startRatio = (double) t/s; 261 | int bUsed = 0; 262 | int aUsed = 0; 263 | 264 | std::vector tmp(s+t); 265 | for(int i = 0; i < tmp.size(); ++i) { 266 | if((double)bUsed/(aUsed+1) >= startRatio) { 267 | tmp[i] = 'a'; 268 | aUsed++; 269 | } 270 | else { 271 | tmp[i] = 'b'; 272 | bUsed++; 273 | } 274 | } 275 | return tmp; 276 | } 277 | 278 | 279 | std::vector LargeGapGrayCode::multiCopyVector(const std::vector& oldVector, int numCopies) 280 | { 281 | std::vector newVector(oldVector.size()*numCopies); 282 | for(int i = 0; i < numCopies; ++i) { 283 | for(int j = 0; j < oldVector.size(); ++j) { 284 | newVector[i*oldVector.size() + j] = oldVector[j]; 285 | } 286 | } 287 | return newVector; 288 | } 289 | 290 | 291 | std::vector LargeGapGrayCode::createTransitionSequenceTheorem1(int n, int m, const std::vector& Z) 292 | { 293 | std::vector tmp(Z.size()); 294 | 295 | std::vector A = m_transitionSequences[n-1]; 296 | std::vector B = m_transitionSequences[m-1]; 297 | int idxA = 0; 298 | int idxB = 0; 299 | 300 | for(int i = 0; i < Z.size(); i++) 301 | { 302 | if(Z[i] == 'a') { 303 | tmp[i] = A[idxA++ % A.size()]; 304 | } 305 | else if(Z[i] == 'b') { 306 | tmp[i] = B[idxB++ % B.size()] + n; 307 | } 308 | } 309 | return tmp; 310 | } 311 | 312 | 313 | std::vector LargeGapGrayCode::createTransitionSequenceTheorem2(int n, int m, int r, const std::vector& Z) 314 | { 315 | std::vector tmp(Z.size()); 316 | 317 | std::vector A = m_transitionSequences[n-1]; 318 | std::vector B = m_transitionSequences[m-1]; 319 | std::vector C = m_transitionSequences[r-1]; 320 | int idxA = 0; 321 | int idxB = 0; 322 | int idxC = 0; 323 | 324 | for(int i = 0; i < Z.size(); i++) 325 | { 326 | if(Z[i] == 'a') { 327 | tmp[i] = A[idxA++ % A.size()]; 328 | } 329 | else if(Z[i] == 'b') { 330 | tmp[i] = B[idxB++ % B.size()] + n; 331 | } 332 | else if(Z[i] == 'c') { 333 | tmp[i] = C[idxC++ % C.size()] + n + m; 334 | } 335 | } 336 | return tmp; 337 | } 338 | 339 | void LargeGapGrayCode::replaceLastBWithC(std::vector& v) 340 | { 341 | for(int k = v.size()-1; k >= 0; --k) { 342 | if(v[k] == 'b') { 343 | v[k] = 'c'; 344 | break; 345 | } 346 | } 347 | } 348 | -------------------------------------------------------------------------------- /src/LargeGapGrayCode.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file LargeGapGrayCode.h 3 | * @author Kent Hansen 4 | * @date 8 Jan 2015 5 | * @brief File for constructing Large-Gap Gray codes (LGGC) 6 | * 7 | * LGGC is a special type of Gray code with the additional 8 | * property that it contains large run lengths. 9 | * 10 | * For more information about LGGC construction, see: 11 | * http://www.github.com/tckent/largegap-graycode 12 | */ 13 | 14 | #ifndef LARGEGAPGRAYCODE_H_ 15 | #define LARGEGAPGRAYCODE_H_ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | class LargeGapGrayCode { 22 | public: 23 | LargeGapGrayCode(); 24 | virtual ~LargeGapGrayCode(); 25 | 26 | std::vector getTransitionSequence(int bitWidth); 27 | std::vector > getBinaryCode(int bitWidth); 28 | 29 | void printAllStatistics(); 30 | void printStatisticsHeader(); 31 | void printStatistics(int bitWidth); 32 | 33 | void createCodeFromTheorem1(int n, int m, int s, int t); 34 | void createCodeFromTheorem2(int n, int m, int r, int s, int t); 35 | 36 | private: 37 | bool isOddPositive(int value); 38 | std::vector createPVector(int s, int t); 39 | std::vector multiCopyVector(const std::vector& oldVector, int numCopies); 40 | void replaceLastBWithC(std::vector& v); 41 | std::vector createTransitionSequenceTheorem1(int n, int m, const std::vector& Z); 42 | std::vector createTransitionSequenceTheorem2(int n, int m, int r, const std::vector& Z); 43 | 44 | std::map computeRunLengths(int bitWidth); 45 | double computeGapVariance(const std::map& runLengths); 46 | void computeMinGap(const std::map& runLengths, int& minGap, int& minCount); 47 | void computeMaxGap(const std::map& runLengths, int& maxGap, int& maxCount); 48 | 49 | std::vector > m_transitionSequences; 50 | std::vector m_creationMethod; 51 | }; 52 | 53 | #endif /* LARGEGAPGRAYCODE_H_ */ 54 | -------------------------------------------------------------------------------- /src/examples.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file examples.cpp 3 | * @author Kent Hansen 4 | * @date 8 Jan 2015 5 | * @brief Example usage of Large-Gap Gray code (LGGC) class. 6 | * 7 | * 1) Shows statistics for LGGC ranging from 3-20 bits 8 | * 2) Construction of four different 16-bit codes and their statistics 9 | * 3) Print of constructed 7-bit code. Note the length of horizontal bit runs 10 | * 11 | * For more information, see: http://www.github.com/tckent/largegap-graycode 12 | */ 13 | 14 | #include 15 | #include 16 | #include "LargeGapGrayCode.h" 17 | 18 | void printBinaryCode(const std::vector >& code, int bitWidth); 19 | 20 | int main() { 21 | LargeGapGrayCode lggc; 22 | std::cout << "####################################################################" << std::endl; 23 | std::cout << "####### 1) Printing statistics for all Large-Gap Gray Codes #######" << std::endl; 24 | std::cout << "####################################################################" << std::endl << std::endl; 25 | lggc.printAllStatistics(); 26 | 27 | std::cout << std::endl << std::endl; 28 | std::cout << "####################################################################" << std::endl; 29 | std::cout << "####### 2) Printing statistics for different 16-bit codes #######" << std::endl; 30 | std::cout << "####################################################################" << std::endl << std::endl; 31 | lggc.printStatisticsHeader(); 32 | lggc.createCodeFromTheorem1(14, 2, 3, 1); 33 | lggc.printStatistics(16); 34 | lggc.createCodeFromTheorem1(8, 8, 129, 127); 35 | lggc.printStatistics(16); 36 | lggc.createCodeFromTheorem1(9, 7, 65, 63); 37 | lggc.printStatistics(16); 38 | lggc.createCodeFromTheorem1(11, 5, 21, 11); 39 | lggc.printStatistics(16); 40 | 41 | std::cout << std::endl << std::endl; 42 | std::cout << "####################################################################" << std::endl; 43 | std::cout << "####### 3) Printing generated 7-bit binary code #######" << std::endl; 44 | std::cout << "####### Note: MinGap = 5 and MaxGap = 11 #######" << std::endl; 45 | std::cout << "####################################################################" << std::endl << std::endl; 46 | printBinaryCode(lggc.getBinaryCode(7), 7); 47 | 48 | return 0; 49 | } 50 | 51 | 52 | void printBinaryCode(const std::vector >& code, int bitWidth) 53 | { 54 | for(int j = 0; j < bitWidth; ++j) 55 | { 56 | for(int i = 0; i < pow(2, bitWidth); i++) 57 | { 58 | std::cout << code[i][j]; 59 | } 60 | std::cout << std::endl; 61 | } 62 | std::cout << std::endl; 63 | } 64 | -------------------------------------------------------------------------------- /src/imagePatterns.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file imagePatterns.cpp 3 | * @author Kent Hansen 4 | * @date 8 Jan 2015 5 | * @brief Generation of image patterns that can be used for structured light applications. 6 | * 7 | * Usage: ./imagePatterns bitWidth 8 | * 9 | * For more information, see: http://www.github.com/tckent/largegap-graycode 10 | */ 11 | 12 | #include "LargeGapGrayCode.h" 13 | #include 14 | 15 | const int maxBitWidth = 10; 16 | const int imgWidth = pow(2, maxBitWidth); 17 | const int imgHeight = 500; 18 | 19 | void createImagePatterns(int bitWidth); 20 | 21 | int main(int argc,char *argv[]) 22 | { 23 | if(argc != 2) { 24 | std::cout << "Usage: ./imagePatterns bitWidth" << std::endl; 25 | return -1; 26 | } 27 | int bitWidth = atoi(argv[1]); 28 | 29 | if(bitWidth > 0 && bitWidth <= maxBitWidth) { 30 | createImagePatterns(bitWidth); 31 | } 32 | return 0; 33 | } 34 | 35 | 36 | void createImagePatterns(int bitWidth) 37 | { 38 | LargeGapGrayCode lggc; 39 | std::vector > binaryCode = lggc.getBinaryCode(bitWidth); 40 | 41 | int stripeWidth = imgWidth/pow(2,bitWidth); 42 | cv::Mat image = cv::Mat::zeros(imgHeight, imgWidth, CV_8U); 43 | 44 | for(int i = 0; i < bitWidth; ++i) { 45 | for(int j = 0; j < pow(2, bitWidth); ++j) { 46 | if(binaryCode[j][i]) { 47 | for(int l = 0; l < stripeWidth; ++l) { 48 | for(int k = 0; k < imgHeight/bitWidth; k++) { 49 | image.at(k+i*imgHeight/bitWidth, stripeWidth*j + l) = 255; 50 | } 51 | } 52 | } 53 | } 54 | } 55 | 56 | std::stringstream windowTitle; 57 | windowTitle << "Large-Gap Gray code: All " << bitWidth << " bits"; 58 | cv::imshow(windowTitle.str().c_str() , image); 59 | cv::waitKey(0); 60 | 61 | for(int i = 0; i < bitWidth; ++i) { 62 | image = cv::Mat::zeros(imgHeight, imgWidth, CV_8U); 63 | for(int j = 0; j < pow(2, bitWidth); ++j) { 64 | if(binaryCode[j][i]) { 65 | for(int l = 0; l < stripeWidth; ++l) { 66 | for(int k = 0; k < imgHeight; k++) { 67 | image.at(k, stripeWidth*j + l) = 255; 68 | } 69 | } 70 | } 71 | } 72 | windowTitle.str(""); 73 | windowTitle << "Large-Gap Gray code: Bit " << i; 74 | cv::imshow(windowTitle.str().c_str(), image); 75 | cv::waitKey(0); 76 | } 77 | } 78 | --------------------------------------------------------------------------------