├── Document ├── comp │ ├── gallo.pdf │ └── soros.pdf └── 1Dbarcode_iyyun.pdf ├── src └── Linux │ └── tencon │ ├── Test_images │ ├── t1.jpg │ ├── t2.jpg │ ├── t3.jpg │ ├── t4.jpg │ ├── t5.jpg │ └── t6.jpg │ ├── CMakeLists.txt │ ├── gallo │ ├── gallo.h │ └── gallo.cpp │ ├── soros │ ├── soros.h │ └── soros.cpp │ ├── main.cpp │ └── yun │ ├── yun.h │ └── yun.cpp ├── .gitignore ├── LICENSE └── README.md /Document/comp/gallo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iyyun/Barcode_1D/HEAD/Document/comp/gallo.pdf -------------------------------------------------------------------------------- /Document/comp/soros.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iyyun/Barcode_1D/HEAD/Document/comp/soros.pdf -------------------------------------------------------------------------------- /Document/1Dbarcode_iyyun.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iyyun/Barcode_1D/HEAD/Document/1Dbarcode_iyyun.pdf -------------------------------------------------------------------------------- /src/Linux/tencon/Test_images/t1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iyyun/Barcode_1D/HEAD/src/Linux/tencon/Test_images/t1.jpg -------------------------------------------------------------------------------- /src/Linux/tencon/Test_images/t2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iyyun/Barcode_1D/HEAD/src/Linux/tencon/Test_images/t2.jpg -------------------------------------------------------------------------------- /src/Linux/tencon/Test_images/t3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iyyun/Barcode_1D/HEAD/src/Linux/tencon/Test_images/t3.jpg -------------------------------------------------------------------------------- /src/Linux/tencon/Test_images/t4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iyyun/Barcode_1D/HEAD/src/Linux/tencon/Test_images/t4.jpg -------------------------------------------------------------------------------- /src/Linux/tencon/Test_images/t5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iyyun/Barcode_1D/HEAD/src/Linux/tencon/Test_images/t5.jpg -------------------------------------------------------------------------------- /src/Linux/tencon/Test_images/t6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iyyun/Barcode_1D/HEAD/src/Linux/tencon/Test_images/t6.jpg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Settings 2 | .vscode/ 3 | 4 | # Prerequisites 5 | *.d 6 | 7 | # Compiled Object files 8 | *.slo 9 | *.lo 10 | *.o 11 | *.obj 12 | build/ 13 | 14 | # Precompiled Headers 15 | *.gch 16 | *.pch 17 | 18 | # Compiled Dynamic libraries 19 | *.so 20 | *.dylib 21 | *.dll 22 | 23 | # Fortran module files 24 | *.mod 25 | *.smod 26 | 27 | # Compiled Static libraries 28 | *.lai 29 | *.la 30 | *.a 31 | *.lib 32 | 33 | # Executables 34 | *.exe 35 | *.out 36 | *.app 37 | -------------------------------------------------------------------------------- /src/Linux/tencon/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | project( iyCode ) 4 | 5 | find_package(OpenCV REQUIRED) 6 | 7 | if(OpenCV_FOUND) 8 | file(GLOB_RECURSE COMP_METHOD 9 | "./gallo/*.cpp" 10 | "./gallo/*.h" 11 | "./soros/*.cpp" 12 | "./soros/*.h" 13 | "./yun/*.cpp" 14 | "./yun/*.h" 15 | ) 16 | 17 | add_executable( iyBarcode main.cpp ${COMP_METHOD}) 18 | 19 | target_link_libraries( iyBarcode ${OpenCV_LIBS}) 20 | 21 | endif() 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/Linux/tencon/gallo/gallo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 Inyong Yun (Sungkyunkwan University) 3 | * 4 | * Created on: 2017. 11. 24. (Rev. 2.0) 5 | * Author: Inyong Yun 6 | * type: c/c++ 7 | * 8 | * Reference paper: 9 | * Gallo, O., & Manduchi, R. (2011). "Reading 1D barcodes with mobile phones using deformable templates." 10 | * IEEE transactions on pattern analysis and machine intelligence, 33(9), 1834-1843. 11 | * 12 | * etc: not include barcode recognition process. 13 | * only localization method! * 14 | */ 15 | 16 | #include 17 | 18 | namespace iy{ 19 | class Gallo { 20 | private: 21 | cv::Mat calc_gradient(cv::Mat &src); 22 | cv::Mat calc_integral_image(cv::Mat &src); 23 | cv::Point find_max_point_with_smooth(cv::Mat &src, cv::Mat &smooth_map, int WinSz); 24 | cv::Rect box_detection(cv::Mat &src, cv::Point cp); 25 | public: 26 | Gallo(){} 27 | ~Gallo(){} 28 | 29 | cv::Rect process(cv::Mat &gray_src, int WinSz = 20); 30 | }; 31 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 iyyun 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 | -------------------------------------------------------------------------------- /src/Linux/tencon/soros/soros.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 Inyong Yun (Sungkyunkwan University) 3 | * 4 | * Created on: 2017. 11. 24. (Rev. 2.0) 5 | * Author: Inyong Yun 6 | * type: c/c++ 7 | * 8 | * Reference paper: 9 | * Sörös, Gábor, and Christian Flörkemeier. "Blur-resistant joint 1D and 2D barcode localization for smartphones." 10 | * Proceedings of the 12th International Conference on Mobile and Ubiquitous Multimedia. ACM, 2013. 11 | * 12 | * etc: not include barcode recognition process. 13 | * only localization method! * 14 | */ 15 | 16 | #include 17 | 18 | namespace iy{ 19 | class Soros { 20 | private: 21 | cv::Mat SaliencyMapbyAndoMatrix(cv::Mat &src, bool is1D = true); 22 | cv::Mat calc_integral_image(cv::Mat &src); 23 | cv::Point find_max_point_with_smooth(cv::Mat &src, cv::Mat &smooth_map, int WinSz = 20); 24 | cv::Rect box_detection(cv::Mat &src, cv::Point cp); 25 | public: 26 | Soros() {} 27 | ~Soros() {} 28 | 29 | cv::Rect process(cv::Mat &gray_src, bool is1D = true, int WinSz = 20); 30 | }; 31 | } -------------------------------------------------------------------------------- /src/Linux/tencon/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "gallo/gallo.h" 6 | #include "soros/soros.h" 7 | #include "yun/yun.h" 8 | 9 | // key 10 | const char* keys = 11 | "{h help | | print help message }" 12 | "{file | /file/dir/file_name | test image file(.bmp .jpg .png) }"; 13 | 14 | int main(int argc, char* argv[]) 15 | { 16 | cv::CommandLineParser cmd(argc, argv, keys); 17 | if (cmd.has("help") || !cmd.check()) 18 | { 19 | cmd.printMessage(); 20 | cmd.printErrors(); 21 | return 0; 22 | } 23 | 24 | std::string fn = cmd.get("file"); 25 | 26 | iy::Gallo mGallo; 27 | iy::Soros mSoros; 28 | iy::Yun mYun; 29 | 30 | cv::Mat frame_gray; 31 | cv::Mat frame = cv::imread(fn.c_str()); 32 | 33 | if(frame.data == NULL) { 34 | std::cerr << "error! read image" << std::endl; 35 | return -1; 36 | } 37 | 38 | cv::cvtColor(frame, frame_gray, cv::COLOR_BGR2GRAY); 39 | 40 | cv::Rect g_rt = mGallo.process(frame_gray, 20); 41 | cv::rectangle(frame, g_rt, cv::Scalar(0, 255, 0), 2); 42 | 43 | cv::Rect s_rt = mSoros.process(frame_gray, 20); 44 | cv::rectangle(frame, s_rt, cv::Scalar(255,0,0), 2); 45 | 46 | std::vector list_barcode = mYun.process(frame_gray); 47 | if (!list_barcode.empty()) 48 | { 49 | for (std::vector::iterator it = list_barcode.begin(); it < list_barcode.end(); it++) 50 | { 51 | if (it->isBarcode) 52 | { 53 | cv::Rect y_rt = it->roi; 54 | cv::rectangle(frame, y_rt, cv::Scalar(0, 255, 255), 2); 55 | } 56 | } 57 | 58 | list_barcode.clear(); 59 | } 60 | 61 | cv::imshow("frame", frame); 62 | cv::waitKey(0); 63 | 64 | cv::destroyAllWindows(); 65 | 66 | return 0; 67 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vision-based 1D barcode localization method for scale and rotation invariant 2 | 3 | This is a barcode detection project at the digital signal processing laboratory of the Sungkyunkwan University. With the program in this repository you can evaluate your data. 4 | 5 | The software runs under windows and linux and is written in C++. 6 | 7 | Based on the following libraries: 8 | * OpenCV ( >= 4.10) 9 | * CMake (>= 2.8) 10 | * VTK (>= 9.3.1) 11 | * HDF5 (>= 1.14.4.3) 12 | 13 | Build Instructions 14 | ------------------ 15 | $ git clone https://github.com/iyyun/Barcode_1D.git 16 | $ cd Barcode_1D/src/Linux/tencon 17 | $ mkdir build 18 | $ cd build 19 | $ cmake .. 20 | $ make 21 | 22 | Dataset 23 | ------- 24 | you can download our dataset from [here](http://dspl.skku.ac.kr/home_course/data/barcode/skku_inyong_DB.zip) (not include ground truth labels) 25 | 26 | 27 | Demo 28 | ---- 29 | $ cd Barcode_1D/src/Linux/tencon/build 30 | $ ./iyBarcode --file=../../tencone/Test_images/t1.jpg 31 | 32 | [![video](http://img.youtube.com/vi/KbB97vP3mhA/0.jpg)](https://youtu.be/KbB97vP3mhA?t=0s) 33 | 34 | Cite 35 | ---- 36 | 37 | yon can find the paper in the "Document" section or [here](https://www.researchgate.net/publication/321349040_VIsion-based_1D_Barcode_Localization_Method_for_Scale_and_Rotation_Invariant) or [IEEEXelore](https://ieeexplore.ieee.org/document/8228227). 38 | 39 | If you use this barcode detection program, please cite the following: 40 | 41 | @inproceedings{yun2017vision, 42 | title={Vision-based 1D barcode localization method for scale and rotation invariant}, 43 | author={Yun, Inyong and Kim, Joongkyu}, 44 | booktitle={Region 10 Conference, TENCON 2017-2017 IEEE}, 45 | pages={2204--2208}, 46 | year={2017}, 47 | organization={IEEE} 48 | } 49 | -------------------------------------------------------------------------------- /src/Linux/tencon/yun/yun.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 Inyong Yun (Sungkyunkwan University) 3 | * 4 | * Created on: 2017. 11. 24. (Rev. 2.0) 5 | * Author: Inyong Yun 6 | * type: c/c++ 7 | * 8 | * Reference paper: 9 | * I.Y. Yun & J.K. Kim, (2017) "Vision-Based 1D Barcode Localization Method for Scale and Rotation Invariant." 10 | * Proc. of the 2017 IEEE Region 10 Conference (TENCON), Malaysia, Nov 5-8, 2204-2208 11 | * 12 | * etc: not include barcode recognition process. 13 | * only localization method! * 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | #define NUM_ANG 18 20 | 21 | namespace iy{ 22 | typedef struct 23 | { 24 | int cnt; 25 | bool isStrong; 26 | } YunOrientation; 27 | 28 | typedef struct 29 | { 30 | cv::Rect roi; 31 | int max_orientation; 32 | } YunLabel; 33 | 34 | typedef struct 35 | { 36 | cv::Point last_pt, first_pt; 37 | cv::Rect roi; 38 | int orientation; 39 | bool isBarcode; 40 | } YunCandidate; 41 | 42 | typedef struct 43 | { 44 | int magT; 45 | int winSz; 46 | int minEdgeT; 47 | int localBlockSz; 48 | double minDensityEdgeT; 49 | } YunParams; 50 | 51 | class Yun{ 52 | private: 53 | // process parameter 54 | YunParams pam; 55 | 56 | cv::Mat calc_orientation(cv::Mat &src, cv::Mat &mMap, std::vector &Vmap); 57 | cv::Mat calc_saliency(cv::Mat &src, std::vector &Vmap, int lbSz); 58 | cv::Mat calc_integral_image(cv::Mat &src); 59 | cv::Mat calc_smooth(cv::Mat &src, int WinSz); 60 | int push(int *stackx, int *stacky, int arr_size, int vx, int vy, int *top); 61 | int pop(int *stackx, int *stacky, int arr_size, int *vx, int *vy, int *top); 62 | std::vector ccl(cv::Mat &src, cv::Mat &oMap, std::vector &Vmap); 63 | std::vector calc_candidate(std::vector &val, cv::Mat &mMap, cv::Mat &oMap); 64 | YunCandidate sub_candidate(YunLabel val, cv::Mat &mMap, cv::Mat &oMap); 65 | YunCandidate calc_region_check(YunCandidate val, cv::Size imSz); 66 | 67 | public: 68 | Yun() { 69 | // init value 70 | pam.magT = 30; 71 | pam.winSz = 25; 72 | pam.minEdgeT = 30; 73 | pam.localBlockSz = 15; 74 | pam.minDensityEdgeT = 0.3; 75 | } 76 | ~Yun() {} 77 | 78 | std::vector process(cv::Mat &gray_src); 79 | std::vector process(cv::Mat &gray_src, YunParams pams) 80 | { 81 | pam = pams; 82 | std::vector result = process(gray_src); 83 | return result; 84 | }; 85 | }; 86 | } -------------------------------------------------------------------------------- /src/Linux/tencon/gallo/gallo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 Inyong Yun (Sungkyunkwan University) 3 | * 4 | * Created on: 2017. 11. 24. (Rev. 2.0) 5 | * Author: Inyong Yun 6 | * type: c/c++ 7 | * 8 | * Reference paper: 9 | * Gallo, O., & Manduchi, R. (2011). "Reading 1D barcodes with mobile phones using deformable templates." 10 | * IEEE transactions on pattern analysis and machine intelligence, 33(9), 1834-1843. 11 | * 12 | * etc: not include barcode recognition process. 13 | * only localization method! * 14 | */ 15 | 16 | #include "gallo.h" 17 | 18 | using namespace iy; 19 | 20 | cv::Rect Gallo::process(cv::Mat &gray_src, int WinSz/*=20*/) 21 | { 22 | cv::Rect result(0,0,0,0); 23 | 24 | try{ 25 | // gradirnt map 26 | cv::Mat hGrad = calc_gradient(gray_src); 27 | 28 | // integral map 29 | cv::Mat iMap = calc_integral_image(hGrad); 30 | 31 | // find max point with box filter 32 | cv::Mat sMap(hGrad.size(), CV_8UC1); 33 | cv::Point cp = find_max_point_with_smooth(iMap, sMap, WinSz); 34 | 35 | // global binzrization 36 | cv::Mat bMap(hGrad.size(), CV_8UC1); 37 | cv::threshold(sMap, bMap, 50, 255, cv::THRESH_OTSU); 38 | 39 | // box detection 40 | result = box_detection(bMap, cp); 41 | } 42 | catch(cv::Exception &e) 43 | { 44 | std::cerr << "cv::Exception: " << std::endl; 45 | std::cerr << e.what() << std::endl; 46 | } 47 | 48 | // return result 49 | return result; 50 | } 51 | 52 | cv::Mat Gallo::calc_gradient(cv::Mat &src) 53 | { 54 | assert(src.channels() == 1); 55 | 56 | const cv::Size imSz = src.size(); 57 | cv::Mat result(imSz, CV_8UC1); 58 | 59 | for(int h = 1; h < imSz.height - 1; h++) 60 | { 61 | for(int w = 1; w < imSz.width - 1; w++) 62 | { 63 | int dx = src.at(h-1,w-1) + 2*src.at(h,w-1) + src.at(h+1,w-1) - 64 | src.at(h-1,w+1) - 2*src.at(h,w+1) - src.at(h+1,w+1); 65 | 66 | result.at(h,w) = std::abs(dx); 67 | } 68 | } 69 | 70 | return result; 71 | } 72 | 73 | cv::Mat Gallo::calc_integral_image(cv::Mat &src) 74 | { 75 | assert(src.channels() == 1); 76 | 77 | const cv::Size imSz = src.size(); 78 | cv::Mat result(imSz, CV_32FC1); 79 | 80 | // -1st cols 81 | result.at(0,0) = src.at(0,0); 82 | for(int w = 1; w < imSz.width; w++) 83 | result.at(0, w) = (float)src.at(0, w) + result.at(0, w-1); 84 | 85 | // -other cols 86 | for(int h = 1; h < imSz.height; h++) 87 | { 88 | float sum = 0.0f; 89 | for(int w = 0; w < imSz.width; w++) 90 | { 91 | sum += src.at(h, w); 92 | result.at(h, w) = result.at(h-1, w) + sum; 93 | } 94 | } 95 | 96 | return result; 97 | } 98 | 99 | cv::Point Gallo::find_max_point_with_smooth(cv::Mat &src, cv::Mat &smooth_map, int WinSz) 100 | { 101 | const cv::Size imSz = src.size(); 102 | cv::Point max_pt(0, 0); 103 | 104 | const int nSize = WinSz * WinSz; 105 | const int cSize = (WinSz / 2) + 1; 106 | const int max_height = imSz.height - cSize; 107 | const int max_width = imSz.width - cSize; 108 | float mean_max = 0.0f; 109 | 110 | for(int h = 0; h < imSz.height; h++) 111 | { 112 | int temp_top = h - cSize; 113 | int ntop = (temp_top > max_height) ? max_height : temp_top; 114 | int temp_bottom = h + cSize; 115 | int nbottom = (temp_bottom >= imSz.height-1) ? imSz.height-1 : temp_bottom; 116 | 117 | for(int w = 0; w < imSz.width; w++) 118 | { 119 | int temp_left = w - cSize; 120 | int nleft = (temp_left > max_width) ? max_width : temp_left; 121 | int temp_right = w + cSize; 122 | int nright = (temp_right >= imSz.width-1) ? imSz.width-1 : temp_right; 123 | 124 | // local mean 125 | float n1 = (nleft > 0 && ntop > 0) ? src.at(ntop, nleft-1): 0; 126 | float n2 = (nleft > 0) ? src.at(nbottom, nleft-1): 0; 127 | float n3 = (ntop > 0) ? src.at(ntop, nright): 0; 128 | 129 | float sum = src.at(nbottom, nright) - n3 - n2 + n1; 130 | float mean = sum / nSize; 131 | 132 | if(mean > mean_max){ 133 | mean_max = mean; 134 | max_pt.x = w; 135 | max_pt.y = h; 136 | } 137 | 138 | smooth_map.at(h,w) = (mean > 255) ? 255 : mean; 139 | } 140 | } 141 | 142 | return max_pt; 143 | } 144 | 145 | cv::Rect Gallo::box_detection(cv::Mat &src, cv::Point cp) 146 | { 147 | cv::Rect result(0,0,0,0); 148 | 149 | const cv::Size imSz = src.size(); 150 | 151 | // lfet 152 | for(int w = cp.x; w >= 0; w--) 153 | { 154 | if(src.at(cp.y, w) < 128) 155 | { 156 | result.x = w; 157 | break; 158 | } 159 | } 160 | 161 | // right 162 | for(int w = cp.x; w < imSz.width; w++) 163 | { 164 | if(src.at(cp.y, w) < 128) 165 | { 166 | result.width = w - result.x; 167 | break; 168 | } 169 | } 170 | 171 | // up 172 | for(int h = cp.y; h >= 0; h--) 173 | { 174 | if(src.at(h, cp.x) < 128) 175 | { 176 | result.y = h; 177 | break; 178 | } 179 | } 180 | 181 | //down 182 | for(int h = cp.y; h < imSz.height; h++) 183 | { 184 | if(src.at(h, cp.x) < 128) 185 | { 186 | result.height = h - result.y; 187 | break; 188 | } 189 | } 190 | 191 | return result; 192 | } 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | -------------------------------------------------------------------------------- /src/Linux/tencon/soros/soros.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 Inyong Yun (Sungkyunkwan University) 3 | * 4 | * Created on: 2017. 11. 24. (Rev. 2.0) 5 | * Author: Inyong Yun 6 | * type: c/c++ 7 | * 8 | * Reference paper: 9 | * Sörös, Gábor, and Christian Flörkemeier. "Blur-resistant joint 1D and 2D barcode localization for smartphones." 10 | * Proceedings of the 12th International Conference on Mobile and Ubiquitous Multimedia. ACM, 2013. 11 | * 12 | * etc: not include barcode recognition process. 13 | * only localization method! * 14 | */ 15 | 16 | #include "soros.h" 17 | 18 | using namespace iy; 19 | 20 | cv::Rect Soros::process(cv::Mat &gray_src, bool is1D /*= true*/, int WinSz /*= 20*/) 21 | { 22 | cv::Rect result(0,0,0,0); 23 | 24 | try{ 25 | // saliency map 26 | cv::Mat saliency = SaliencyMapbyAndoMatrix(gray_src, is1D); 27 | 28 | // integral map 29 | cv::Mat iMap = calc_integral_image(saliency); 30 | 31 | // find max point with box filter 32 | cv::Mat sMap(saliency.size(), CV_8UC1); 33 | cv::Point cp = find_max_point_with_smooth(iMap, sMap, WinSz); 34 | 35 | // global binzrization 36 | cv::Mat bMap(saliency.size(), CV_8UC1); 37 | cv::threshold(sMap, bMap, 50, 255, cv::THRESH_OTSU); 38 | 39 | // box detection 40 | result = box_detection(bMap, cp); 41 | } 42 | catch(cv::Exception &e) 43 | { 44 | std::cerr << "cv::Exception: " << std::endl; 45 | std::cerr << e.what() << std::endl; 46 | } 47 | 48 | // return result 49 | return result; 50 | } 51 | 52 | double gmask[7][7] = {{0.0071, 0.0071, 0.0143, 0.0143, 0.0143, 0.0071, 0.0071}, 53 | {0.0071, 0.0143, 0.0143, 0.0286, 0.0143, 0.0143, 0.0071}, 54 | {0.0143, 0.0143, 0.0286, 0.0571, 0.0286, 0.0143, 0.0143}, 55 | {0.0143, 0.0286, 0.0571, 0.1143, 0.0571, 0.0281, 0.0143}, 56 | {0.0143, 0.0143, 0.0286, 0.0571, 0.0286, 0.0143, 0.0143}, 57 | {0.0071, 0.0143, 0.0143, 0.0286, 0.0143, 0.0143, 0.0071}, 58 | {0.0071, 0.0071, 0.0143, 0.0143, 0.0143, 0.0071, 0.0071} }; 59 | 60 | cv::Mat Soros::SaliencyMapbyAndoMatrix(cv::Mat &src, bool is1D) 61 | { 62 | const cv::Size imSz = src.size(); 63 | 64 | cv::Mat result(imSz, CV_8UC1); 65 | 66 | double *Ixx = new double[sizeof(double) * imSz.width * imSz.height]; 67 | double *Ixy = new double[sizeof(double) * imSz.width * imSz.height]; 68 | double *Iyy = new double[sizeof(double) * imSz.width * imSz.height]; 69 | double *Cxx = new double[sizeof(double) * imSz.width * imSz.height]; 70 | double *Cxy = new double[sizeof(double) * imSz.width * imSz.height]; 71 | double *Cyy = new double[sizeof(double) * imSz.width * imSz.height]; 72 | 73 | // edge by sobel 74 | for(int h = 1; h < imSz.height - 1; h++) 75 | { 76 | for(int w = 1; w < imSz.width - 1; w++) 77 | { 78 | float dx = (float)src.at(h-1,w-1) + 2.0f*src.at(h,w-1) + (float)src.at(h+1,w-1) - 79 | (float)src.at(h-1,w+1) - 2.0f*src.at(h,w+1) - (float)src.at(h+1,w+1); 80 | 81 | float dy = (float)src.at(h-1,w-1) + 2.0f*src.at(h-1,w) + (float)src.at(h-1,w+1) - 82 | (float)src.at(h+1,w-1) - 2.0f*src.at(h+1,w) - (float)src.at(h+1,w+1); 83 | 84 | Ixx[h*imSz.width + w] = dx*dx; 85 | Ixy[h*imSz.width + w] = dx*dy; 86 | Iyy[h*imSz.width + w] = dy*dy; 87 | } 88 | } 89 | 90 | // apply gaussian window function 91 | for(int h = 1; h < imSz.height - 1; h++) 92 | { 93 | for(int w = 1; w < imSz.width - 1; w++) 94 | { 95 | double C1 = 0; 96 | double C2 = 0; 97 | double C3 = 0; 98 | 99 | for(int m = 0; m < 7; m++) 100 | { 101 | int s = h + m - 4; 102 | if(s < 0) continue; 103 | for(int n = 0; n < 7; n++) 104 | { 105 | int k = w + n - 4; 106 | if(k < 0) continue; 107 | C1 += Ixx[s*imSz.width + k] * gmask[m][n]; 108 | C2 += Ixy[s*imSz.width + k] * gmask[m][n]; 109 | C3 += Iyy[s*imSz.width + k] * gmask[m][n]; 110 | } 111 | } 112 | 113 | Cxx[h*imSz.width + w] = C1; 114 | Cxy[h*imSz.width + w] = C2; 115 | Cyy[h*imSz.width + w] = C3; 116 | } 117 | } 118 | 119 | // edge or corner map 120 | for(int h = 1; h < imSz.height - 1; h++) 121 | { 122 | for(int w = 1; w < imSz.width - 1; w++) 123 | { 124 | double Txx = Cxx[h*imSz.width + w]; 125 | double Txy = Cxy[h*imSz.width + w]; 126 | double Tyy = Cyy[h*imSz.width + w]; 127 | 128 | double m = 0; 129 | if(is1D) 130 | { 131 | m = ((Txx - Tyy)*(Txx - Tyy) + 4 * (Txy * Txy)) / ((Txx + Tyy) * (Txx + Tyy) + 10000); 132 | } 133 | else 134 | { 135 | m = (4 * (Txx*Tyy - (Txy*Txy))) / ((Txx + Tyy)*(Txx + Tyy) + 10000); 136 | } 137 | 138 | m *= 255.0; 139 | 140 | result.at(h,w) = (m > 255) ? 255 : m; 141 | } 142 | } 143 | 144 | delete[]Ixx; 145 | delete[]Ixy; 146 | delete[]Iyy; 147 | delete[]Cxx; 148 | delete[]Cxy; 149 | delete[]Cyy; 150 | 151 | return result; 152 | } 153 | 154 | cv::Mat Soros::calc_integral_image(cv::Mat &src) 155 | { 156 | assert(src.channels() == 1); 157 | 158 | const cv::Size imSz = src.size(); 159 | cv::Mat result(imSz, CV_32FC1); 160 | 161 | // -1st cols 162 | result.at(0,0) = src.at(0,0); 163 | for(int w = 1; w < imSz.width; w++) 164 | result.at(0, w) = (float)src.at(0, w) + result.at(0, w-1); 165 | 166 | // -other cols 167 | for(int h = 1; h < imSz.height; h++) 168 | { 169 | float sum = 0.0f; 170 | for(int w = 0; w < imSz.width; w++) 171 | { 172 | sum += src.at(h, w); 173 | result.at(h, w) = result.at(h-1, w) + sum; 174 | } 175 | } 176 | 177 | return result; 178 | } 179 | 180 | cv::Point Soros::find_max_point_with_smooth(cv::Mat &src, cv::Mat &smooth_map, int WinSz) 181 | { 182 | const cv::Size imSz = src.size(); 183 | cv::Point max_pt(0, 0); 184 | 185 | const int nSize = WinSz * WinSz; 186 | const int cSize = (WinSz / 2) + 1; 187 | const int max_height = imSz.height - cSize; 188 | const int max_width = imSz.width - cSize; 189 | float mean_max = 0.0f; 190 | 191 | for(int h = 0; h < imSz.height; h++) 192 | { 193 | int temp_top = h - cSize; 194 | int ntop = (temp_top > max_height) ? max_height : temp_top; 195 | int temp_bottom = h + cSize; 196 | int nbottom = (temp_bottom >= imSz.height-1) ? imSz.height-1 : temp_bottom; 197 | 198 | for(int w = 0; w < imSz.width; w++) 199 | { 200 | int temp_left = w - cSize; 201 | int nleft = (temp_left > max_width) ? max_width : temp_left; 202 | int temp_right = w + cSize; 203 | int nright = (temp_right >= imSz.width-1) ? imSz.width-1 : temp_right; 204 | 205 | // local mean 206 | float n1 = (nleft > 0 && ntop > 0) ? src.at(ntop, nleft-1): 0; 207 | float n2 = (nleft > 0) ? src.at(nbottom, nleft-1): 0; 208 | float n3 = (ntop > 0) ? src.at(ntop, nright): 0; 209 | 210 | float sum = src.at(nbottom, nright) - n3 - n2 + n1; 211 | float mean = sum / nSize; 212 | 213 | if(mean > mean_max){ 214 | mean_max = mean; 215 | max_pt.x = w; 216 | max_pt.y = h; 217 | } 218 | 219 | smooth_map.at(h,w) = (mean > 255) ? 255 : mean; 220 | } 221 | } 222 | 223 | return max_pt; 224 | } 225 | 226 | cv::Rect Soros::box_detection(cv::Mat &src, cv::Point cp) 227 | { 228 | cv::Rect result(0,0,0,0); 229 | 230 | const cv::Size imSz = src.size(); 231 | 232 | // lfet 233 | for(int w = cp.x; w >= 0; w--) 234 | { 235 | if(src.at(cp.y, w) < 128) 236 | { 237 | result.x = w; 238 | break; 239 | } 240 | } 241 | 242 | // right 243 | for(int w = cp.x; w < imSz.width; w++) 244 | { 245 | if(src.at(cp.y, w) < 128) 246 | { 247 | result.width = w - result.x; 248 | break; 249 | } 250 | } 251 | 252 | // up 253 | for(int h = cp.y; h >= 0; h--) 254 | { 255 | if(src.at(h, cp.x) < 128) 256 | { 257 | result.y = h; 258 | break; 259 | } 260 | } 261 | 262 | //down 263 | for(int h = cp.y; h < imSz.height; h++) 264 | { 265 | if(src.at(h, cp.x) < 128) 266 | { 267 | result.height = h - result.y; 268 | break; 269 | } 270 | } 271 | 272 | return result; 273 | } -------------------------------------------------------------------------------- /src/Linux/tencon/yun/yun.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2017 Inyong Yun (Sungkyunkwan University) 3 | * 4 | * Created on: 2017. 11. 24. (Rev. 2.0) 5 | * Author: Inyong Yun 6 | * type: c/c++ 7 | * 8 | * Reference paper: 9 | * I.Y. Yun & J.K. Kim, (2017) "Vision-Based 1D Barcode Localization Method for Scale and Rotation Invariant." 10 | * Proc. of the 2017 IEEE Region 10 Conference (TENCON), Malaysia, Nov 5-8, 2204-2208 11 | * 12 | * etc: not include barcode recognition process. 13 | * only localization method! * 14 | */ 15 | 16 | #include "yun.h" 17 | 18 | using namespace iy; 19 | 20 | std::vector Yun::process(cv::Mat &gray_src) 21 | { 22 | std::vector result; 23 | 24 | try{ 25 | std::vector Vmap; 26 | cv::Mat mMap(gray_src.size(), CV_8UC1); 27 | cv::Mat oMap = calc_orientation(gray_src, mMap, Vmap); 28 | 29 | // saliency map 30 | cv::Mat eMap = calc_saliency(oMap, Vmap, pam.localBlockSz); 31 | 32 | cv::Mat iMap = calc_integral_image(eMap); 33 | cv::Mat sMap = calc_smooth(iMap, pam.winSz); 34 | 35 | cv::Mat bMap; // (sMap.size(), CV_8UC1); 36 | cv::threshold(sMap, bMap, 50, 255, cv::THRESH_OTSU); 37 | 38 | // search region 39 | std::vector blob = ccl(bMap, oMap, Vmap); 40 | 41 | // candidate 42 | result = calc_candidate(blob, mMap, oMap); 43 | 44 | //clear 45 | Vmap.clear(); 46 | blob.clear(); 47 | } 48 | catch (cv::Exception &e) 49 | { 50 | std::cerr << "cv::Exception: " << std::endl; 51 | std::cerr << e.what() << std::endl; 52 | } 53 | return result; 54 | } 55 | 56 | cv::Mat Yun::calc_orientation(cv::Mat &src, cv::Mat &mMap, std::vector &Vmap) 57 | { 58 | const cv::Size imSz = src.size(); 59 | const int ExtAng = 2 * NUM_ANG; 60 | 61 | cv::Mat oMap(imSz, CV_8UC1); 62 | 63 | Vmap.resize(NUM_ANG); 64 | for (int i = 0; i < NUM_ANG; i++) Vmap[i].cnt = 0; 65 | 66 | for (int h = 1; h < imSz.height - 1; h++) 67 | { 68 | for (int w = 1; w < imSz.width - 1; w++) 69 | { 70 | double dx = (double)src.at(h - 1, w - 1) + 2.0 * (double)src.at(h, w - 1) + (double)src.at(h + 1, w - 1) - 71 | (double)src.at(h - 1, w + 1) - 2.0 * (double)src.at(h, w + 1) - (double)src.at(h + 1, w + 1); 72 | 73 | double dy = (double)src.at(h - 1, w - 1) + 2.0 * (double)src.at(h - 1, w) + (double)src.at(h - 1, w + 1) - 74 | (double)src.at(h + 1, w - 1) - 2.0 * (double)src.at(h + 1, w) - (double)src.at(h + 1, w + 1); 75 | 76 | int intensity = std::sqrt(dx*dx + dy*dy); 77 | mMap.at(h, w) = intensity > 255 ? 255 : intensity; 78 | 79 | if (intensity > pam.magT) 80 | { 81 | double degree = (double)(std::atan2(dy, dx) + CV_PI) * 180.0 / CV_PI; // 0~360; 82 | 83 | // bin 84 | int bin = ExtAng * (degree / 360.0); 85 | if (bin < 0) bin = 0; 86 | else if (bin >= ExtAng) bin = ExtAng - 1; 87 | 88 | // integration 89 | if (bin > 17) bin -= 18; 90 | 91 | // plus integration (not include paper) 92 | if (bin > 16 || bin < 2) bin = 0; 93 | else if (bin < 5) bin = 3; 94 | else if (bin < 8) bin = 6; 95 | else if (bin < 11) bin = 9; 96 | else if (bin < 14) bin = 12; 97 | else bin = 15; 98 | 99 | // save 100 | oMap.at(h, w) = bin; 101 | Vmap[bin].cnt++; 102 | } 103 | else 104 | { 105 | oMap.at(h, w) = 255; 106 | } 107 | } 108 | } 109 | 110 | // check orientation 111 | for (int i = 0; i < NUM_ANG; i++) 112 | { 113 | if (Vmap[i].cnt > 6000) 114 | { 115 | Vmap[i].isStrong = true; 116 | } 117 | else Vmap[i].isStrong = false; 118 | } 119 | 120 | return oMap; 121 | } 122 | 123 | cv::Mat Yun::calc_saliency(cv::Mat &src, std::vector &Vmap, int lbSz) 124 | { 125 | const cv::Size imSz = src.size(); 126 | 127 | cv::Mat sMap(imSz, CV_8UC1); sMap.setTo(0); 128 | const int nMax = lbSz * lbSz * NUM_ANG; 129 | const int cBlock = (lbSz / 2) + 1; 130 | 131 | for (int h = cBlock; h < imSz.height - cBlock; h += lbSz) 132 | { 133 | for (int w = cBlock; w < imSz.width - cBlock; w += lbSz) 134 | { 135 | // step 1 local block histogram (orientation) 136 | int LocalHisto[NUM_ANG] = { 0 }; 137 | for (int y = h - cBlock; y <= h + cBlock; y++) 138 | { 139 | if (y < 0 || y >= imSz.height) continue; 140 | for (int x = w - cBlock; x <= w + cBlock; x++) 141 | { 142 | if (x < 0 || x >= imSz.width) continue; 143 | 144 | uchar bin = src.at(y, x); 145 | if (bin >= NUM_ANG) continue; 146 | 147 | LocalHisto[bin]++; 148 | } 149 | } 150 | 151 | // step 2 find max values 152 | int max_val = 0; 153 | for (int i = 0; i < NUM_ANG; i++) 154 | { 155 | if (LocalHisto[i] > max_val) 156 | max_val = LocalHisto[i]; 157 | } 158 | 159 | // step 3 entropy 160 | double pim = 0; 161 | for (int i = 0; i < NUM_ANG; i++) 162 | { 163 | pim += std::abs(LocalHisto[i] - max_val); 164 | } 165 | 166 | // step 4 check max value 167 | if (max_val == 0) continue; 168 | 169 | // step 5 normalization 170 | double npim = pim / nMax; 171 | uchar ramp_npim = (npim * 255) > 255 ? 255 : (npim * 255); 172 | 173 | if (npim < 0.6) ramp_npim = 0; 174 | 175 | // step 6 set block 176 | for (int y = h - cBlock; y <= h + cBlock; y++) 177 | { 178 | if (y < 0 || y >= imSz.height) continue; 179 | for (int x = w - cBlock; x <= w + cBlock; x++) 180 | { 181 | if (x < 0 || x >= imSz.width) continue; 182 | sMap.at(y, x) = ramp_npim; 183 | } 184 | } 185 | } 186 | } 187 | 188 | return sMap; 189 | } 190 | 191 | cv::Mat Yun::calc_integral_image(cv::Mat &src) 192 | { 193 | //assert(src.channels() == 1); 194 | 195 | const cv::Size imSz = src.size(); 196 | cv::Mat result(imSz, CV_32FC1); 197 | 198 | // -1st cols 199 | result.at(0, 0) = src.at(0, 0); 200 | for (int w = 1; w < imSz.width; w++) 201 | result.at(0, w) = (float)src.at(0, w) + result.at(0, w - 1); 202 | 203 | // -other cols 204 | for (int h = 1; h < imSz.height; h++) 205 | { 206 | float sum = 0.0f; 207 | for (int w = 0; w < imSz.width; w++) 208 | { 209 | sum += src.at(h, w); 210 | result.at(h, w) = result.at(h - 1, w) + sum; 211 | } 212 | } 213 | 214 | return result; 215 | } 216 | 217 | cv::Mat Yun::calc_smooth(cv::Mat &src, int WinSz) 218 | { 219 | const cv::Size imSz = src.size(); 220 | 221 | const int nSize = WinSz * WinSz; 222 | const int cSize = (WinSz / 2) + 1; 223 | const int max_height = imSz.height - cSize; 224 | const int max_width = imSz.width - cSize; 225 | float mean_max = 0.0f; 226 | 227 | cv::Mat smooth_map(imSz, CV_8UC1); 228 | 229 | for (int h = 0; h < imSz.height; h++) 230 | { 231 | int temp_top = h - cSize; 232 | int ntop = (temp_top > max_height) ? max_height : temp_top; 233 | int temp_bottom = h + cSize; 234 | int nbottom = (temp_bottom >= imSz.height - 1) ? imSz.height - 1 : temp_bottom; 235 | 236 | for (int w = 0; w < imSz.width; w++) 237 | { 238 | int temp_left = w - cSize; 239 | int nleft = (temp_left > max_width) ? max_width : temp_left; 240 | int temp_right = w + cSize; 241 | int nright = (temp_right >= imSz.width - 1) ? imSz.width - 1 : temp_right; 242 | 243 | // local mean 244 | float n1 = (nleft > 0 && ntop > 0) ? src.at(ntop, nleft - 1) : 0; 245 | float n2 = (nleft > 0) ? src.at(nbottom, nleft - 1) : 0; 246 | float n3 = (ntop > 0) ? src.at(ntop, nright) : 0; 247 | 248 | float sum = src.at(nbottom, nright) - n3 - n2 + n1; 249 | float mean = sum / nSize; 250 | 251 | smooth_map.at(h, w) = (mean > 255) ? 255 : mean; 252 | } 253 | } 254 | 255 | return smooth_map; 256 | } 257 | 258 | int Yun::push(int *stackx, int *stacky, int arr_size, int vx, int vy, int *top) 259 | { 260 | if (*top >= arr_size) return(-1); 261 | (*top)++; 262 | stackx[*top] = vx; 263 | stacky[*top] = vy; 264 | return 1; 265 | } 266 | 267 | int Yun::pop(int *stackx, int *stacky, int arr_size, int *vx, int *vy, int *top) 268 | { 269 | if (*top == 0) return(-1); 270 | *vx = stackx[*top]; 271 | *vy = stacky[*top]; 272 | (*top)--; 273 | return 1; 274 | } 275 | 276 | std::vector Yun::ccl(cv::Mat &src, cv::Mat &oMap, std::vector &Vmap) 277 | { 278 | std::vector result; 279 | 280 | const cv::Size imSz = src.size(); 281 | cv::Mat mask(imSz, CV_8UC1); mask.setTo(0); 282 | 283 | int *stackx = new int[imSz.width * imSz.height]; 284 | int *stacky = new int[imSz.width * imSz.height]; 285 | 286 | memset(stackx, 0, imSz.width * imSz.height); 287 | memset(stacky, 0, imSz.width * imSz.height); 288 | 289 | int tsize = imSz.width * imSz.height; 290 | int r, c, top, label_id = 0; 291 | 292 | cv::Rect rect; 293 | 294 | for (int h = 1; h < imSz.height - 2; h++) 295 | { 296 | for (int w = 1; w < imSz.width - 2; w++) 297 | { 298 | // skip pixel 299 | if (mask.at(h, w) != 0 || src.at(h, w) < 128) continue; 300 | 301 | // 302 | r = h; 303 | c = w; 304 | rect = cv::Rect(w, h, 0, 0); 305 | 306 | top = 0; 307 | ++label_id; if (label_id > 255) label_id = 1; 308 | 309 | int hist[NUM_ANG] = { 0 }; 310 | 311 | while (true) 312 | { 313 | re: 314 | for (int m = r - 1; m <= r + 1; m++) 315 | { 316 | for (int n = c - 1; n <= c + 1; n++) 317 | { 318 | if ((m < 0) || (m >= imSz.height)) continue; // height ���� ���� 319 | if ((n < 0) || (n >= imSz.width)) continue; // width ���� ���� 320 | 321 | if (mask.at(m, n) != 0 || 322 | src.at(m, n) < 128) continue; 323 | 324 | int bin = oMap.at(m, n); 325 | if (bin >= NUM_ANG) continue; 326 | 327 | mask.at(m, n) = label_id; 328 | hist[bin]++; 329 | 330 | if (push(stackx, stacky, tsize, m, n, &top) == -1) continue; 331 | 332 | r = m; c = n; 333 | rect.x = rect.x > c ? c : rect.x; 334 | rect.y = rect.y > r ? r : rect.y; 335 | rect.width = rect.width > c ? rect.width : c; 336 | rect.height = rect.height > r ? rect.height : r; 337 | goto re; 338 | } 339 | } 340 | 341 | if (pop(stackx, stacky, tsize, &r, &c, &top) == -1) 342 | { 343 | int width = rect.width - rect.x; 344 | int height = rect.height - rect.y; 345 | 346 | if (width > 15 && height > 15) 347 | { 348 | YunLabel val; 349 | 350 | val.roi = cv::Rect(rect.x, rect.y, width, height); 351 | 352 | int max_val = 0; 353 | int ori = 255; 354 | for (int i = 0; i < NUM_ANG; i++) 355 | { 356 | if (max_val < hist[i]) 357 | { 358 | max_val = hist[i]; 359 | ori = i; 360 | } 361 | } 362 | val.max_orientation = ori; 363 | 364 | // check Vmap; 365 | if (Vmap[ori].isStrong) 366 | { 367 | result.push_back(val); 368 | } 369 | } 370 | 371 | break; 372 | } 373 | } 374 | } 375 | } 376 | 377 | delete[]stackx; 378 | delete[]stacky; 379 | 380 | return result; 381 | } 382 | 383 | std::vector Yun::calc_candidate(std::vector &val, cv::Mat &mMap, cv::Mat &oMap) 384 | { 385 | std::vector result; 386 | 387 | for (std::vector::iterator it = val.begin(); it < val.end(); it++) 388 | { 389 | YunCandidate tmp = sub_candidate(*it, mMap, oMap); 390 | if (tmp.isBarcode) 391 | { 392 | // not include paper 393 | YunCandidate new_tmp = calc_region_check(tmp, mMap.size()); 394 | 395 | if (result.empty()) 396 | { 397 | result.push_back(new_tmp); 398 | } 399 | else 400 | { 401 | bool isSave = true; 402 | 403 | cv::Point st = cv::Point(new_tmp.roi.x, new_tmp.roi.y); 404 | cv::Point et = cv::Point(new_tmp.roi.x + new_tmp.roi.width, new_tmp.roi.y + new_tmp.roi.height); 405 | 406 | for (std::vector::iterator rit = result.begin(); rit < result.end(); rit++) 407 | { 408 | cv::Point rst = cv::Point(rit->roi.x, rit->roi.y); 409 | cv::Point ret = cv::Point(rit->roi.x + rit->roi.width, rit->roi.y + rit->roi.height); 410 | 411 | // compare! 412 | //if (new_tmp.roi.contains(rst) || new_tmp.roi.contains(ret) || 413 | // rit->roi.contains(st) || rit->roi.contains(et)) 414 | //{ 415 | if (((et.x >= rst.x) && (et.x <= ret.x) && (st.y >= rst.y) && (st.y <= ret.y)) || 416 | ((st.x >= rst.x) && (st.x <= ret.x) && (st.y >= rst.y) && (st.y <= ret.y)) || 417 | ((et.x >= rst.x) && (et.x <= ret.x) && (et.y >= rst.y) && (et.y <= ret.y)) || 418 | ((st.x >= rst.x) && (st.x <= ret.x) && (et.y >= rst.y) && (et.y <= ret.y)) || 419 | 420 | ((rst.x >= st.x) && (rst.x <= et.x) && (rst.y >= st.y) && (rst.y <= et.y)) || 421 | ((ret.x >= st.x) && (ret.x <= et.x) && (rst.y >= st.y) && (rst.y <= et.y)) || 422 | ((rst.x >= st.x) && (rst.x <= et.x) && (ret.y >= st.y) && (ret.y <= et.y)) || 423 | ((ret.x >= st.x) && (ret.x <= et.x) && (ret.y >= st.y) && (ret.y <= et.y)) 424 | ) 425 | { 426 | // x 427 | if (st.x <= rst.x) rit->roi.x = st.x; 428 | if (et.x >= ret.x) rit->roi.width = et.x; 429 | else rit->roi.width = ret.x; 430 | 431 | // y 432 | if (st.y <= rst.y) rit->roi.y = st.y; 433 | if (et.y >= ret.y) rit->roi.height = et.y; 434 | else rit->roi.height = ret.y; 435 | 436 | rit->roi.width -= rit->roi.x; 437 | rit->roi.height -= rit->roi.y; 438 | 439 | isSave = false; 440 | break; 441 | } 442 | } 443 | 444 | if (isSave) result.push_back(new_tmp); 445 | } 446 | } 447 | } 448 | 449 | return result; 450 | } 451 | 452 | YunCandidate Yun::sub_candidate(YunLabel val, cv::Mat &mMap, cv::Mat &oMap) 453 | { 454 | YunCandidate result; 455 | 456 | cv::Rect roi = val.roi; 457 | cv::Size imSz = mMap.size(); 458 | 459 | // center point 460 | cv::Point_ cPt = cv::Point(roi.x + (roi.width / 2), roi.y + (roi.height / 2)); 461 | 462 | // check dir 463 | double theta; 464 | theta = (CV_PI / NUM_ANG) * (val.max_orientation); 465 | 466 | // step 467 | cv::Point_ step(std::cos(theta), std::sin(theta)); 468 | 469 | // 470 | static cv::Rect limit_area(10, 10, imSz.width - 20, imSz.height - 20); 471 | cv::Rect_ imgRect(limit_area); 472 | 473 | int Nedge = 0; 474 | result.roi = roi; 475 | result.orientation = val.max_orientation; 476 | 477 | // starting from a Point in the middle 478 | // Extend in both directions to find the extend 479 | for (int dir = 0; dir < 2; dir++) 480 | { 481 | int dist = 0; 482 | cv::Point_ curPt = cPt; 483 | cv::Point lastEdge = curPt; 484 | 485 | // change directions 486 | if (dir == 1) step *= -1.0; 487 | 488 | while (imgRect.contains(curPt)) 489 | { 490 | curPt += step; 491 | 492 | // line check 493 | if (mMap.at(curPt) > pam.magT) 494 | { 495 | if (oMap.at(curPt) == val.max_orientation) 496 | { 497 | lastEdge = curPt; 498 | dist = 0; 499 | Nedge++; 500 | } 501 | else if (Nedge > 0) 502 | { 503 | dist++; 504 | Nedge--; 505 | } 506 | } 507 | else if (Nedge > 0) dist++; 508 | 509 | if (dist > 7) 510 | { 511 | if (dir == 1) 512 | result.last_pt = lastEdge; 513 | else 514 | result.first_pt = lastEdge; 515 | 516 | break; 517 | } 518 | } 519 | 520 | // post processing 521 | if (dir == 0) 522 | { 523 | if (result.first_pt.x == 0 && result.first_pt.y == 0) 524 | result.first_pt = lastEdge; 525 | } 526 | else 527 | { 528 | if (result.last_pt.x == 0 && result.last_pt.y == 0) 529 | result.last_pt = lastEdge; 530 | } 531 | } 532 | 533 | int edge_density = cv::norm(result.first_pt - result.last_pt); 534 | 535 | if (Nedge > std::max(pam.minEdgeT, (int)(edge_density * pam.minDensityEdgeT))) 536 | result.isBarcode = true; 537 | else result.isBarcode = false; 538 | 539 | return result; 540 | } 541 | 542 | YunCandidate Yun::calc_region_check(YunCandidate val, cv::Size imSz) 543 | { 544 | YunCandidate new_val = val; 545 | 546 | int margin = 1; 547 | 548 | cv::Point st = cv::Point(val.roi.x, val.roi.y); 549 | cv::Point et = cv::Point(val.roi.x + val.roi.width, val.roi.y + val.roi.height); 550 | 551 | // st 552 | if (st.y >= val.last_pt.y) new_val.roi.y = val.last_pt.y - margin; 553 | else if (st.y >= val.first_pt.y) new_val.roi.y = val.first_pt.y - margin; 554 | else new_val.roi.y = st.y - margin; 555 | 556 | if (new_val.roi.y < 0) new_val.roi.y = 0; 557 | 558 | if (st.x >= val.last_pt.x) new_val.roi.x = val.last_pt.x - margin; 559 | else if (st.x >= val.first_pt.x) new_val.roi.x = val.first_pt.x - margin; 560 | else new_val.roi.x = st.x - margin; 561 | 562 | if (new_val.roi.x < 0) new_val.roi.x = 0; 563 | 564 | // et 565 | if (et.y <= val.last_pt.y) new_val.roi.height = val.last_pt.y + margin; 566 | else if (et.y <= val.first_pt.y) new_val.roi.height = val.first_pt.y + margin; 567 | else new_val.roi.height = et.y + margin; 568 | 569 | if (new_val.roi.height >= imSz.height) new_val.roi.height = imSz.height - 1; 570 | 571 | if (et.x <= val.last_pt.x) new_val.roi.width = val.last_pt.x + margin; 572 | else if (et.x <= val.first_pt.x) new_val.roi.width = val.first_pt.x + margin; 573 | else new_val.roi.width = et.x + margin; 574 | 575 | if (new_val.roi.width >= imSz.width) new_val.roi.width = imSz.width - 1; 576 | 577 | new_val.roi.width -= new_val.roi.x; 578 | new_val.roi.height -= new_val.roi.y; 579 | 580 | return new_val; 581 | } --------------------------------------------------------------------------------