Advertisement
jack06215

[OpenCV] line segment selection

Jul 8th, 2020
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 19.27 KB | None | 0 0
  1. #define NOMAXMIN
  2. #define _USE_MATH_DEFINES
  3. #include <iostream>
  4. #include <opencv2/opencv.hpp>
  5.  
  6. #include <vector>
  7. #include <set>
  8. #include <cerrno>
  9. #include <cmath>
  10. #include <numeric>
  11. #include <limits>
  12.  
  13. #include "lsd.h"
  14. #include "dlib/geometry.h"
  15. #include "dlib/optimization.h"
  16.  
  17.  
  18. #define WIN_TITLE_INPUT "Input"
  19. #define WIN_TTILE_OUTPUT "Output"
  20.  
  21. typedef std::pair<double, int> mypair;
  22. template<typename Iter_T>
  23. float vectorNorm(Iter_T first, Iter_T last)
  24. {
  25.     return sqrt(inner_product(first, last, first, 0.0L));
  26. }
  27. float lsd_angle(std::vector<int>& ls_compared);
  28. bool similarAngle(std::vector<std::vector<int>>& ls12, float athreshold);
  29.  
  30. //std::vector<int> similarAngle(std::vector<std::vector<int>> &ls12, float athreshold);
  31. void resize_image_length(cv::Mat& srcImg, cv::Mat& dstImg, int maxSize);
  32. void lsd_extend(ntuple_list& lsd_out, std::vector<std::vector<float>>& L, dlib::vector<float> center);
  33. bool isEqual(const cv::Vec4i& _l1, const cv::Vec4i& _l2);
  34. void lsd_detection(cv::Mat& srcImg, ntuple_list& lsd_out);
  35.  
  36. #if 1
  37. int main(void)
  38. {
  39.     // Variables define here
  40.     cv::Mat img, img_gray;                      // Color and gray input image
  41.     cv::Mat img_result;                         // Showing result image after lsd
  42.     ntuple_list lsd_out;                        // Line segments vector
  43.     ntuple_list lsd_selected;                   // Selected dominant line segments vector
  44.     // Create windows to show reuslt
  45.     cv::namedWindow(WIN_TTILE_OUTPUT, cv::WINDOW_NORMAL);
  46.     cv::namedWindow(WIN_TITLE_INPUT, cv::WINDOW_NORMAL);
  47.  
  48.     cv::VideoCapture cap(0);
  49.     //cv::VideoCapture cap("http://172.19.127.160:8080/videofeed?dummy=param.mjpg");
  50.     if (!cap.isOpened())
  51.     {
  52.         std::cerr << "cannot open camera during initialisation\n";
  53.         return -1;
  54.     }
  55.     // Configure VideoCapture properties
  56.     cap.set(cv::CAP_PROP_FRAME_WIDTH, 640);
  57.     cap.set(cv::CAP_PROP_FRAME_HEIGHT, 480);
  58.     cap.set(cv::CAP_PROP_FPS, 30);
  59.     cv::waitKey(1000);
  60.  
  61.     dlib::vector<float, 2> center(static_cast<float>(640 / 2), static_cast<float>(360 / 2));
  62.  
  63.     for (;;)
  64.     {
  65.         // Read image and conver to B&W
  66.         cap >> img;
  67.         cv::cvtColor(img, img_gray, cv::COLOR_RGB2GRAY);
  68.  
  69.         // Line segment detection
  70.         lsd_detection(img_gray, lsd_out);
  71.         int no_of_lines = std::min(lsd_out->size, uint(700));
  72.         lsd_selected = new_ntuple_list(5);
  73.         std::vector<std::vector<float>> L;
  74.  
  75.         // Draw lsd result
  76.         cv::Point pt1, pt2;
  77.         int line_width;
  78.         img.copyTo(img_result);
  79.         const unsigned int lsd_dim = lsd_out->dim;
  80.         std::vector<cv::Vec4i> lsd_vec;
  81.         std::vector<int> labels;
  82.         for (int i = 0; i < no_of_lines; i++)
  83.         {
  84.             cv::Vec4i lsd_tmp;
  85.             lsd_tmp[0] = (int)lsd_out->values[0 + i * lsd_dim];
  86.             lsd_tmp[1] = (int)lsd_out->values[1 + i * lsd_dim];
  87.             lsd_tmp[2] = (int)lsd_out->values[2 + i * lsd_dim];
  88.             lsd_tmp[3] = (int)lsd_out->values[3 + i * lsd_dim];
  89.  
  90.             lsd_vec.push_back(lsd_tmp);
  91.  
  92.             // The first four elements in ntuple_list are [x1 y1 x2 y2] point that define the location of line segment
  93.             pt1.x = (int)lsd_out->values[0 + i * lsd_dim];
  94.             pt1.y = (int)lsd_out->values[1 + i * lsd_dim];
  95.             pt2.x = (int)lsd_out->values[2 + i * lsd_dim];
  96.             pt2.y = (int)lsd_out->values[3 + i * lsd_dim];
  97.  
  98.             // The 5th element is the width of line segment
  99.             line_width = 2;// (int)lsd_out->values[4 + i * lsd_dim];
  100.             //cv::line(img_result, pt1, pt2, cv::Scalar(0, 255, 255), line_width, CV_AA);
  101.         }
  102.  
  103.         // Label out the unique subset ID for each the line segment belings to
  104.         int numberOfLines = cv::partition(lsd_vec, labels, isEqual);
  105.  
  106.         std::vector<std::pair<int, std::vector<int>>> lsd_label_table;
  107.         std::vector<std::pair<int, int>> lsd_label;
  108.  
  109.         // Construct a LUT for each line segment w.r.t. its belonging set index.
  110.         for (int i = 0; i < labels.size(); i++)
  111.         {
  112.             std::pair<int, int> freq_count_tmp;
  113.             freq_count_tmp = std::make_pair(labels.at(i), i);
  114.             lsd_label.push_back(freq_count_tmp);
  115.  
  116.         }
  117.         std::sort(lsd_label.begin(), lsd_label.end());
  118.  
  119.         if (lsd_label.size() > 2)
  120.         {
  121.             // Sort out the set index w.r.t. its corresponding line segment index
  122.             int current = lsd_label.at(0).first;
  123.             std::vector<int> freq_sorted;
  124.             std::pair<int, std::vector<int>> freq_pushed;
  125.             std::vector<std::pair<int, int>> freq_count;
  126.             int size = lsd_label.size();
  127.             int set_idx = 0;
  128.             for (int i = 0; i < size - 1; i++)
  129.             {
  130.                 freq_sorted.push_back(lsd_label.at(i).second);
  131.                 current = lsd_label.at(i).first;
  132.                 if (current != lsd_label.at(i + 1).first)
  133.                 {
  134.                     freq_pushed.first = set_idx;
  135.                     freq_pushed.second.swap(freq_sorted);
  136.                     lsd_label_table.push_back(freq_pushed);
  137.                     freq_sorted.clear();
  138.                     set_idx++;
  139.                 }
  140.             }
  141.  
  142.             for (int i = 0; i < lsd_label_table.size(); i++)
  143.             {
  144.                 std::pair<int, int> tmp = std::make_pair(lsd_label_table.at(i).second.size(), lsd_label_table.at(i).first);
  145.                 freq_count.push_back(tmp);
  146.             }
  147.             std::sort(freq_count.rbegin(), freq_count.rend());
  148.  
  149.  
  150.             // Select the most dominant line segment: pick the most the the second most dominant inedex.
  151.             int lsd_select_threshold = static_cast<int>(freq_count.at(0).first * 0.8f);
  152.             std::cout << "selection threshold: " << lsd_select_threshold << '\n';
  153.             std::vector<int> lsd_selected_idx;
  154.             bool isDone = false;
  155.             lsd_selected_idx.push_back(freq_count.at(0).second);
  156.             lsd_selected_idx.push_back(freq_count.at(1).second);
  157.  
  158.  
  159. #if 0
  160.             // In some cases, we can also select the thrid and preceeding ones if the count is above some threshold
  161.             int selected_idx = 2;
  162.             while (!isDone)
  163.             {
  164.                 int count_tmp = freq_count.at(selected_idx).first;
  165.                 if (count_tmp > lsd_select_threshold)
  166.                 {
  167.                     lsd_selected_idx.push_back(freq_count.at(selected_idx).second);
  168.                 }
  169.                 else
  170.                 {
  171.                     isDone = true;
  172.                 }
  173.                 selected_idx++;
  174.             }
  175. #endif
  176.  
  177.             lsd_vec.clear();
  178.  
  179.             // For all selected line segments
  180.             for (int i = 0; i < lsd_selected_idx.size(); i++)
  181.             {
  182.                 int idxx = lsd_selected_idx.at(i);
  183.                 for (int j = 0; j < lsd_label_table.at(idxx).second.size(); j++)
  184.                 {
  185.                     int idx = lsd_label_table.at(idxx).second.at(j);
  186.                     cv::Vec4i lsd_tmp;
  187.                     lsd_tmp[0] = (int)lsd_out->values[0 + idx * lsd_dim];
  188.                     lsd_tmp[1] = (int)lsd_out->values[1 + idx * lsd_dim];
  189.                     lsd_tmp[2] = (int)lsd_out->values[2 + idx * lsd_dim];
  190.                     lsd_tmp[3] = (int)lsd_out->values[3 + idx * lsd_dim];
  191.                     lsd_vec.push_back(lsd_tmp);
  192.  
  193.                     struct rect
  194.                     {
  195.                         double x1, y1, x2, y2; /* first and second point of the line segment */
  196.                         double width;        /* rectangle width */
  197.                     }rec;
  198.  
  199.  
  200.  
  201.                     rec.x1 = lsd_out->values[0 + idx * lsd_dim];
  202.                     rec.y1 = lsd_out->values[1 + idx * lsd_dim];
  203.                     rec.x2 = lsd_out->values[2 + idx * lsd_dim];
  204.                     rec.y2 = lsd_out->values[3 + idx * lsd_dim];
  205.                     rec.width = lsd_out->values[4 + idx * lsd_dim];
  206.                     add_5tuple(lsd_selected, rec.x1, rec.y1, rec.x2, rec.y2, rec.width);
  207.  
  208.  
  209. #if 0
  210.                     pt1.x = (int)lsd_out->values[0 + idx * lsd_dim];
  211.                     pt1.y = (int)lsd_out->values[1 + idx * lsd_dim];
  212.                     pt2.x = (int)lsd_out->values[2 + idx * lsd_dim];
  213.                     pt2.y = (int)lsd_out->values[3 + idx * lsd_dim];
  214.  
  215.                     // The 5th element is the width of line segment
  216.                     line_width = 2;// (int)lsd_out->values[4 + i * lsd_dim];
  217.                     cv::line(img_result, pt1, pt2, cv::Scalar(0, 0, 255), 5, CV_AA);
  218. #endif
  219.                 }
  220.             }
  221.  
  222. #if 1
  223.             // Draw the all line segments
  224.             for (int i = 0; i < labels.size(); i++)
  225.             {
  226.                 // The first four elements in ntuple_list are [x1 y1 x2 y2] point that define the location of line segment
  227.                 pt1.x = (int)lsd_out->values[0 + i * lsd_dim];
  228.                 pt1.y = (int)lsd_out->values[1 + i * lsd_dim];
  229.                 pt2.x = (int)lsd_out->values[2 + i * lsd_dim];
  230.                 pt2.y = (int)lsd_out->values[3 + i * lsd_dim];
  231.  
  232.                 // The 5th element is the width of line segment
  233.                 line_width = 2;// (int)lsd_out->values[4 + i * lsd_dim];
  234.                 cv::line(img_result, pt1, pt2, cv::Scalar(0, 255, 0), line_width, cv::LINE_AA);
  235.             }
  236. #endif
  237.  
  238.             // Line selection is done!!!
  239.             // Line gap filling
  240.             std::vector<int> lsd_mergelist;
  241.             std::vector<std::vector<int>> ls12;
  242.             float athreshold = 2;
  243.             float dthreshold = 10;
  244.  
  245.  
  246.             ls12.resize(2);
  247.             for (int i = 0; i < 2; i++)
  248.                 ls12[i].resize(4);
  249.  
  250.             for (int i = 0; i < lsd_selected->size - 1; i++)
  251.             {
  252.                 // ls1 pt1
  253.                 ls12[0][0] = (int)lsd_selected->values[0 + i * lsd_dim];
  254.                 ls12[1][0] = (int)lsd_selected->values[1 + i * lsd_dim];
  255.  
  256.                 // ls1 pt2
  257.                 ls12[0][1] = (int)lsd_selected->values[2 + i * lsd_dim];
  258.                 ls12[1][1] = (int)lsd_selected->values[3 + i * lsd_dim];
  259.                 for (int j = i + 1; j < lsd_selected->size; j++)
  260.                 {
  261.                     // ls2 pt1
  262.                     ls12[0][2] = (int)lsd_selected->values[0 + j * lsd_dim];
  263.                     ls12[1][2] = (int)lsd_selected->values[1 + j * lsd_dim];
  264.  
  265.                     // ls2 pt2
  266.                     ls12[0][3] = (int)lsd_selected->values[2 + j * lsd_dim];
  267.                     ls12[1][3] = (int)lsd_selected->values[3 + j * lsd_dim];
  268.  
  269.                     bool test = similarAngle(ls12, athreshold);
  270.                     if (test)
  271.                     {
  272.                         lsd_mergelist.push_back(j);
  273.                     }
  274.                 }
  275.                 bool mergelist = static_cast<bool>(std::accumulate(lsd_mergelist.begin(), lsd_mergelist.end(), 0));
  276.                 if (mergelist)
  277.                 {
  278.                     int maxx, maxy, minx, miny = 0;
  279.  
  280.  
  281.                     // 1. grab the corresponding merge ls. First one is the current ls followed by a set of potential merging ones.
  282.                     ls12.resize(4);
  283.                     for (int i = 0; i < 4; i++)
  284.                         ls12[i].resize(1 + lsd_mergelist.size());
  285.  
  286.                     ls12[0][0] = (int)lsd_selected->values[0 + i * lsd_dim];    // x1
  287.                     ls12[1][0] = (int)lsd_selected->values[1 + i * lsd_dim];    // y1
  288.                     ls12[2][0] = (int)lsd_selected->values[2 + i * lsd_dim];    // x2
  289.                     ls12[3][0] = (int)lsd_selected->values[3 + i * lsd_dim];    // y2
  290.  
  291.  
  292.                     int idx = 1;
  293.                     for (int i = 0; i < lsd_mergelist.size(); i++)
  294.                     {
  295.                         int idxx = lsd_mergelist.at(i);
  296.                         ls12[0][idx] = (int)lsd_selected->values[0 + idxx * lsd_dim];
  297.                         ls12[1][idx] = (int)lsd_selected->values[1 + idxx * lsd_dim];
  298.                         ls12[2][idx] = (int)lsd_selected->values[2 + idxx * lsd_dim];
  299.                         ls12[3][idx] = (int)lsd_selected->values[3 + idxx * lsd_dim];
  300.                         idx++;
  301.                     }
  302.  
  303.                     // 2. sort the segments on the line, by their "left" endpoint
  304.                     for (int i = 0; i < ls12[0].size(); i++)
  305.                     {
  306.  
  307.                     }
  308.  
  309.  
  310.                     //std::cout << "merging\n";
  311.                 }
  312.  
  313.                 // TODO: Update lsd_selected ()
  314.  
  315.                 //std::cout << '[';
  316.                 //for (int i = 0; i < lsd_mergelist.size(); i++)
  317.                 //{
  318.                 //  std::cout << lsd_mergelist.at(i) << ", ";
  319.                 //}
  320.                 //std::cout << "\b\b]\n";
  321.                 lsd_mergelist.clear();
  322.                 //cv::waitKey(1);
  323.             }
  324.             //std::cout << "\n------------------------------\n";
  325.  
  326.  
  327.             lsd_extend(lsd_selected, L, center);
  328.  
  329.             int no_of_lines = static_cast<int>(lsd_selected->size);
  330.             for (int j = 0; j < no_of_lines; j++)
  331.             {
  332.                 float x1 = L[0][j];
  333.                 float y1 = L[1][j];
  334.                 float x2 = L[2][j];
  335.                 float y2 = L[3][j];
  336.  
  337.                 pt1.x = int(x1);
  338.                 pt1.y = int(y1);
  339.                 pt2.x = int(x2);
  340.                 pt2.y = int(y2);
  341.                 float width = 2;// int(lsd_out->values[4 + j * lsd_out->dim]);
  342.                 cv::line(img, pt1, pt2, cv::Scalar(0, 255, 255), width, cv::LINE_AA);
  343.             }
  344.         }
  345.  
  346.         // Show result
  347.         cv::imshow(WIN_TITLE_INPUT, img);
  348.         cv::imshow(WIN_TTILE_OUTPUT, img_result);
  349.  
  350.  
  351.         // Free up memory
  352.         L.clear();
  353.         free_ntuple_list(lsd_out);
  354.         free_ntuple_list(lsd_selected);
  355.         if (cv::waitKey(1) == 27)
  356.             break;
  357.     }
  358.  
  359.     return 0;
  360. }
  361. #endif
  362.  
  363.  
  364. bool similarAngle(std::vector<std::vector<int>>& ls12, float athreshold)
  365. {
  366.     bool rtn = true;
  367.     std::vector<int> chk_book;
  368.     std::vector<std::vector<int>> comb{ { 0, 1, 2, 3 },
  369.                                         { 0, 1, 0, 2 },
  370.                                         { 0, 1, 0, 3 },
  371.                                         { 0, 1, 1, 2 },
  372.                                         { 0, 1, 1, 3 },
  373.                                         { 2, 3, 2, 0 },
  374.                                         { 2, 3, 2, 1 },
  375.                                         { 2, 3, 3, 0 },
  376.                                         { 2, 3, 3, 1 } };
  377.  
  378.     std::vector<int> ls_compared;
  379.  
  380.     ls_compared.resize(8);
  381.  
  382.  
  383.     for (int i = 0; i < comb.size(); i++)
  384.     {
  385.         bool tmp;
  386.         // ls1
  387.         ls_compared[0] = ls12[0][comb[i][0]];   // x1
  388.         ls_compared[1] = ls12[1][comb[i][0]];   // y1
  389.         ls_compared[2] = ls12[0][comb[i][1]];   // x2
  390.         ls_compared[3] = ls12[1][comb[i][1]];   // y2
  391.  
  392.                                                 // ls2
  393.         ls_compared[4] = ls12[0][comb[i][2]];   // x1
  394.         ls_compared[5] = ls12[1][comb[i][2]];   // y1
  395.         ls_compared[6] = ls12[0][comb[i][3]];   // x2
  396.         ls_compared[7] = ls12[1][comb[i][3]];   // y2
  397.  
  398.  
  399.                                                 // measure cos similarity
  400.         float theta = lsd_angle(ls_compared);
  401.         float threshold = std::cos(athreshold * M_PI / 180);
  402.         threshold *= threshold;
  403.         //std::cout << "theta: " << theta << '\t' << threshold << '\n';
  404.         if (theta < threshold) return false;
  405.         //chk_book.push_back(tmp);
  406.     }
  407.     return true;
  408. }
  409.  
  410. float lsd_angle(std::vector<int>& ls_compared)
  411. {
  412.     std::vector<float> ls1_vector;
  413.     std::vector<float> ls2_vector;
  414.     float theta = 0.0f;
  415.  
  416.     ls1_vector.resize(2);
  417.     ls2_vector.resize(2);
  418.  
  419.     // convert points to vector form
  420.     // (x2 - x1, y2 - y1) / norm((x2 - x1, y2 - y1))
  421.     ls1_vector[0] = std::abs((ls_compared[2] - ls_compared[0]));
  422.     ls1_vector[1] = std::abs((ls_compared[3] - ls_compared[1]));
  423.     ls2_vector[0] = std::abs((ls_compared[6] - ls_compared[4]));
  424.     ls2_vector[1] = std::abs((ls_compared[7] - ls_compared[5]));
  425.  
  426.     float norm = std::sqrt(ls1_vector[0] * ls1_vector[0] + ls1_vector[1] * ls1_vector[1]);
  427.     ls1_vector[0] /= norm;
  428.     ls1_vector[1] /= norm;
  429.     norm = std::sqrt(ls2_vector[0] * ls2_vector[0] + ls2_vector[1] * ls2_vector[1]);
  430.     ls2_vector[0] /= norm;
  431.     ls2_vector[1] /= norm;
  432.     for (int k = 0; k < 2; k++)
  433.     {
  434.         theta += ls1_vector[k] * ls2_vector[k];
  435.     }
  436.     theta *= theta;
  437.     return theta;
  438. }
  439.  
  440.  
  441.  
  442.  
  443. void resize_image_length(cv::Mat& srcImg, cv::Mat& dstImg, int maxSize)
  444. {
  445.     //cv::Mat myImg = srcImg;
  446.     if (std::max(srcImg.rows, srcImg.cols) > 1000)
  447.     {
  448.         std::cout << "over sized frame, scale down needed" << std::endl;
  449.         float s = float(1000) / std::max(srcImg.rows, srcImg.cols);
  450.         cv::resize(srcImg, dstImg, cv::Size(srcImg.cols * s, srcImg.rows * s), 0, 0, cv::INTER_LINEAR);
  451.         //std::cout << my_image_copy.cols << " x " << my_image_copy.rows << std::endl;
  452.         //my_image_copy.copyTo(output_image);
  453.     }
  454.     else
  455.     {
  456.         srcImg.copyTo(dstImg);
  457.     }
  458. }
  459.  
  460. void lsd_extend(ntuple_list& lsd_out, std::vector<std::vector<float>>& L, dlib::vector<float> center)
  461. {
  462.     float extension_fac = 0.5f;         // Line Extension factor, the larger the number the longer LSD extend.
  463.     bool talk = false;
  464.     std::vector<mypair> line_lengths;
  465.     float sqd_distance;
  466.     float x1, x2, y1, y2;
  467.     int size = lsd_out->size;
  468.     int dim = lsd_out->dim;
  469.     //for (int j = 0; j < (size * dim); j = j + 5)
  470.     //{
  471.     //  x1 = lsd_out->values[j];
  472.     //  x2 = lsd_out->values[j + 1];
  473.     //  y1 = lsd_out->values[j + 2];
  474.     //  y2 = lsd_out->values[j + 3];
  475.     //  sqd_distance = (x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1);
  476.     //  line_lengths.push_back(std::make_pair(sqd_distance, j));
  477.     //}
  478.     //std::sort(line_lengths.begin(), line_lengths.end());
  479.     //std::reverse(line_lengths.begin(), line_lengths.end());
  480.  
  481.     //if (talk) std::cout << line_lengths[0].first << " " << line_lengths[0].second << " " << line_lengths[1].first << " " << line_lengths[1].second << std::endl;
  482.     ////cv::waitKey(1000);
  483.  
  484.     uint no_of_lines = std::min((uint)size, uint(700));
  485.     //std::cout << "Number of lines: " << no_of_lines << std::endl;
  486.  
  487.     L.resize(4);
  488.     int lsd_dim = lsd_out->dim;
  489.     for (int i = 0; i < 4; i++)
  490.         L[i].resize(no_of_lines);
  491.  
  492.     for (int j = 0; j < no_of_lines; j++)
  493.     {
  494.         //mypair tmp = line_lengths[j];
  495.         //L[0][j] = lsd_out->values[tmp.second];
  496.         //L[1][j] = lsd_out->values[tmp.second + 1];
  497.         //L[2][j] = lsd_out->values[tmp.second + 2];
  498.         //L[3][j] = lsd_out->values[tmp.second + 3];
  499.  
  500.         L[0][j] = (int)lsd_out->values[0 + j * lsd_dim];
  501.         L[1][j] = (int)lsd_out->values[1 + j * lsd_dim];
  502.         L[2][j] = (int)lsd_out->values[2 + j * lsd_dim];
  503.         L[3][j] = (int)lsd_out->values[3 + j * lsd_dim];
  504.     }
  505.     // LINE EXTNESION
  506.     float line_length;
  507.     float line_gradient;
  508.     float rise_angle;
  509.     float delta_x;
  510.     float delta_y;
  511.  
  512.     for (int j = 0; j < no_of_lines; j++) {
  513.         x1 = L[0][j];
  514.         y1 = L[1][j];
  515.         x2 = L[2][j];
  516.         y2 = L[3][j];
  517.         line_length = std::sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
  518.         line_gradient = (y2 - y1) / (x2 - x1);
  519.         rise_angle = std::atan(std::abs(line_gradient));
  520.         delta_x = std::cos(rise_angle) * (line_length * extension_fac);
  521.         delta_y = std::sin(rise_angle) * (line_length * extension_fac);
  522.  
  523.         if (line_gradient < 0)
  524.         {
  525.             if (x1 > x2)
  526.             {
  527.                 L[0][j] += delta_x;
  528.                 L[1][j] -= delta_y;
  529.                 L[2][j] -= delta_x;
  530.                 L[3][j] += delta_y;
  531.             }
  532.             else
  533.             {
  534.                 L[2][j] += delta_x;
  535.                 L[3][j] -= delta_y;
  536.                 L[0][j] -= delta_x;
  537.                 L[1][j] += delta_y;
  538.             }
  539.         }
  540.         else
  541.         {
  542.             if (x1 > x2)
  543.             {
  544.                 L[0][j] += delta_x;
  545.                 L[1][j] += delta_y;
  546.                 L[2][j] -= delta_x;
  547.                 L[3][j] -= delta_y;
  548.             }
  549.             else
  550.             {
  551.                 L[2][j] += delta_x;
  552.                 L[3][j] += delta_y;
  553.                 L[0][j] -= delta_x;
  554.                 L[1][j] -= delta_y;
  555.             }
  556.         }
  557.         x1 = L[0][j];
  558.         y1 = L[1][j];
  559.         x2 = L[2][j];
  560.         y2 = L[3][j];
  561.  
  562.         //L[2][j] -= center.x(); //Move Origin to the Principle Point
  563.         //L[3][j] -= center.y();
  564.         //L[0][j] -= center.x();
  565.         //L[1][j] -= center.y();
  566.     }
  567.     line_lengths.clear();
  568. }
  569.  
  570.  
  571. bool isEqual(const cv::Vec4i& _l1, const cv::Vec4i& _l2)
  572. {
  573.     cv::Vec4i l1(_l1), l2(_l2);
  574.  
  575.     float length1 = sqrtf((l1[2] - l1[0]) * (l1[2] - l1[0]) + (l1[3] - l1[1]) * (l1[3] - l1[1]));
  576.     float length2 = sqrtf((l2[2] - l2[0]) * (l2[2] - l2[0]) + (l2[3] - l2[1]) * (l2[3] - l2[1]));
  577.  
  578.     float product = (l1[2] - l1[0]) * (l2[2] - l2[0]) + (l1[3] - l1[1]) * (l2[3] - l2[1]);
  579.  
  580.     if (fabs(product / (length1 * length2)) < cos(CV_PI / 180))
  581.         return false;
  582.  
  583.     float mx1 = (l1[0] + l1[2]) * 0.5f;
  584.     float mx2 = (l2[0] + l2[2]) * 0.5f;
  585.  
  586.     float my1 = (l1[1] + l1[3]) * 0.5f;
  587.     float my2 = (l2[1] + l2[3]) * 0.5f;
  588.     float dist = sqrtf((mx1 - mx2) * (mx1 - mx2) + (my1 - my2) * (my1 - my2));
  589.  
  590.     if (dist > std::max(length1, length2) * 0.9f)
  591.         return false;
  592.  
  593.     return true;
  594. }
  595.  
  596. void lsd_detection(cv::Mat& srcImg, ntuple_list& lsd_out)
  597. {
  598.     bool talk = false;
  599.     bool verbose = false;
  600.     // Converting image to image double
  601.     image_double dub_image;
  602.     uint w = srcImg.cols;
  603.     uint h = srcImg.rows;
  604.     uchar* imgP = srcImg.data;
  605.  
  606.     // All parameters defined here
  607.     //      1.LSD parameters
  608.     double scale = 0.8;       // Scale the image by Gaussian filter to 'scale'.
  609.     double sigma_scale = 0.6; // Sigma for Gaussian filter is computed as sigma = sigma_scale/scale.
  610.     double quant = 2.0;       // Bound to the quantization error on the gradient norm.
  611.     double ang_th = 22.5;     // Gradient angle tolerance in degrees.
  612.     double eps = 0.0;         // Detection threshold, -log10(NFA).
  613.     double density_th = 0.7;  // Minimal density of region points in rectangle.
  614.     int n_bins = 1024;        // Number of bins in pseudo-ordering of gradient modulus.
  615.     double max_grad = 255.0;  // Gradient modulus in the highest bin. The default value corresponds to the highest
  616.                               // gradient modulus on images with gray levels in [0,255].
  617.                               //        2. Other flags and parameters
  618.     double athreshadj = 10;             // Threshold defining whether a pair of lsd are potentially orthogonal.
  619.     float extension_fac = 0.5f;         // Line Extension factor, the larger the number the longer LSD extend.
  620.  
  621.     dub_image = new_image_double(w, h);
  622.     double px = 0;
  623.     if (talk) std::cout << "\n-----------\nInput data being written to image buffer" << std::endl;
  624.     for (int j = 0; j < (w * h); j++)
  625.     {
  626.         px = imgP[j];
  627.         dub_image->data[j] = px;
  628.         if (verbose)    std::cout << " " << dub_image->data[j];
  629.     }
  630.     lsd_out = LineSegmentDetection(dub_image, scale, sigma_scale, quant, ang_th, eps, density_th, n_bins, max_grad, nullptr);
  631.     free_image_double(dub_image);
  632. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement