【问题标题】:cartToPolar returns not enough distinct anglescartToPolar 返回的不同角度不够
【发布时间】:2019-08-17 00:36:18
【问题描述】:

我的目标是使用 opencv 根据角度用 3 种颜色对相机梯度幅度进行着色。

为了获得梯度幅度,我将帧从相机转换为灰度,然后应用高斯模糊,然后在 x 轴和 y 轴上创建 sobel,并使用阈值函数将它们二值化。在最后一步,我使用了名为 cartToPolar() 的函数。 但是经过调试,cartToPolar 返回的角度矩阵只有 3 个不同的值。

负责创建梯度幅度和相应角度的代码

cvtColor(frame, frame, COLOR_BGR2GRAY);
GaussianBlur(frame, gauss, Size(gauss_size, gauss_size), 2.0);

Sobel(gauss, sobel_x, CV_32F, 1.0, 0.0, 3);
threshold(sobel_x, sobel_x_bin, 20, 255, THRESH_BINARY);
Sobel(gauss, sobel_y, CV_32F, 0.0, 1.0, 3);
threshold(sobel_y, sobel_y_bin, 20, 255, THRESH_BINARY);
cartToPolar(sobel_x_bin, sobel_y_bin, gradient, angle, true);

负责着色的代码

gradient.copyTo(gradient_colored);
cvtColor(gradient_colored, gradient_colored, COLOR_GRAY2BGR);
gradient_colored.convertTo(gradient_colored, CV_8UC3, 255);
float angle_value;

Vec3b red = Vec3b(0, 0, 255);
Vec3b green = Vec3b(0, 255, 0);
Vec3b blue = Vec3b(255, 0, 0);
Vec3b white = Vec3b(255, 255, 255);

for (int i = 0; i < gradient.rows; i++) {
    for (int j = 0; j < gradient.cols; j++) {
        angle_value = angle.at<float>(i, j);
        // angle contains only three unique values 0, 44.9, 90, why?

        Vec3b *color = &gradient_colored.at<Vec3b>(i, j);
        if (angle_value > 45 && angle_value <= 135)
            * color = white;
        if (angle_value > 135 && angle_value <= 255)
            * color = blue;
        if (angle_value > 255 && angle_value <= 315)
            * color = green;
        if ((angle_value > 315 && angle_value <= 360) || (angle_value > 0 && angle_value <= 45))
            * color = red;

    }
}

我想要基于相机视图的三色(红、蓝、绿、白、黑)渐变幅度,但实际输出只有一种颜色(白、黑、红)

【问题讨论】:

    标签: c++ opencv gradient gaussian magnitude


    【解决方案1】:

    您有两个二进制图像(sobel_x_binsobel_y_bin),您将它们用作每个像素处的渐变的 xy 分量。因此,每个像素只能有四个不同的梯度向量,只有三个不同的角度:

    • x=0, y=0 -> 角度未定义。可能返回 0。

    • x=255, y=0 -> 角度为 0°(梯度向量沿 x 轴)。

    • x=0, y=255 -> 角度为 90°(梯度向量沿 y 轴)。

    • x=255, y=255 -> 角度为 45°。

    看看你交给cartToPolar的数组,这应该会很清楚。

    您究竟为什么要用二进制阈值对梯度图像进行阈值处理?如果你想切断低于某个幅度的所有梯度,那么你可以使用不同的阈值函数(检查available options)。但这应该在幅度图像上完成(例如 cartToPolar 返回的图像),而不是单个组件。

    你应该试试这个:

    cvtColor(frame, frame, COLOR_BGR2GRAY);
    GaussianBlur(frame, gauss, Size(gauss_size, gauss_size), 2.0);
    
    Sobel(gauss, sobel_x, CV_32F, 1.0, 0.0, 3);
    Sobel(gauss, sobel_y, CV_32F, 0.0, 1.0, 3);
    cartToPolar(sobel_x, sobel_y, gradient, angle, true);
    

    然后从那里探索如何获得您需要的东西。

    【讨论】:

    • 我做了mag, angle = cv2.cartToPolar(sobel_x, sobel_y) 并查看了两个返回的数组。 mag 是不言自明的,但是 ang 数组中的条目是否需要乘以 pi 才能转换为弧度?文档不清楚。因此,如果我在 ang 数组中得到 1.56743,这实际上意味着 1.56743 * pi?
    • @mLstudent33 如果没有更多信息,我会假设它们已经是弧度。请注意,1.56743 非常接近 PI/2(即 90°)。将角度作为 PI 的分数返回是非常不寻常的。
    • 很抱歉,我使用的是 np.abs(dx)np.abs(dy)。这使得从cv2.cartToPolar() 返回的所有角度都保持在 pi/2 或更低。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-10
    • 2019-12-31
    • 2021-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多