Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to interpret c++ opencv Assertion error messages due to an error in cvtColor function?

Following is an Assertion Error report (displayed on console) when calling cvtColor() function in opencv giving the argument CV_GRAY2BGR on a Mat object which is already a BGR image. I want to know how to interpret this error message by a person who yet doesn't know what the error here. (Hope some erudites won't vote to close this question as off topic, as I know there is a big value in learning to read Assertion or any other error messages for newbees for c++. ) And as I guess this might be most probably a opencv issue on reading assertion errors.

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

I know 2 conditions are tested here,

  1. (scn == 1)
  2. (dcn == 3 || dcn == 4)

and one of them should have failed which has caused the Assertion error. How to distinct and clarify the failed condition? May be I might have to seek into the cvtColor function source code and that would be no problem. (actually I did it but I couldn't find variables with names scn or dcn there in that improc.cpp class there)

like image 522
Samitha Chathuranga Avatar asked Aug 15 '15 18:08

Samitha Chathuranga


2 Answers

calling cvtColor() function in opencv giving the argument CV_GRAY2BGR on a Mat object which is already a BGR image

You have already answered your own question here. The assertion will have originally have been something like:

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

Since you're using a BGR Mat, scn - which is the number of channels in the source Mat - will be 3 causing the whole expression to evaluate to false, and the assertion to fail.

The operation you are performing makes no sense. Omit it, and your code will probably work.

like image 37
marko Avatar answered Sep 28 '22 06:09

marko


This snippet

#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;
}

will produce your exact error:

OpenCV Error: Assertion failed (scn == 1 && (dcn == 3 || dcn == 4)) in cv::cvtCo lor, file C:\builds\2_4_PackSlave-win32-vc12-static\opencv\modules\imgproc\src\c olor.cpp, line 3789


This code is obviuosly wrong, because you're trying to convert an BGR image from GRAY.

OpenCV is telling you:

Since you're using the code CV_GRAY2BGR, I'm expecting to convert from GRAY (1 channel) source image to a BGR (3 channel) destination image. (I'll allow also BGRA (4 channels) as destination image, even if CV_GRAY2BGRA would be more appropriate in this case.)

In the documentation OpenCV is telling you:

  • src: input image: 8-bit unsigned, 16-bit unsigned ( CV_16UC... ), or single-precision floating-point.
  • dst: output image of the same size and depth as src.
  • code: color space conversion code (see the description below).
  • dstCn: number of channels in the destination image; if the parameter is 0, the number of the channels is derived automatically from src and code .

In C++, OpenCV say this as

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

where scn stands for "Source Channels Number", and dcn stands for "Destination Channels Number".

Now the last point, where do scn and dcn comes from? If you use a debugger and follow the execution path, you'll see in function void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) in color.cpp that (comments added by me):

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));
    ...
}        
like image 67
Miki Avatar answered Sep 28 '22 05:09

Miki