现在的位置: 首页 > 综合 > 正文

opencv c++ 线检测 封装类

2019年03月09日 ⁄ 综合 ⁄ 共 4548字 ⁄ 字号 评论关闭

///各位拿走的时候请注明博客地址 

#ifndef OPENCVLinesDetector_HPP

#define OPENCVLinesDetector_HPP
#include "AbstractLinesDetector.hpp"
namespace doppia {
class OpenCvLinesDetector: public AbstractLinesDetector
{
public:
    OpenCvLinesDetector();
    OpenCvLinesDetector(const float input_image_threshold,
                         const float direction_resolution, const float origin_resolution,
                         const int detection_threshold);
    ~OpenCvLinesDetector();
    void operator()(const source_view_t &src, lines_t &lines);
protected:
    /// 0 to 255, input_image pixels below this value are considered as 0
    const float input_image_threshold;
    const float direction_resolution;
    const float origin_resolution;
    const int detection_threshold;
};
} // namespace doppia

#endif // OPENCVLinesDetector_HPP

////And cpp

#include "OpenCvLinesDetector.hpp"
#include <boost/gil/extension/opencv/ipl_image_wrapper.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <vector>
#include <stdexcept>
namespace doppia {
using namespace std;
OpenCvLinesDetector::OpenCvLinesDetector()
    :
      input_image_threshold(150),
      direction_resolution((M_PI/180)*1),
      origin_resolution(1),
      detection_threshold(50)
{
    // nothing to do here
    return;
}

OpenCvLinesDetector::OpenCvLinesDetector(const float input_image_threshold_,
                                           const float direction_resolution_, const float origin_resolution_,
                                           const int detection_threshold_)
    : input_image_threshold(input_image_threshold_),
      direction_resolution(direction_resolution_),
      origin_resolution(origin_resolution_),
      detection_threshold(detection_threshold_)
{
    // nothing to do here
    return;
}
OpenCvLinesDetector::~OpenCvLinesDetector()
{
    // nothing to do here
    return;
}
void OpenCvLinesDetector::operator()(const source_view_t &src, lines_t &lines)
{
    using namespace boost::gil;
    // convert to opencv format --
    opencv::ipl_image_wrapper src_img = opencv::create_ipl_image(src);
    cv::Mat input_image(src_img.get());
    const double threshold_value = input_image_threshold; // 0 to 255
    const double max_value = 255;
    const int threshold_type = cv::THRESH_TOZERO; // any value bellow the threshold_value is set to zero
    cv::threshold(input_image, input_image, threshold_value, max_value, threshold_type);
    // call opencv --
    vector<cv::Vec2f> found_lines;
    {
        const float rho_scale = 1;
        const float theta_scale = 1;

        // rho: distance resolution of the accumulator in pixels
        const double rho = origin_resolution*rho_scale;
        // theta: angle resolution of the accumulator in radians
        const double theta = direction_resolution*theta_scale;
        // threshold: the accumulator threshold parameter. Only those lines are returned that get enough votes
        const int threshold = detection_threshold;
        //cv::HoughLines(input_image, found_lines, rho, theta, threshold, rho_scale, theta_scale);
        cv::HoughLines(input_image, found_lines, rho, theta, threshold);
    }
    // convert to output format --
    lines.clear();
    for(std::size_t i=0; i < found_lines.size(); i+=1)
    {
        line_t t_line;
        const float rho = found_lines[i][0];
        const float theta = found_lines[i][1];
        double sin_theta, cos_theta;
        sincos(theta, &sin_theta, &cos_theta);
        if(sin_theta == 0)
        {
            // we simply skip this value (is this such a good idea ?)
            continue;
            //throw std::runtime_error("OpenCvLinesDetector::operator division by zero");
        }
        // 理论见维基百科
        t_line.direction()(0) = - cos_theta / sin_theta;
        t_line.origin()(0) = rho / sin_theta;
        lines.push_back(t_line);
    }
    const bool show_found_lines = false;
    if(show_found_lines)
    {
        cv::Mat src_img_mat(src_img.get()), color_image;
        cv::cvtColor(src_img_mat, color_image, CV_GRAY2RGB);
        const size_t max_lines_to_draw = 1; //5; // 20

        for(size_t i = 0; i < std::min(found_lines.size(), max_lines_to_draw); i+=1)
        {
            CvPoint pt1, pt2;
            const bool draw_final_lines = true;
            if(draw_final_lines)
            {
                const line_t &t_line = lines.at(i);
                pt1.x = 0;
                pt1.y = t_line.origin()(0);
                pt2.x = 1000;
                pt2.y = pt1.y + pt2.x * t_line.direction()(0);
            }
            else
            {
                // use opencv lines instead of final lines
                const cv::Vec2f &t_line = found_lines.at(i);
                const float rho = t_line[0];
                const float theta = t_line[1];
                const double cos_theta = cos(theta), sin_theta = sin(theta);
                const double x0 = cos_theta*rho, y0 = sin_theta*rho;
                pt1.x = cvRound(x0 + 1000*(-sin_theta));
                pt1.y = cvRound(y0 + 1000*(cos_theta));
                pt2.x = cvRound(x0 - 1000*(-sin_theta));
                pt2.y = cvRound(y0 - 1000*(cos_theta));
            }
            const int thickness = 1;
            cv::line( color_image, pt1, pt2, CV_RGB(255,0,0), thickness, CV_AA);
        } // end of "for each found line"
        cv::imshow("OpenCvLinesDetector", color_image);
        cv::waitKey(0); // force a drawing
    } // end of "if show_found_lines"

    return;
}
} // namespace doppia

抱歉!评论已关闭.