Размер ядра OpenCV GaussianBlur 0

Как указано в документы opencv,

ksize – Gaussian kernel size. ksize.width and ksize.height can differ but they both must be positive and odd. Or, they can be zero’s and then they are computed from sigma* .

Я попытался установить размер ядра равным 0:

Mat input = imread(inputImagePath, IMREAD_COLOR);
Mat smooth;
int sigma=1;
GaussianBlur(input, smooth, Size(0, 0), sigma);

В результате:

OpenCV(3.4.1) Error: Assertion failed (ksize.width > 0 && ksize.width % 2 == 1 && ksize.height > 0 && ksize.height % 2 == 1) in createGaussianKernels

Работает с Size(3, 3). Где я не прав? Спасибо.

Основываясь на исходной ссылке на документацию ... вы используете OpenCV 3.4.1, но обратитесь к документации для 2.4.x - имейте в виду, что в API были внесены некоторые небольшие изменения, поэтому рекомендуется ссылаться на те, которые соответствовать используемой вами версии. Однако, насколько я могу судить, это не похоже на источник проблемы.

Dan Mašek 11.04.2018 16:01

Как вы выяснили, что документация для 2.4? По ссылке 3.4: docs.opencv.org/3.4.1/d4/d86/…

Gerry 11.04.2018 16:31

Потому что я прочитал это перед тем, как одобрить правку Дмитрия. | Кстати, можете ли вы попробовать это с какой-нибудь более старой версией OpenCV? До сих пор я пытался воспроизвести его с помощью 3.1.0, которая была у меня под рукой, но не смог. Это может быть регресс или какое-то недавнее изменение, которое не вошло в документацию. Я интерпретирую документацию так же, как и вы, и это должно работать (если я тоже чего-то не упускаю: D).

Dan Mašek 11.04.2018 16:35

Судя по виду исходный код, код Джерри должен работать. Может быть, нестабильная сборка? Попробуйте установить opencv из стабильного канала

Dmitrii Z. 11.04.2018 16:45

@DmitriiZ. Да, я это тоже просто просматривал, что часть не изменилась за 8 лет ... Довольно странно.

Dan Mašek 11.04.2018 16:49
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
973
2

Ответы 2

Вы не можете сделать размер ядра нулевым. Вы можете сделать значения сигмы равными нулю. Вот почему утверждение не удалось.

Также важно отметить, что размеры ядра должны быть строго нечетными.

Вы можете вызвать cv::GaussianBlur(...) с вашим ядром, в этом случае размер ядра в обоих измерениях должен быть странный: kernel.width % 2 == 1 && kernel.height % 2 == 1.

Или вы можете оставить размер ядра не установленным и указать положительные значения сигмы (sigma1 должен быть установлен, sigma2 будет установлен равным ему по умолчанию). Если это так, ядро ​​вычисляется следующим образом:

template <typename T>
static void createGaussianKernels( T & kx, T & ky, int type, Size &ksize,
                               double sigma1, double sigma2 )
{
int depth = CV_MAT_DEPTH(type);
if ( sigma2 <= 0 )
    sigma2 = sigma1;

// automatic detection of kernel size from sigma
if ( ksize.width <= 0 && sigma1 > 0 )
    ksize.width = cvRound(sigma1*(depth == CV_8U ? 3 : 4)*2 + 1)|1;
if ( ksize.height <= 0 && sigma2 > 0 )
    ksize.height = cvRound(sigma2*(depth == CV_8U ? 3 : 4)*2 + 1)|1;

CV_Assert( ksize.width  > 0 && ksize.width  % 2 == 1 &&
           ksize.height > 0 && ksize.height % 2 == 1 );
...
...
}

Это из источников OpenCV 4.1.1. Итак, ваш код выглядит вполне корректным. Я скомпилировал его, и он работал без утверждения, как и ожидалось. Проверьте, какую версию библиотеки вы используете, но это самый базовый функционал, который в последнее время практически не менялся.

Вы также можете попробовать предоставить как sigma1, так и sigma2 (и использовать двойные значения, чтобы избежать неявного преобразования типов):

double sigmaX = 1.;
double sigmaY = 1.;
cv::GaussianBlur(input, smooth, cv::Size(0, 0), sigmaX, sigmaY);

Другие вопросы по теме