cartToPolar возвращает недостаточно различных углов

Моя цель - раскрасить величину градиента камеры тремя цветами в зависимости от угла с помощью opencv.

Чтобы получить величину градиента, я преобразовал кадр с камеры в шкалу серого, затем применил размытие по Гауссу, затем создал собел по осям x и y и бинаризовал их с помощью пороговой функции. На последнем этапе я использовал функцию 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;

    }
}

Мне нужна трехцветная (красная, синяя, зеленая, белая, черная) величина градиента на основе вида камеры, но фактический результат имеет один цвет (белый, черный, красный)


person Kuba Ronkiewicz    schedule 26.03.2019    source источник


Ответы (1)


У вас есть два бинарных изображения (sobel_x_bin и sobel_y_bin), которые вы используете в качестве компонентов x и y градиента для каждого пикселя. Следовательно, каждый пиксель может иметь только четыре различных вектора градиента только с тремя разными углами:

  • x=0, y=0 -> Угол не определен. Вероятнее всего возвращает 0.

  • x=255, y=0 -> Угол равен 0° (вектор градиента проходит по оси x).

  • x=0, y=255 -> Угол равен 90° (вектор градиента проходит по оси Y).

  • x=255, y=255 -> Угол равен 45°.

Взгляните на массивы, которые вы передаете cartToPolar, и все станет ясно.

Почему именно вы ограничиваете свои градиентные изображения бинарным порогом? Если вы хотите отрезать все градиенты ниже определенной величины, вы можете использовать другую пороговую функцию (см. доступные параметры). Но это следует делать с изображением величины (например, с изображением, возвращаемым 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);

а затем изучить оттуда, как получить то, что вам нужно.

person Max Langhof    schedule 26.03.2019
comment
Я сделал mag, angle = cv2.cartToPolar(sobel_x, sobel_y) и посмотрел на оба возвращенных массива. mag не требует пояснений, но нужно ли умножать записи в массиве ang на pi для преобразования в радианы? Документация не ясна. Итак, если я получу 1,56743 в массиве ang, это на самом деле означает 1,56743 * пи? - person mLstudent33; 26.11.2019
comment
@ mLstudent33 Без дополнительной информации я бы предположил, что они уже указаны в радианах. Обратите внимание, что 1,56743 очень близко к PI/2 (т.е. 90°). Возвращать углы в виде долей числа PI было бы крайне необычно. - person Max Langhof; 26.11.2019
comment
Извините, но я использовал np.abs(dx) и np.abs(dy). Это сохраняло все углы, возвращаемые из cv2.cartToPolar(), на пи/2 или ниже. - person mLstudent33; 26.11.2019