从 360 度仪表读取角度

Read angle from a 360 degre meter

我有一个使用 openCV 成功提取的仪表 Image of the meter in different positions中间白色的东西是一个指针,可以从0到360。

我的代码:

void readAngleOfMeter(Mat image, int number)
{
    cvtColor(image, image, COLOR_BGR2GRAY);
    inRange(image, Scalar(255, 255, 255), Scalar(255, 255, 255), image);

    vector<Vec2f> lines;
    HoughLines(tmp, lines, 1, CV_PI / 360, 30, 0, 0);

    if (lines.size() == 0) {
        cout << "No lines found" << endl;
        return;
    }

    float thetasum = 0;
    for (size_t i = 0; i < lines.size(); i++)
    {
        float theta = lines[i][1];
        thetasum += theta;
    }
    thetasum = thetasum / static_cast<int>(lines.size());
    cout << "Theta " << thetasum << endl;
}

我现在的问题是我想读取仪表的角度。所以我考虑过使用每条线的平均角度,但问题是它不起作用,因为一条线可以用两种方式解释(示例 90 与 270 相同)以及当它从 360 变为 0 时。

有什么想法吗?

您甚至不需要使用霍夫变换。编写一个循环,以 1 度为增量从 0 度迭代到 360 度,查看以图像中心为中心的圆中的像素。记住第一个白色像素的角度,当你找到下一个围绕圆圈的黑色像素时,取它的角度并与起始角度平均。

您可能需要先模糊一点或扩大仪表针以填补任何空白。

试验半径 - 较小的半径会使您的分辨率降低,因为那里的针看起来更粗。较大的半径将为您提供更高的分辨率,但您可能会错过针头,因为它离中心更细。

霍夫函数确实会留下不可恢复的180°不确定性

您可以计算交点,即估计中心点并检查它位于 ROI 的哪一侧(如有必要,沿平分线采样以找到指针的方向。

已解决,这是我使用的代码。

float radius = 50;
bool found = false;
float startv = 0;
float endv = 0;
for (float v = 0; v < 360; v++)
{
    int x = center.x + cos(v * CV_PI / 180.0) * radius;
    int y = center.y + sin(v * CV_PI / 180.0) * radius;
    Point p{x,y};

    if (!found && gray.at<uchar>(x, y) != 255) {
        startv = v;
        found = true;
    }
    if (found && gray.at<uchar>(x, y) == 255) {
        endv = v;
        break;
    }
}