Advertisement
Guest User

Untitled

a guest
Jul 23rd, 2017
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.58 KB | None | 0 0
  1.  
  2. #include <stdio.h>
  3. #include <opencv2/opencv.hpp>
  4. #include <iostream>
  5. #include <vector>
  6. #include <set>
  7. #include <queue>
  8. #include <string>
  9.  
  10. using namespace std;
  11. using namespace cv;
  12.  
  13. enum class HoughType {
  14.     LINES,
  15.     CIRCLES,
  16. };
  17.  
  18. struct Cell {
  19.     int row;
  20.     int col;
  21.     Cell(int row = -1, int col = -1): row(row), col(col) {};
  22. };
  23.  
  24. struct IPoint {
  25.     int value;
  26.     Cell cell;
  27.     int angle;
  28.     IPoint(int value, Cell cell): value(value), cell(cell) {};
  29.     bool operator < (const IPoint& r) const { return value > r.value; }
  30. };
  31.  
  32. struct Params {
  33.     int phi;
  34.     int r;
  35.     Params(int phi, int r): phi(phi), r(r) {};
  36.     bool operator < (const Params& right) const { return make_pair(r, phi) < make_pair(right.r, right.phi); }
  37. };
  38.  
  39. struct Bfs {
  40.  
  41.     Mat used;
  42.     Mat mat;
  43.     vector <Mat> debug;
  44.     vector <vector <Cell>> components;
  45.  
  46.     Bfs(Mat& mat): mat(mat) {
  47.         used = Mat::zeros(mat.rows, mat.cols, CV_32SC1);
  48.     }
  49.  
  50.  
  51.     void bfs(Cell s) {
  52.  
  53.         int dcols[4] = {1, 0, -1, 0};
  54.         int drows[4] = {0, 1, 0, -1};
  55.         vector<Cell> res;
  56.         queue<Cell> q;
  57.         q.push(s);
  58.         used.at<int>(s.row, s.col) = 1;
  59.         while (!q.empty()) {
  60.             Cell cell = q.front();
  61.             res.push_back(cell);
  62.             q.pop();
  63.             // cout << cell.row << "   " << cell.col << endl;
  64.             for (int i = 0; i < 4; i++) {
  65.                 int drow = cell.row + drows[i];
  66.                 int dcol = cell.col + dcols[i];
  67.                 if (drow >= 0 && drow < mat.rows && dcol >= 0 && dcol < mat.cols &&
  68.                     used.at<int>(drow, dcol) == 0 && mat.at<uchar>(drow, dcol) > 0) {
  69.                     used.at<int>(drow, dcol) = 1;
  70.                     q.push(Cell(drow, dcol));
  71.                 }
  72.             }
  73.         }
  74.  
  75.         Mat tmp;
  76.         if (res.size() > 20) {
  77.             cvtColor(mat, tmp, CV_GRAY2RGB);
  78.             for (auto cell : res) {
  79.                 tmp.at<Vec3b>(cell.row, cell.col)[0] = 0;
  80.                 tmp.at<Vec3b>(cell.row, cell.col)[1] = 0;
  81.                 tmp.at<Vec3b>(cell.row, cell.col)[2] = 255;
  82.             }
  83.             debug.push_back(tmp);
  84.             components.push_back(res);
  85.         }
  86.     }
  87.  
  88.     void start() {
  89.         for (int i = 0; i < mat.rows; i++) {
  90.             for (int j = 0; j < mat.cols; j++) {
  91.                 if (used.at<int>(i, j) == 0 && mat.at<uchar>(i, j) > 0) {
  92.                     bfs(Cell(i, j));
  93.                 }
  94.             }
  95.         }
  96.     }
  97. };
  98.  
  99. Mat intToUchar(const Mat& mat) {
  100.     double _min = 0, _max = 0;
  101.     minMaxLoc(mat, &_min, &_max);
  102.  
  103.     Mat res = Mat::zeros(mat.rows, mat.cols, CV_8UC1);
  104.     // assert (_max > 0);
  105.     if (_max <= 0) {
  106.         return res;
  107.     }
  108.     for (int i = 0; i < mat.rows; i++) {
  109.         for (int j = 0; j < mat.cols; j++) {
  110.             res.at<uchar>(i, j) = (255 * mat.at<int>(i, j)) / (int)_max;
  111.         }
  112.     }
  113.     return res;
  114. }
  115.  
  116. Mat intToUcharGlobalMax(const Mat& mat, int _max) {
  117.    
  118.     Mat res = Mat::zeros(mat.rows, mat.cols, CV_8UC1);
  119.     // assert (_max > 0);
  120.     if (_max <= 0) {
  121.         return res;
  122.     }
  123.     for (int i = 0; i < mat.rows; i++) {
  124.         for (int j = 0; j < mat.cols; j++) {
  125.             res.at<uchar>(i, j) = (255 * mat.at<int>(i, j)) / (int)_max;
  126.         }
  127.     }
  128.     return res;
  129. }
  130.  
  131. void threshHold(Mat& mat, uchar value) {
  132.     for (int i = 0; i < mat.rows; i++) {
  133.         for (int j = 0; j < mat.cols; j++) {
  134.             if (mat.at<uchar>(i, j) < value) {
  135.                 mat.at<uchar>(i, j) = 0;
  136.             }
  137.         }
  138.     }
  139. }
  140.  
  141. void drawLine(set <Params> lines, Mat& rgb, int offset) {
  142.     for (auto line_ : lines) {
  143.         double r = line_.r - offset, phi = line_.phi;
  144.        
  145.         Point pt1, pt2;
  146.         double phi_rad = (phi * CV_PI) / 180.0;
  147.         // phi = (phi_rad * 180.0) / cv_pi;
  148.         double a = cos(phi_rad), b = sin(phi_rad);
  149.         double x0 = a*r, y0 = b*r;
  150.         pt1.x = cvRound(x0 + 1000*(-b));
  151.         pt1.y = cvRound(y0 + 1000*(a));
  152.         pt2.x = cvRound(x0 - 1000*(-b));
  153.         pt2.y = cvRound(y0 - 1000*(a));
  154.         line(rgb, pt1, pt2, Scalar(0,0,255), 3);
  155.     }
  156. }
  157.  
  158. set <Params> findLocalMax(const Mat& mat, int windowSize) {
  159.     assert(windowSize <= mat.rows);
  160.     assert(windowSize <= mat.cols);
  161.     set <Params> res;
  162.     for (int i = windowSize; i <= mat.rows - windowSize; i += 1) {
  163.         for (int j = windowSize; j <= mat.cols - windowSize; j += 1) {
  164.             Rect roi(j - windowSize, i - windowSize, windowSize * 2, windowSize * 2);
  165.  
  166.             Mat roiMat = mat(roi);
  167.  
  168.             double _min, _max;
  169.             Point minLoc, maxLoc;
  170.             minMaxLoc(roiMat, &_min, &_max, &minLoc, &maxLoc);
  171.  
  172.             for (int k = i - windowSize; k < i + windowSize; k++) {
  173.                 for (int l = j - windowSize; l < j + windowSize; l++) {
  174.                     if ((maxLoc.x + (j - windowSize) == l) && (maxLoc.y + (i - windowSize) == k)) {
  175.                         if (mat.at<uchar>(k, l) > 0) {
  176.                             res.emplace(k, l);
  177.                         }
  178.                     }
  179.                 }
  180.             }
  181.         }
  182.     }
  183.     return res;
  184. }
  185.  
  186. Mat FindEdges(const Mat& mat, Mat& angles, HoughType houghType) {
  187.     Mat deltaI = Mat::zeros(mat.rows - 1, mat.cols - 1, CV_32SC1);
  188.     vector<IPoint> filtering;
  189.  
  190.     int dx = 0;
  191.     int dy = 0;
  192.     int tmp = 0;
  193.  
  194.     angles = Mat::zeros(deltaI.rows, deltaI.cols, CV_32SC1);
  195.  
  196.     for (int i = 0; i < mat.rows - 1; i++) {
  197.         for (int j = 0; j < mat.cols - 1; j++) {
  198.  
  199.             dx = (int)mat.at<uchar>(i, j) - (int)mat.at<uchar>(i, j + 1);
  200.             dy = (int)mat.at<uchar>(i, j) - (int)mat.at<uchar>(i + 1, j);
  201.             tmp = dx * dx + dy * dy;
  202.             double alpha = atan2(dy, dx);
  203.  
  204.             if (houghType == HoughType::LINES && alpha < 0) {
  205.                 alpha += CV_PI;
  206.             }
  207.  
  208.             int alpha_grad = (alpha * 180.0) / CV_PI;
  209.             // cout << alpha_grad << endl;
  210.             angles.at<int>(i, j) = alpha_grad;
  211.             deltaI.at<int>(i, j) = tmp;
  212.             filtering.push_back(IPoint(tmp, Cell(i, j)));
  213.         }
  214.     }
  215.  
  216.     Mat deltaIConvert = intToUchar(deltaI);
  217.  
  218.     sort(filtering.begin(), filtering.end());
  219.  
  220.     vector<IPoint> filtered = vector<IPoint>(filtering.begin(), filtering.begin() + filtering.size() * 0.05);
  221.  
  222.     Mat edges = Mat::zeros(deltaI.rows, deltaI.cols, CV_32SC1);
  223.  
  224.     for (auto point: filtered) {
  225.         edges.at<int>(point.cell.row, point.cell.col) = point.value;
  226.     }
  227.  
  228.     Mat edgesChar = intToUchar(edges);
  229.  
  230.     return edgesChar;
  231. }
  232.  
  233. Mat HoughLineMy(const Mat& I, Mat& edgesChar, int& offset, Mat& angles) {
  234.     int phi = 180;
  235.     offset = cvRound(sqrt((double)(I.rows * I.rows + I.cols * I.cols)));
  236.  
  237.     Mat C = Mat::zeros(phi + 1, offset * 2, CV_32SC1);
  238.  
  239.     for (int i = 0; i < edgesChar.rows; i++) {
  240.         for (int j = 0; j < edgesChar.cols; j++) {
  241.             if (edgesChar.at<uchar>(i, j) == 0) {
  242.                 continue;
  243.             }
  244.  
  245.             int curAngle = angles.at<int>(i, j);
  246.             int bound = 5;
  247.             int start = (curAngle <= bound) ? 0 : curAngle - bound;
  248.             int finish = (curAngle + bound >= 180) ? 180 : curAngle + bound;
  249.  
  250.             // cout << start << "   " << curAngle << "   " << finish << endl;
  251.  
  252.             for (int angle = start; angle < finish; angle++) {
  253.                 double theta = (angle * CV_PI) / 180.0;
  254.                 int cur_r = i * sin(theta) + j * cos(theta);
  255.                 C.at<int>(angle, cur_r + offset)++;
  256.             }
  257.         }
  258.     }
  259.  
  260.     Mat H = intToUchar(C);
  261.  
  262.     return H;
  263. }
  264.  
  265. Mat HoughCirclesMy(const Mat& I, Mat& edgesChar, int R, Mat& angles) {
  266.  
  267.     Mat C = Mat::zeros(I.rows, I.cols, CV_32SC1);
  268.  
  269.     for (int i = 0; i < edgesChar.rows; i++) {
  270.         for (int j = 0; j < edgesChar.cols; j++) {
  271.             if (edgesChar.at<uchar>(i, j) == 0) {
  272.                 continue;
  273.             }
  274.  
  275.             int curAngle = angles.at<int>(i, j);
  276.             int bound = 15;
  277.             int start = curAngle - 15;
  278.             int finish = curAngle + 15;
  279.  
  280.             for (int r = R - 10; r < R + 10; r++) {
  281.                 for (int angle = start; angle < finish; angle++) {
  282.                     double theta = (angle * CV_PI) / 180.0;
  283.                     int x = r * cos(theta) + j;
  284.                     int y = r * sin(theta) + i;
  285.                     if (x >= 0 && x < C.cols && y < C.rows && y >= 0)
  286.                         C.at<int>(y, x)++;
  287.                 }
  288.  
  289.                 start = curAngle - 15 + 180;
  290.                 finish = curAngle + 15 + 180;
  291.  
  292.                 for (int angle = start; angle < finish; angle++) {
  293.                     double theta = (angle * CV_PI) / 180.0;
  294.                     int x = r * cos(theta) + j;
  295.                     int y = r * sin(theta) + i;
  296.                     if (x >= 0 && x < C.cols && y < C.rows && y >= 0)
  297.                         C.at<int>(y, x)++;
  298.                 }
  299.             }
  300.         }
  301.     }
  302.  
  303.     Mat H = intToUchar(C);
  304.  
  305.     return H;
  306. }
  307.  
  308. vector <Cell> countAverage(Bfs& bfs) {
  309.     vector <Cell> coords;
  310.     for (auto component: bfs.components) {
  311.         int averagerow = 0, averagecol = 0;
  312.  
  313.         for (auto cell: component) {
  314.             averagerow += cell.row;
  315.             averagecol += cell.col;
  316.         }
  317.         averagerow /= (int)component.size();
  318.         averagecol /= (int)component.size();
  319.  
  320.         coords.emplace_back(averagerow, averagecol);
  321.     }
  322.     return coords;
  323. }
  324.  
  325. void drawCircles(Mat& mat, vector <Cell> circleCoords, int R) {
  326.     for (auto elem: circleCoords) {
  327.         circle(mat, Point(elem.col, elem.row), R, Scalar(0, 0, 255));
  328.     }
  329. }
  330.  
  331. vector <Cell> rotateRect(vector <Cell> rectCoords, Cell centr, int angle) {
  332.     vector<Cell> res(rectCoords.size());
  333.     for (int i = 0; i < rectCoords.size(); i++) {
  334.         rectCoords[i].row -= centr.row;
  335.         rectCoords[i].col -= centr.col;
  336.     }
  337.  
  338.     for (int i = 0; i < res.size(); i++) {
  339.         double theta = (angle * CV_PI) / 180.0;
  340.         res[i].row = rectCoords[i].col * sin(theta) + rectCoords[i].row * cos(theta);
  341.         res[i].col = rectCoords[i].col * cos(theta) - rectCoords[i].row * sin(theta);
  342.     }
  343.  
  344.     for (int i = 0; i < res.size(); i++) {
  345.         res[i].row += centr.row;
  346.        
  347.         res[i].col += centr.col;
  348.     }
  349.  
  350.     return res;
  351. }
  352.  
  353. void runAlongLine(const Mat& I, vector <Mat>& C, Cell p0, Cell p1, int scale, int scaleAngle, IPoint& curMax, int phi) {
  354.     if (phi < 0) {
  355.         phi += 180;
  356.     } else if (phi > 180) {
  357.         phi -= 180;
  358.     }
  359.     // cout << "lol" << endl;
  360.  
  361.     int phiScaled = phi / scaleAngle;
  362.     // cout << phiScaled << "    " << C.size() << endl;
  363.     double _norm = sqrt((p1.row - p0.row) * (p1.row - p0.row) + (p1.col - p0.col) * (p1.col - p0.col));
  364.     for (double t = 0; t <= 1; t += scale / (double)(_norm)) {
  365.     // for (double t = 0; t <= 1; t += 0.02) {
  366.         Cell p = Cell(floor(p0.row + (p1.row - p0.row) * t), floor(p0.col + (p1.col - p0.col) * t));
  367.         if (p.row < I.rows && p.row > 0 && p.col < I.cols && p.col > 0) {
  368.             C[phiScaled].at<int>(p.row / scale, p.col / scale)++;
  369.             if (C[phiScaled].at<int>(p.row / scale, p.col / scale) > curMax.value) {
  370.                 curMax.value = C[phiScaled].at<int>(p.row / scale, p.col / scale);
  371.                 curMax.cell.row = p.row / scale;
  372.                 curMax.cell.col = p.col / scale;
  373.                 curMax.angle = phi;///?
  374.             }
  375.         }
  376.     }
  377.     // cout << "kek" << endl;
  378. }
  379.  
  380. void runRectangle(const Mat& I, vector <Mat>& Cangles, int scale, int scaleAngle, IPoint& curMax, int phi, int R, int k, int i, int j) {
  381.     for (int r = R - 2; r < R + 2; r++) {
  382.  
  383.         // int curAngle = angles.at<int>(i, j) + phi;
  384.         int curAngle = phi;
  385.         int bound = 15;
  386.  
  387.         int start = curAngle - bound;
  388.         int finish = curAngle + bound;
  389.         // cout << "123" << endl;
  390.         for (int angle = start; angle <= finish; angle += scaleAngle) {
  391.             int curHeight = r;
  392.             int curWidth = k * r;
  393.  
  394.             Cell pul = Cell(i - curHeight, j - curWidth);
  395.             Cell pur = Cell(i - curHeight, j + curWidth);
  396.             Cell pdl = Cell(i + curHeight, j - curWidth);
  397.             Cell pdr = Cell(i + curHeight, j + curWidth);
  398.  
  399.             vector <Cell> rectCoords = { pul, pur, pdl, pdr };
  400.             vector <Cell> rotateCoords = rotateRect(rectCoords, Cell(i, j), angle);
  401.  
  402.             runAlongLine(I, Cangles, rotateCoords[0], rotateCoords[1], scale, scaleAngle, curMax, angle);
  403.             runAlongLine(I, Cangles, rotateCoords[2], rotateCoords[3], scale, scaleAngle, curMax, angle);
  404.             runAlongLine(I, Cangles, rotateCoords[0], rotateCoords[2], scale, scaleAngle, curMax, angle);
  405.             runAlongLine(I, Cangles, rotateCoords[1], rotateCoords[3], scale, scaleAngle, curMax, angle);
  406.         }
  407.         // cout << "asdasdas" << endl;
  408.     }
  409. }
  410.  
  411. vector <Mat> HoughRectMy(const Mat& I, const Mat& edgesChar, int height, int width, const Mat& angles,
  412.     int scale, int scaleAngle, IPoint& curMax) {
  413.     Mat C = Mat::zeros(I.rows / scale, I.cols / scale, CV_32SC1);
  414.  
  415.     int MaxAngle = (180 + 1) / scaleAngle;
  416.     // cout << MaxAngle << endl;
  417.     // cout << "das;fk;sldkf;lsdk;lfk;dslkf;lksd;k" << endl;
  418.     vector <Mat> Cangles(MaxAngle + 1);
  419.     for (int i = 0; i <= MaxAngle; i ++) {
  420.         Cangles[i] = Mat::zeros(I.rows / scale, I.cols / scale, CV_32SC1);
  421.     }
  422.  
  423.     int R = height;
  424.     double k = (width / (double)height);
  425.     int tmp = k * R;
  426.     for (int i = 0; i < edgesChar.rows; i++) {
  427.         for (int j = 0; j < edgesChar.cols; j++) {
  428.             if (edgesChar.at<uchar>(i, j) == 0) {
  429.                 continue;
  430.             }
  431.             runRectangle(I, Cangles, scale, scaleAngle, curMax, angles.at<int>(i, j), R, k, i, j);
  432.             runRectangle(I, Cangles, scale, scaleAngle, curMax, angles.at<int>(i, j) + 90, R, k, i, j);
  433.         }
  434.     }
  435.  
  436.     vector <Mat> Hangles(MaxAngle + 1);
  437.  
  438.     for (int angle = 0; angle < Cangles.size(); angle++) {
  439.         int Cmax = 0;
  440.         for (int i = 0; i < Cangles[angle].rows; i++) {
  441.             for (int j = 0; j < Cangles[angle].cols; j++) {
  442.                 Cmax = max(Cmax, (int)Cangles[angle].at<uchar>(i, j));
  443.             }
  444.         }
  445.         // cout << angle << "  " << Cmax << endl;
  446.     }
  447.  
  448.     for (int i = 0; i <= MaxAngle; i++) {
  449.         Hangles[i] = intToUcharGlobalMax(Cangles[i], curMax.value);
  450.     }
  451.     // Mat H = intToUchar(C);
  452.  
  453.     return Hangles;
  454. }
  455.  
  456.  
  457. void drawRect(Mat& mat, vector <Cell> rectCoords, int height, int width, int scale, int angle) {
  458.     for (auto elem: rectCoords) {
  459.         int col = elem.col * scale + scale / 2;
  460.         int row = elem.row * scale + scale / 2;
  461.         // rectangle(mat, Point(col - width, row - height), Point(col + width, row + height), Scalar(0, 0, 255));
  462.         RotatedRect rRect = RotatedRect(Point2f(col, row), Size2f(width, height), angle);
  463.         Point2f vertices[4];
  464.         rRect.points(vertices);
  465.         for (int i = 0; i < 4; i++) {
  466.             line(mat, vertices[i], vertices[(i+1)%4], Scalar(0, 0, 255), 3);
  467.         }
  468.     }
  469. }
  470.  
  471. Mat SobelGrad(Mat& mat) {
  472.     int scale = 1;
  473.     int delta = 0;
  474.     int ddepth = CV_16S;
  475.     Mat grad_x, grad_y;
  476.     Mat angles = Mat::zeros(mat.rows, mat.cols, CV_32SC1);
  477.     Sobel(mat, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT);
  478.     Sobel(mat, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT);
  479.  
  480.     for (int i = 0; i < angles.rows - 1; i++) {
  481.         for (int j = 0; j < angles.cols - 1; j++) {
  482.  
  483.             int dx = grad_x.at<short>(i, j);
  484.             int dy = grad_y.at<short>(i, j);
  485.             double alpha = atan2(dy, dx);
  486.  
  487.             if (alpha < 0) {
  488.                 alpha += CV_PI;
  489.             }
  490.  
  491.             int alpha_grad = (alpha * 180.0) / CV_PI;
  492.             angles.at<int>(i, j) = alpha_grad;
  493.         }
  494.     }
  495.     return angles;
  496. }
  497.  
  498. int main(int argc, char** argv) {
  499.     if ( argc != 2 ) {
  500.         printf("usage: DisplayImage.out <Image_Path>\n");
  501.         return -1;
  502.     }
  503.  
  504.     Mat I, T, src;
  505.     src = imread(argv[1]);
  506.     GaussianBlur(src, src, Size(3,3), 0, 0, BORDER_DEFAULT );
  507.     T = src;
  508.     resize(src, T, Size(500, 300));
  509.     cvtColor(T, I, CV_BGR2GRAY);
  510.  
  511.     Mat angles;
  512.  
  513.     Mat edgesChar = FindEdges(I, angles, HoughType::LINES);
  514.  
  515.     //Mat angles1 = SobelGrad(I);
  516.  
  517.  
  518.     int offset = 0;
  519.  
  520.     //ширина 340
  521.     //высота 308
  522.  
  523.     // IPoint curMax1 = IPoint(-1, Cell(-1, -1));
  524.     // vector <Mat> C1 = HoughRectMy(I, edgesChar, 100 / 2, 300 / 2, angles, 5, curMax1);
  525.  
  526.     IPoint curMax2 = IPoint(-1, Cell(-1, -1));
  527.     // cout << "as,hfdkjdf" << endl;
  528.     int scaleAngle = 5;
  529.     vector <Mat> C2 = HoughRectMy(I, edgesChar, 50 / 2, 150 / 2,
  530.         angles, 5, scaleAngle, curMax2);
  531.  
  532.     Mat C3;
  533.     int scaledAngle = curMax2.angle / scaleAngle;
  534.     resize(C2[scaledAngle], C3, Size(C2[scaledAngle].cols * 4,
  535.         C2[scaledAngle].rows * 4));
  536.  
  537.     vector<Cell> points;
  538.     points.push_back(curMax2.cell);
  539.     // cout << curMax2.cell.row << "    " << curMax2.cell.col << "    " << curMax2.angle << endl;
  540.     // cout << "dkasj;kasj" << endl;
  541.     // cout << curMax2.angle << endl;
  542.     drawRect(T, points, 50, 150, 5, curMax2.angle);
  543.  
  544.     // Mat C1 = HoughLineMy(I, edgesChar, offset, angles);
  545.     // threshHold(C1, 200);
  546.     // set <Params> params = findLocalMax(C1, 4);
  547.     // drawLine(params, T, offset);
  548.  
  549.     // imshow("T", T);
  550.     // imshow("C1", C1);
  551.     // imshow("C1", C1[curMax1.angle]);
  552.     // imshow("C2", C2[scaledAngle]);
  553.     // imshow("C3", C3);
  554.     imwrite("out" + string(argv[1]), T);
  555.     // waitKey(0);
  556.     return 0;
  557. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement