Как интерпретировать сообщения об ошибках C++ opencv Assertion из-за ошибки в функции cvtColor?

Ниже приведен отчет об ошибке утверждения (отображаемый на консоли) при вызове функции cvtColor() в opencv с аргументом CV_GRAY2BGR для объекта Mat, который уже является изображением BGR. Я хочу знать, как интерпретировать это сообщение об ошибке человеком, который еще не знает, что здесь за ошибка. (Надеюсь, некоторые эрудиты не проголосуют за то, чтобы закрыть этот вопрос как не по теме, поскольку я знаю, что научиться читать утверждение или любые другие сообщения об ошибках для новичков в С++ имеет большое значение.) И, как я предполагаю, это может быть, скорее всего, проблема opencv при чтении ошибок утверждения.

OpenCV Error: Assertion failed (scn == 1 && (dcn == 3 ||
 dcn == 4)) in cv::cvtColor, file C:\builds\2_4_PackSlave-win32-vc12-shared\open
cv\modules\imgproc\src\color.cpp, line 3791

Я знаю, что здесь проверяются 2 условия,

  1. (сбн == 1)
  2. (СН == 3 || ССН == 4)

и один из них должен был дать сбой, что вызвало ошибку утверждения. Как отличить и уточнить несостоявшееся состояние? Возможно, мне придется искать исходный код функции cvtColor, и это не будет проблемой. (на самом деле я это сделал, но я не смог найти там переменные с именами scn или dcn в этом классе improc.cpp)


person Samitha Chathuranga    schedule 15.08.2015    source источник
comment
Если вы сдали bgr Mat, т.е. 3, первое утверждение не удалось, так как исходный канал (scn) не равен 1. Dcn — это канал назначения. Вы должны проверить color.cpp (как указано в ошибке), а не improc.cpp. И последнее, но не менее важное: используйте отладчик...   -  person Miki    schedule 15.08.2015
comment
означает: SourceChannelNumber должен быть равен 1 (оттенки серого), а DestinationChannelNumber должен быть равен 3 или 4 (цветное изображение).   -  person Micka    schedule 15.08.2015
comment
@Мики и Мика, вы оба потрясающие...! ;-) Спасибо за поддержку. Пожалуйста, добавьте эти комментарии в качестве ответа, и я бы отметил его как принятый ответ.   -  person Samitha Chathuranga    schedule 15.08.2015
comment
Во всяком случае, теперь у меня есть новая проблема. Я проверил color.cpp. Да, эти переменные были в этом классе. Но где определяется их значение (поскольку scn=номер исходного канала и dcn=номер канала назначения)? Я имею в виду, где комментарии, разъясняющие длинные фразы этих сокращенных имен переменных. ммм... ИЛИ мы должны использовать общий смысл или догадки, чтобы определить значения...   -  person Samitha Chathuranga    schedule 15.08.2015
comment
Обычно без комментариев. Вы делаете вывод, что они означают, глядя на аргументы функции или на то, как инициализируется переменная. Немного опыта, и вы познакомитесь со значением таких названий и утверждений. Как я уже говорил ранее, использование отладчика очень полезно для отслеживания вызовов функций и, в конечном счете, обнаружения ошибки.   -  person Miki    schedule 15.08.2015
comment
Спасибо @Мики. Я использую Visual Studio 2013 во встроенном отладчике. Есть ли другие лучшие отладчики, которые используют эксперты С++?   -  person Samitha Chathuranga    schedule 15.08.2015
comment
Я тоже использую в основном VS, и лично я нахожу его превосходным (просто личное мнение). С другой IDE вы можете использовать gdb и valgrind (но здесь я не совсем доступен)   -  person Miki    schedule 16.08.2015


Ответы (2)


Этот фрагмент

#include <opencv2\opencv.hpp>
using namespace cv;

int main(int argc, char** argv)
{
    // Just a small green BGR image
    Mat3b img(10,10,Vec3b(0,255,0));

    Mat1b gray;
    cvtColor(img, gray, CV_GRAY2BGR); // WARNING: this won't work (on purpose)

    return 0;
}

выдаст вашу точную ошибку:

Ошибка OpenCV: утверждение не удалось (scn == 1 && (dcn == 3 || dcn == 4)) в cv::cvtColor, файл C:\builds\2

CV_Assert( scn == 1 && (dcn == 3 || dcn == 4));
PackSlave-win32-vc12-static\opencv\modules\imgproc \src\c color.cpp, строка 3789


Этот код явно неверен, потому что вы пытаетесь преобразовать изображение BGR из GRAY.

OpenCV говорит вам:

Поскольку вы используете код CV_GRAY2BGR, я ожидаю преобразования исходного изображения GRAY (1 канал) в целевое изображение BGR (3 канала). (Я также разрешаю BGRA (4 канала) в качестве целевого изображения, даже если CV_GRAY2BGRA будет более подходящим в этом случае.)

В документации OpenCV говорит вам:

  • src: входное изображение: 8-битное беззнаковое, 16-битное беззнаковое ( CV_16UC... ) или с плавающей запятой одинарной точности.
  • dst: выходное изображение того же размера и глубины, что и src.
  • code: код преобразования цветового пространства (см. описание ниже).
  • dstCn: количество каналов в целевом изображении; если параметр равен 0, количество каналов определяется автоматически из src и code .

В С++ OpenCV говорит это как

CV_Assert( scn == 1 && (dcn == 3 || dcn == 4));

где scn означает «Номер исходных каналов», а dcn означает «Номер каналов назначения».

Теперь последний вопрос, откуда взялись scn и dcn? Если вы используете отладчик и проследите путь выполнения, вы увидите в функции void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) в color.cpp, что (комментарии добавлены мной):

void cv::cvtColor( InputArray _src /* source image*/, 
                   OutputArray _dst /* destination image*/,  
                   int code, /* here is CV_GRAY2BGR*/ 
                   int dcn /* defaults to -1*/ ) 
{
    Mat src = _src.getMat(), dst;
    ...
    int scn = src.channels(); // scn is the number of channels of the source image 
    ...
    switch( code ) {
        ...
        case CV_GRAY2BGR: case CV_GRAY2BGRA:
            if( dcn <= 0 ) dcn = (code==CV_GRAY2BGRA) ? 4 : 3; 
            // destination channels are set to 3 because of the code CV_GRAY2BGR

            // Check that the input arguments are correct
            CV_Assert( scn == 1 && (dcn == 3 || dcn == 4));
    ...
}        
person Miki    schedule 16.08.2015
comment
Большое спасибо за длинное определение. Это отлично отвечает на мой вопрос. - person Samitha Chathuranga; 16.08.2015

вызов функции cvtColor() в opencv с аргументом CV_GRAY2BGR для объекта Mat, который уже является изображением BGR

Вы уже ответили на свой вопрос здесь. Утверждение изначально было примерно таким:

CV_Assert( scn == 1 && (dcn == 3 || dcn == 4));

Так как вы используете BGR Mat, scn — количество каналов в исходном Mat — будет равно 3, что приведет к тому, что все выражение будет оцениваться как false, а утверждение не будет выполнено.

Операция, которую вы выполняете, не имеет смысла. Опустите его, и ваш код, вероятно, будет работать.

person marko    schedule 15.08.2015
comment
Ответ, который я ожидал, на самом деле является интерпретацией отчета об ошибке, а не того, что это за ошибка. В любом случае, спасибо. Мика и Мики дали ответы, как я и ожидал. - person Samitha Chathuranga; 15.08.2015
comment
Во всяком случае, теперь у меня есть новая проблема. Я проверил color.cpp. Да, эти переменные были в этом классе. Но где определяется их значение (поскольку scn=номер исходного канала и dcn=номер канала назначения)? Я имею в виду, где комментарии, разъясняющие длинные фразы этих сокращенных имен переменных. - person Samitha Chathuranga; 15.08.2015
comment
@SamithaChathuranga: прочитайте мой ответ более внимательно;) OpenCV на самом деле не подходит для того, чтобы его рассматривали как библиотеку черного ящика, и временами может быть довольно враждебной разработчикам. Нет ничего другого, кроме как копаться в (огромном количестве) исходного кода. - person marko; 16.08.2015
comment
Ok. Какая-то другая проблема здесь. Думаю, я все делаю правильно, вызывая cvtColor(sourceMat,sourceMat,CV_BGR2GRAY); Даю одно и то же исходное изображение как на вход, так и на выход мат. Так что dcn тоже не 3 и не 4. (это все еще 1, так как это изображение в градациях серого). Но никаких утверждений не появилось. Так какой там реальный сценарий.? - person Samitha Chathuranga; 16.08.2015
comment
Вы уверены, что cvtColor() может выполнить это преобразование на месте? Я подозреваю, что это невозможно, поэтому вам нужно создать мат для использования в качестве второго параметра. - person marko; 16.08.2015
comment
Итак, в документации к cvtColor() указано: dst — выходное изображение того же размера и глубины, что и src. - это не совсем говорит о том, что у них должно быть одинаковое количество каналов. В приведенном ими примере действительно показано преобразование на месте, но это преобразование с одинаковым количеством входных и выходных каналов. - person marko; 16.08.2015
comment
Да, cvtColor() может выполнить это преобразование. (прямое преобразование исходного изображения RGB в оттенки серого). Я делал это много раз. - person Samitha Chathuranga; 16.08.2015