gpt4 book ai didi

python - 使用opencv检测角的角度

转载 作者:行者123 更新时间:2023-12-02 16:49:19 26 4
gpt4 key购买 nike

我有以下转角图像:

original

我正在尝试获取白色角的 Angular ,即以下内容:

expected result

所以我走了一条明显的路去消除噪音

  • 将图像转换为灰度
  • 添加了一些高斯模糊
  • 应用的阈值

  • 结果如下:

    after threshold

    因为我想要 Angular ,所以我需要组成该角的线,所以,我当然使用了canny + hough线,但这是问题所在,我一直在使用Hough来获取多条错误线,而且我不知道如何过滤掉它们:

    after Hough Transform

    有没有已知的方法来获得每条线的置信度,因此我只能获得角的正确的垂直和水平部分?

    最佳答案

    这是不使用cv::HoughLines() 的方法:在二进制图像上,执行一个功能以检测从图像中心到特定方向(左,右,上,下)的最远像素。此函数返回以下像素,在下图中以红色,绿色和蓝色绘制:

    Left:  [21, 35]
    Top: [43, 0]
    Right: [63, 35]

    从这三个点中,您可以选择两种方法来检测 Angular :
  • 丢弃其中一个点,并计算其他两个点之间的 Angular ;
  • 找出哪个是中心点,并计算所有三个点之间的 Angular ;

  • 下面的源代码找出哪个最接近图像中心,并使用 atan2()方法从所有3个点计算 Angular 。

    使用二进制图像输出运行示例:
    Angle: 57.8477 (degrees)

    似乎合法!

    从现在开始,您可以进行一些改进以提高 Angular 准确性。其中之一是使二进制图像骨架化,并使这些线条真正变细。

    源代码:
    #include <opencv2/opencv.hpp>
    #include <opencv2/highgui.hpp>
    #include <opencv2/imgproc.hpp>
    #include <iostream>

    enum imgEdge {
    LEFT = 0,
    RIGHT = 1,
    TOP = 2,
    BOTTOM = 3
    };

    // Find the most distant pixel from the center in a particular direction
    cv::Point mostDistantPixel(const cv::Mat& input, const imgEdge& edge)
    {
    if (edge < 0 || edge > 3)
    {
    std::cout << "!!! mostDistantPixel() invalid side" << std::endl;
    return cv::Point();
    }

    if (input.channels() > 1)
    {
    std::cout << "!!! mostDistantPixel() only single channel img is supported" << std::endl;
    return cv::Point();
    }

    cv::Point mostDistant(-1,-1);
    for (int r = 0; r < input.rows; r++)
    {
    for (int c = 0; c < input.cols; c++)
    {
    // Examine pure white pixels only (row, col)
    if (input.at<uchar>(r,c) == 255)
    {
    switch (edge)
    {
    case imgEdge::LEFT:
    if (c <= mostDistant.x || mostDistant == cv::Point(-1, -1))
    mostDistant = cv::Point(c, r);
    break;

    case imgEdge::RIGHT:
    if (c >= mostDistant.x || mostDistant == cv::Point(-1, -1))
    mostDistant = cv::Point(c, r);
    break;

    case imgEdge::TOP:
    if (r <= mostDistant.y || mostDistant == cv::Point(-1, -1))
    mostDistant = cv::Point(c, r);
    break;

    case imgEdge::BOTTOM:
    if (r >= mostDistant.y || mostDistant == cv::Point(-1, -1))
    mostDistant = cv::Point(c, r);
    break;
    }
    }
    }
    }

    return mostDistant;
    }

    // Eucledian distance between 2 points
    unsigned int distance(const cv::Point& a, const cv::Point& b)
    {
    return std::sqrt(std::pow(b.x-a.x, 2) + std::pow(b.y-a.y, 2));
    }

    // Compute the angle between 3 points (degrees)
    double calcAngle(const cv::Point& center, const cv::Point& point, const cv::Point& base)
    {
    /* Compute the angle between the center, a point and it's base (starting point for the angle computation)
    *
    * %
    * * * @ = center
    * * @ # # = base (origin)
    * * * % = point
    * * From # to %, there are 90 degrees
    */

    double angle = std::atan2(point.y - center.y, point.x - center.x) * 180 / 3.141592;
    angle = (angle < 0) ? (360 + angle) : angle;
    return (360 - angle);
    }

    int main()
    {
    cv::Mat img = cv::imread("corner.png", CV_LOAD_IMAGE_GRAYSCALE);
    if (img.empty())
    {
    std::cout << "!!! imread()" << std::endl;
    return -1;
    }

    // Find the left-most, right-most and top-most pixel
    cv::Point leftPix = mostDistantPixel(img, imgEdge::LEFT);
    std::cout << "Left: " << leftPix << std::endl;

    cv::Point topPix = mostDistantPixel(img, imgEdge::TOP);
    std::cout << "Top: " << topPix << std::endl;

    cv::Point rightPix = mostDistantPixel(img, imgEdge::RIGHT);
    std::cout << "Right: " << rightPix << std::endl;

    // Draw pixels for debugging purposes
    // cv::Mat colored;
    // cv::cvtColor(img, colored, CV_GRAY2BGR);
    // cv::circle(colored, leftPix, 2, cv::Scalar(0, 0, 255), cv::FILLED); // red
    // cv::circle(colored, topPix, 2, cv::Scalar(0, 255, 0), cv::FILLED); // green
    // cv::circle(colored, rightPix, 2, cv::Scalar(255, 0, 0), cv::FILLED); // blue
    // cv::imwrite("points.png", colored);

    // Find the pivot point: which of them is closest to the center
    cv::Point center(img.cols/2, img.rows/2);
    unsigned int leftDistance = distance(center, leftPix);
    unsigned int rightDistance = distance(center, rightPix);
    unsigned int topDistance = distance(center, topPix);

    // This part needs a lot more testing and refinement
    double angle = 0;
    if (leftDistance <= rightDistance && leftDistance <= topDistance)
    angle = calcAngle(leftPix, topPix, rightPix); // looks good
    else if (rightDistance <= leftDistance && rightDistance <= topDistance)
    angle = calcAngle(rightPix, leftPix, topPix); // needs testing
    else
    angle = calcAngle(topPix, leftPix, rightPix); // needs testing

    std::cout << "Angle: " << angle << " (degrees)" << std::endl;
    return 0;
    }

    关于python - 使用opencv检测角的角度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48488723/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com