123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- /*M///////////////////////////////////////////////////////////////////////////////////////
- //
- // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
- //
- // By downloading, copying, installing or using the software you agree to this license.
- // If you do not agree to this license, do not download, install,
- // copy or use the software.
- //
- //
- // License Agreement
- // For Open Source Computer Vision Library
- //
- // Copyright (C) 2015, Smart Engines Ltd, all rights reserved.
- // Copyright (C) 2015, Institute for Information Transmission Problems of the Russian Academy of Sciences (Kharkevich Institute), all rights reserved.
- // Copyright (C) 2015, Dmitry Nikolaev, Simon Karpenko, Michail Aliev, Elena Kuznetsova, all rights reserved.
- // Third party copyrights are property of their respective owners.
- //
- // Redistribution and use in source and binary forms, with or without modification,
- // are permitted provided that the following conditions are met:
- //
- // * Redistribution's of source code must retain the above copyright notice,
- // this list of conditions and the following disclaimer.
- //
- // * Redistribution's in binary form must reproduce the above copyright notice,
- // this list of conditions and the following disclaimer in the documentation
- // and/or other materials provided with the distribution.
- //
- // * The name of the copyright holders may not be used to endorse or promote products
- // derived from this software without specific prior written permission.
- //
- // This software is provided by the copyright holders and contributors "as is" and
- // any express or implied warranties, including, but not limited to, the implied
- // warranties of merchantability and fitness for a particular purpose are disclaimed.
- // In no event shall the Intel Corporation or contributors be liable for any direct,
- // indirect, incidental, special, exemplary, or consequential damages
- // (including, but not limited to, procurement of substitute goods or services;
- // loss of use, data, or profits; or business interruption) however caused
- // and on any theory of liability, whether in contract, strict liability,
- // or tort (including negligence or otherwise) arising in any way out of
- // the use of this software, even if advised of the possibility of such damage.
- //
- //M*/
- #include <opencv2/imgproc.hpp>
- #include <opencv2/highgui.hpp>
- #include <opencv2/core/utility.hpp>
- #include <opencv2/ximgproc.hpp>
- #include <iostream>
- #include <iomanip>
- #include <cstdio>
- #include <ctime>
- #include <vector>
- using namespace cv;
- using namespace cv::ximgproc;
- using namespace std;
- static void help()
- {
- cout << "\nThis program demonstrates line finding with the Fast Hough transform.\n"
- "Usage:\n"
- "./fasthoughtransform\n"
- "<image_name>, default is '../../../samples/data/building.jpg'\n"
- "<fht_image_depth>, default is " << CV_32S << "\n"
- "<fht_angle_range>, default is " << 6 << " (@see cv::AngleRangeOption)\n"
- "<fht_operator>, default is " << 2 << " (@see cv::HoughOp)\n"
- "<fht_makeskew>, default is " << 1 << "(@see cv::HoughDeskewOption)" << endl;
- }
- static bool parseArgs(int argc, const char **argv,
- Mat &img,
- int &houghDepth,
- int &houghAngleRange,
- int &houghOperator,
- int &houghSkew)
- {
- if (argc > 6)
- {
- cout << "Too many arguments" << endl;
- return false;
- }
- const char *filename = argc >= 2 ? argv[1]
- : "../../../samples/data/building.jpg";
- img = imread(filename, 0);
- if (img.empty())
- {
- cout << "Failed to load image from '" << filename << "'" << endl;
- return false;
- }
- houghDepth = argc >= 3 ? atoi(argv[2]) : CV_32S;
- houghAngleRange = argc >= 4 ? atoi(argv[3]) : 6;//ARO_315_135
- houghOperator = argc >= 5 ? atoi(argv[4]) : 2;//FHT_ADD
- houghSkew = argc >= 6 ? atoi(argv[5]) : 1;//HDO_DESKEW
- return true;
- }
- static bool getEdges(const Mat &src, Mat &dst)
- {
- Mat ucharSingleSrc;
- src.convertTo(ucharSingleSrc, CV_8UC1);
- Canny(ucharSingleSrc, dst, 50, 200, 3);
- return true;
- }
- static bool fht(const Mat &src, Mat &dst,
- int dstDepth, int angleRange, int op, int skew)
- {
- clock_t clocks = clock();
- FastHoughTransform(src, dst, dstDepth, angleRange, op, skew);
- clocks = clock() - clocks;
- double secs = (double)clocks / CLOCKS_PER_SEC;
- cout << std::setprecision(2) << "FastHoughTransform finished in " << secs
- << " seconds" << endl;
- return true;
- }
- template<typename T>
- bool rel(pair<T, Point> const &a, pair<T, Point> const &b)
- {
- return a.first > b.first;
- }
- template<typename T>
- bool incIfGreater(const T& a, const T& b, int *value)
- {
- if (!value || a < b)
- return false;
- if (a > b)
- ++(*value);
- return true;
- }
- static const int MAX_LEN = 10000;
- template<typename T>
- bool getLocalExtr(vector<Vec4i> &lines,
- const Mat &src,
- const Mat &fht,
- float minWeight,
- int maxCount)
- {
- vector<pair<T, Point> > weightedPoints;
- for (int y = 0; y < fht.rows; ++y)
- {
- if (weightedPoints.size() > MAX_LEN)
- break;
- T const *pLine = (T *)fht.ptr(max(y - 1, 0));
- T const *cLine = (T *)fht.ptr(y);
- T const *nLine = (T *)fht.ptr(min(y + 1, fht.rows - 1));
- for (int x = 0; x < fht.cols; ++x)
- {
- if (weightedPoints.size() > MAX_LEN)
- break;
- T const value = cLine[x];
- if (value >= minWeight)
- {
- int isLocalMax = 0;
- for (int xx = max(x - 1, 0);
- xx <= min(x + 1, fht.cols - 1);
- ++xx)
- {
- if (!incIfGreater(value, pLine[xx], &isLocalMax) ||
- !incIfGreater(value, cLine[xx], &isLocalMax) ||
- !incIfGreater(value, nLine[xx], &isLocalMax))
- {
- isLocalMax = 0;
- break;
- }
- }
- if (isLocalMax > 0)
- weightedPoints.push_back(make_pair(value, Point(x, y)));
- }
- }
- }
- if (weightedPoints.empty())
- return true;
- sort(weightedPoints.begin(), weightedPoints.end(), &rel<T>);
- weightedPoints.resize(min(static_cast<int>(weightedPoints.size()),
- maxCount));
- for (size_t i = 0; i < weightedPoints.size(); ++i)
- {
- lines.push_back(HoughPoint2Line(weightedPoints[i].second, src));
- }
- return true;
- }
- static bool getLocalExtr(vector<Vec4i> &lines,
- const Mat &src,
- const Mat &fht,
- float minWeight,
- int maxCount)
- {
- int const depth = CV_MAT_DEPTH(fht.type());
- switch (depth)
- {
- case 0:
- return getLocalExtr<uchar>(lines, src, fht, minWeight, maxCount);
- case 1:
- return getLocalExtr<schar>(lines, src, fht, minWeight, maxCount);
- case 2:
- return getLocalExtr<ushort>(lines, src, fht, minWeight, maxCount);
- case 3:
- return getLocalExtr<short>(lines, src, fht, minWeight, maxCount);
- case 4:
- return getLocalExtr<int>(lines, src, fht, minWeight, maxCount);
- case 5:
- return getLocalExtr<float>(lines, src, fht, minWeight, maxCount);
- case 6:
- return getLocalExtr<double>(lines, src, fht, minWeight, maxCount);
- default:
- return false;
- }
- }
- static void rescale(Mat const &src, Mat &dst,
- int const maxHeight=500,
- int const maxWidth = 1000)
- {
- double scale = min(min(static_cast<double>(maxWidth) / src.cols,
- static_cast<double>(maxHeight) / src.rows), 1.0);
- resize(src, dst, Size(), scale, scale, INTER_LINEAR_EXACT);
- }
- static void showHumanReadableImg(string const &name, Mat const &img)
- {
- Mat ucharImg;
- img.convertTo(ucharImg, CV_MAKETYPE(CV_8U, img.channels()));
- rescale(ucharImg, ucharImg);
- imshow(name, ucharImg);
- }
- static void showFht(Mat const &fht)
- {
- double minv(0), maxv(0);
- minMaxLoc(fht, &minv, &maxv);
- Mat ucharFht;
- fht.convertTo(ucharFht, CV_MAKETYPE(CV_8U, fht.channels()),
- 255.0 / (maxv + minv), minv / (maxv + minv));
- rescale(ucharFht, ucharFht);
- imshow("fast hough transform", ucharFht);
- }
- static void showLines(Mat const &src, vector<Vec4i> const &lines)
- {
- Mat bgrSrc;
- cvtColor(src, bgrSrc, COLOR_GRAY2BGR);
- for (size_t i = 0; i < lines.size(); ++i)
- {
- Vec4i const &l = lines[i];
- line(bgrSrc, Point(l[0], l[1]), Point(l[2], l[3]),
- Scalar(0, 0, 255), 1, LINE_AA);
- }
- rescale(bgrSrc, bgrSrc);
- imshow("lines", bgrSrc);
- }
- int main(int argc, const char **argv)
- {
- Mat src;
- int depth(0);
- int angleRange(0);
- int op(0);
- int skew(0);
- if (!parseArgs(argc, argv, src, depth, angleRange, op, skew))
- {
- help();
- return -1;
- }
- showHumanReadableImg("src", src);
- Mat canny;
- if (!getEdges(src, canny))
- {
- cout << "Failed to select canny edges";
- return -2;
- }
- showHumanReadableImg("canny", canny);
- Mat hough;
- if (!fht(canny, hough, depth, angleRange, op, skew))
- {
- cout << "Failed to compute Fast Hough Transform";
- return -2;
- }
- showFht(hough);
- vector<Vec4i> lines;
- if (!getLocalExtr(lines, canny, hough,
- static_cast<float>(255 * 0.3 * min(src.rows, src.cols)),
- 50))
- {
- cout << "Failed to find local maximums on FHT image";
- return -2;
- }
- showLines(canny, lines);
- waitKey();
- return 0;
- }
|