Path: blob/master/modules/imgproc/test/test_houghlines.cpp
16339 views
/*M///////////////////////////////////////////////////////////////////////////////////////1//2// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.3//4// By downloading, copying, installing or using the software you agree to this license.5// If you do not agree to this license, do not download, install,6// copy or use the software.7//8//9// License Agreement10// For Open Source Computer Vision Library11//12// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.13// Copyright (C) 2009, Willow Garage Inc., all rights reserved.14// Copyright (C) 2014, Itseez, Inc, all rights reserved.15// Third party copyrights are property of their respective owners.16//17// Redistribution and use in source and binary forms, with or without modification,18// are permitted provided that the following conditions are met:19//20// * Redistribution's of source code must retain the above copyright notice,21// this list of conditions and the following disclaimer.22//23// * Redistribution's in binary form must reproduce the above copyright notice,24// this list of conditions and the following disclaimer in the documentation25// and/or other materials provided with the distribution.26//27// * The name of the copyright holders may not be used to endorse or promote products28// derived from this software without specific prior written permission.29//30// This software is provided by the copyright holders and contributors "as is" and31// any express or implied warranties, including, but not limited to, the implied32// warranties of merchantability and fitness for a particular purpose are disclaimed.33// In no event shall the Intel Corporation or contributors be liable for any direct,34// indirect, incidental, special, exemplary, or consequential damages35// (including, but not limited to, procurement of substitute goods or services;36// loss of use, data, or profits; or business interruption) however caused37// and on any theory of liability, whether in contract, strict liability,38// or tort (including negligence or otherwise) arising in any way out of39// the use of this software, even if advised of the possibility of such damage.40//41//M*/4243#include "test_precomp.hpp"4445//#define GENERATE_DATA // generate data in debug mode via CPU code path (without IPP / OpenCL and other accelerators)4647namespace opencv_test { namespace {4849template<typename T>50struct SimilarWith51{52T value;53float theta_eps;54float rho_eps;55SimilarWith<T>(T val, float e, float r_e): value(val), theta_eps(e), rho_eps(r_e) { };56bool operator()(const T& other);57};5859template<>60bool SimilarWith<Vec2f>::operator()(const Vec2f& other)61{62return std::abs(other[0] - value[0]) < rho_eps && std::abs(other[1] - value[1]) < theta_eps;63}6465template<>66bool SimilarWith<Vec3f>::operator()(const Vec3f& other)67{68return std::abs(other[0] - value[0]) < rho_eps && std::abs(other[1] - value[1]) < theta_eps;69}7071template<>72bool SimilarWith<Vec4i>::operator()(const Vec4i& other)73{74return cv::norm(value, other) < theta_eps;75}7677template <typename T>78int countMatIntersection(const Mat& expect, const Mat& actual, float eps, float rho_eps)79{80int count = 0;81if (!expect.empty() && !actual.empty())82{83for (MatConstIterator_<T> it=expect.begin<T>(); it!=expect.end<T>(); it++)84{85MatConstIterator_<T> f = std::find_if(actual.begin<T>(), actual.end<T>(), SimilarWith<T>(*it, eps, rho_eps));86if (f != actual.end<T>())87count++;88}89}90return count;91}9293String getTestCaseName(String filename)94{95string temp(filename);96size_t pos = temp.find_first_of("\\/.");97while ( pos != string::npos ) {98temp.replace( pos, 1, "_" );99pos = temp.find_first_of("\\/.");100}101return String(temp);102}103104class BaseHoughLineTest105{106public:107enum {STANDART = 0, PROBABILISTIC};108protected:109template<typename LinesType, typename LineType>110void run_test(int type, const char* xml_name);111112string picture_name;113double rhoStep;114double thetaStep;115int threshold;116int minLineLength;117int maxGap;118};119120typedef tuple<string, double, double, int> Image_RhoStep_ThetaStep_Threshold_t;121class StandartHoughLinesTest : public BaseHoughLineTest, public testing::TestWithParam<Image_RhoStep_ThetaStep_Threshold_t>122{123public:124StandartHoughLinesTest()125{126picture_name = get<0>(GetParam());127rhoStep = get<1>(GetParam());128thetaStep = get<2>(GetParam());129threshold = get<3>(GetParam());130minLineLength = 0;131maxGap = 0;132}133};134135typedef tuple<string, double, double, int, int, int> Image_RhoStep_ThetaStep_Threshold_MinLine_MaxGap_t;136class ProbabilisticHoughLinesTest : public BaseHoughLineTest, public testing::TestWithParam<Image_RhoStep_ThetaStep_Threshold_MinLine_MaxGap_t>137{138public:139ProbabilisticHoughLinesTest()140{141picture_name = get<0>(GetParam());142rhoStep = get<1>(GetParam());143thetaStep = get<2>(GetParam());144threshold = get<3>(GetParam());145minLineLength = get<4>(GetParam());146maxGap = get<5>(GetParam());147}148};149150typedef tuple<double, double, double, double> HoughLinesPointSetInput_t;151class HoughLinesPointSetTest : public testing::TestWithParam<HoughLinesPointSetInput_t>152{153protected:154void run_test();155double Rho;156double Theta;157double rhoMin, rhoMax, rhoStep;158double thetaMin, thetaMax, thetaStep;159public:160HoughLinesPointSetTest()161{162rhoMin = get<0>(GetParam());163rhoMax = get<1>(GetParam());164rhoStep = (rhoMax - rhoMin) / 360.0f;165thetaMin = get<2>(GetParam());166thetaMax = get<3>(GetParam());167thetaStep = CV_PI / 180.0f;168Rho = 320.00000;169Theta = 1.04719;170}171};172173template<typename LinesType, typename LineType>174void BaseHoughLineTest::run_test(int type, const char* xml_name)175{176string filename = cvtest::TS::ptr()->get_data_path() + picture_name;177Mat src = imread(filename, IMREAD_GRAYSCALE);178ASSERT_FALSE(src.empty()) << "Invalid test image: " << filename;179180string xml = string(cvtest::TS::ptr()->get_data_path()) + "imgproc/" + xml_name;181182Mat dst;183Canny(src, dst, 100, 150, 3);184ASSERT_FALSE(dst.empty()) << "Failed Canny edge detector";185186LinesType lines;187if (type == STANDART)188HoughLines(dst, lines, rhoStep, thetaStep, threshold, 0, 0);189else if (type == PROBABILISTIC)190HoughLinesP(dst, lines, rhoStep, thetaStep, threshold, minLineLength, maxGap);191192String test_case_name = format("lines_%s_%.0f_%.2f_%d_%d_%d", picture_name.c_str(), rhoStep, thetaStep,193threshold, minLineLength, maxGap);194test_case_name = getTestCaseName(test_case_name);195196#ifdef GENERATE_DATA197{198FileStorage fs(xml, FileStorage::READ);199ASSERT_TRUE(!fs.isOpened() || fs[test_case_name].empty());200}201{202FileStorage fs(xml, FileStorage::APPEND);203EXPECT_TRUE(fs.isOpened()) << "Cannot open sanity data file: " << xml;204fs << test_case_name << Mat(lines);205}206#else207FileStorage fs(xml, FileStorage::READ);208FileNode node = fs[test_case_name];209ASSERT_FALSE(node.empty()) << "Missing test data: " << test_case_name << std::endl << "XML: " << xml;210211Mat exp_lines_;212read(fs[test_case_name], exp_lines_, Mat());213fs.release();214LinesType exp_lines;215exp_lines_.copyTo(exp_lines);216217int count = -1;218if (type == STANDART)219count = countMatIntersection<LineType>(Mat(exp_lines), Mat(lines), (float) thetaStep + FLT_EPSILON, (float) rhoStep + FLT_EPSILON);220else if (type == PROBABILISTIC)221count = countMatIntersection<LineType>(Mat(exp_lines), Mat(lines), 1e-4f, 0.f);222223#if defined HAVE_IPP && IPP_VERSION_X100 >= 810 && !IPP_DISABLE_HOUGH224EXPECT_LE(std::abs((double)count - Mat(exp_lines).total()), Mat(exp_lines).total() * 0.25)225<< "count=" << count << " expected=" << Mat(exp_lines).total();226#else227EXPECT_EQ(count, (int)Mat(exp_lines).total());228#endif229#endif // GENERATE_DATA230}231232void HoughLinesPointSetTest::run_test(void)233{234Mat lines_f, lines_i;235vector<Point2f> pointf;236vector<Point2i> pointi;237vector<Vec3d> line_polar_f, line_polar_i;238const float Points[20][2] = {239{ 0.0f, 369.0f }, { 10.0f, 364.0f }, { 20.0f, 358.0f }, { 30.0f, 352.0f },240{ 40.0f, 346.0f }, { 50.0f, 341.0f }, { 60.0f, 335.0f }, { 70.0f, 329.0f },241{ 80.0f, 323.0f }, { 90.0f, 318.0f }, { 100.0f, 312.0f }, { 110.0f, 306.0f },242{ 120.0f, 300.0f }, { 130.0f, 295.0f }, { 140.0f, 289.0f }, { 150.0f, 284.0f },243{ 160.0f, 277.0f }, { 170.0f, 271.0f }, { 180.0f, 266.0f }, { 190.0f, 260.0f }244};245246// Float247for (int i = 0; i < 20; i++)248{249pointf.push_back(Point2f(Points[i][0],Points[i][1]));250}251252HoughLinesPointSet(pointf, lines_f, 20, 1,253rhoMin, rhoMax, rhoStep,254thetaMin, thetaMax, thetaStep);255256lines_f.copyTo( line_polar_f );257258// Integer259for( int i = 0; i < 20; i++ )260{261pointi.push_back( Point2i( (int)Points[i][0], (int)Points[i][1] ) );262}263264HoughLinesPointSet( pointi, lines_i, 20, 1,265rhoMin, rhoMax, rhoStep,266thetaMin, thetaMax, thetaStep );267268lines_i.copyTo( line_polar_i );269270EXPECT_EQ((int)(line_polar_f.at(0).val[1] * 100000.0f), (int)(Rho * 100000.0f));271EXPECT_EQ((int)(line_polar_f.at(0).val[2] * 100000.0f), (int)(Theta * 100000.0f));272EXPECT_EQ((int)(line_polar_i.at(0).val[1] * 100000.0f), (int)(Rho * 100000.0f));273EXPECT_EQ((int)(line_polar_i.at(0).val[2] * 100000.0f), (int)(Theta * 100000.0f));274}275276TEST_P(StandartHoughLinesTest, regression)277{278run_test<Mat, Vec2f>(STANDART, "HoughLines.xml");279}280281TEST_P(ProbabilisticHoughLinesTest, regression)282{283run_test<Mat, Vec4i>(PROBABILISTIC, "HoughLinesP.xml");284}285286TEST_P(StandartHoughLinesTest, regression_Vec2f)287{288run_test<std::vector<Vec2f>, Vec2f>(STANDART, "HoughLines2f.xml");289}290291TEST_P(StandartHoughLinesTest, regression_Vec3f)292{293run_test<std::vector<Vec3f>, Vec3f>(STANDART, "HoughLines3f.xml");294}295296TEST_P(HoughLinesPointSetTest, regression)297{298run_test();299}300301INSTANTIATE_TEST_CASE_P( ImgProc, StandartHoughLinesTest, testing::Combine(testing::Values( "shared/pic5.png", "../stitching/a1.png" ),302testing::Values( 1, 10 ),303testing::Values( 0.05, 0.1 ),304testing::Values( 80, 150 )305));306307INSTANTIATE_TEST_CASE_P( ImgProc, ProbabilisticHoughLinesTest, testing::Combine(testing::Values( "shared/pic5.png", "shared/pic1.png" ),308testing::Values( 5, 10 ),309testing::Values( 0.05, 0.1 ),310testing::Values( 75, 150 ),311testing::Values( 0, 10 ),312testing::Values( 0, 4 )313));314315INSTANTIATE_TEST_CASE_P( Imgproc, HoughLinesPointSetTest, testing::Combine(testing::Values( 0.0f, 120.0f ),316testing::Values( 360.0f, 480.0f ),317testing::Values( 0.0f, (CV_PI / 18.0f) ),318testing::Values( (CV_PI / 2.0f), (CV_PI * 5.0f / 12.0f) )319));320321}} // namespace322323324