Search code examples
c++clinuxopencvraspberry-pi

OpenCV Error: Sizes of input arguments do not match (The operation is neither 'array op array')


I am working on a project that uses opencv on raspberry pi. I have run into a hurdle which looks simple, but I am unable to solve the issue. First of all, here a part of my code:

    {
        gray=cvarrToMat(py);
        ///cvShowImage("camcvWin", py); // display only gray channel
        if(img_num%2 == 1)
        {
            cv::imwrite("/home/pi/test/Gray_2Image1.jpg",gray);
        }
        else if (img_num%2 == 0)
        {
            cv::imwrite( "/home/pi/test/Gray_2Image2.jpg", gray );  
            cv::Mat img2 = cv::imread("/home/pi/test/Gray_2Image2.jpg", 0);
            cv::Mat img1 = cv::imread("/home/pi/test/Gray_2Image1.jpg", 0);
            diffImage = abs(img1-img2);
            imshow("diffImage", diffImage);
            cv::imwrite( "/home/pi/test/Diffimage.jpg", diffImage );

        }          
        img_num++;

This code has no problem. However, if I edit the code to make a slight modification as follows:

    {
        gray=cvarrToMat(py);
        ///cvShowImage("camcvWin", py); // display only gray channel
        if(img_num%2 == 1)
        {
            cv::imwrite("/home/pi/test/Gray_2Image1.jpg",gray);
            cv::Mat img1 = cv::imread("/home/pi/test/Gray_2Image1.jpg", 0);
        }
        else if (img_num%2 == 0)
        {
            cv::imwrite( "/home/pi/test/Gray_2Image2.jpg", gray );  
            cv::Mat img2 = cv::imread("/home/pi/test/Gray_2Image2.jpg", 0);
            diffImage = abs(img1-img2);
            imshow("diffImage", diffImage);
            cv::imwrite( "/home/pi/test/Diffimage.jpg", diffImage );

        }          
        img_num++;

I get the following error:

OpenCV Error: Sizes of input arguments do not match (The operation is neither 'array op array' (where arrays have the same size and the same number of channels), nor 'array op scalar', nor 'scalar op array') in arithm_op, file /home/pi/OpenCV-2.3.1/modules/core/src/arithm.cpp, line 1253 terminate called after throwing an instance of 'cv::Exception' what(): /home/pi/OpenCV-2.3.1/modules/core/src/arithm.cpp:1253: error: (-209) The operation is neither 'array op array' (where arrays have the same size and the same number of channels), nor 'array op scalar', nor 'scalar op array' in function arithm_op

I am not really able to understand what is going on. img1 and img2 are declared globally as Mat. This might be a simple issue, but I am still a novice. Please help me solve the issue. Thank you for your time.


Solution

  • In the first block of code, img1 and img2 are declared and contain two gray valid images (since you do imread). Note that these img1 and img2 are not global variables, but local. If you have global variables with the same names, the local ones shadow them.

    In the second block, you define img2 in the else and later do img1 - img2, but you don't show to us the value of img1 (in this case, the global variable). The img1 that is in the if is local to that if and is not visible in the else. Probably, you defined cv::Mat img1 in the global scope but you didn't give it any value. This would cause an error in img1-img2 because they are of different size (img1 would be empty).

    Update: Something like this should fix it.

    // global scope
    cv::Mat img1, img2, diffImage;
    
    void yourFunction()
    {
       ...
       img1 = cv::imread("/home/pi/test/Gray_2Image1.jpg", 0);
       img2 = cv::imread("/home/pi/test/Gray_2Image2.jpg", 0);
       diffImage = abs(img1-img2);
       ...
    }
    

    Update again: you can load the images in different if-else blocks as long as their declaration is visible.

    This is ok:

    // global scope
    cv::Mat img1, img2, diffImage;
    
    void yourFunction()
    {
       ...
       if(condition)
       {
          img1 = cv::imread("/home/pi/test/Gray_2Image1.jpg", 0);
       }
       else
       {
          img2 = cv::imread("/home/pi/test/Gray_2Image2.jpg", 0);
       }
       ...
       diffImage = abs(img1-img2); // make sure img1 and img2 are loaded first
       ...
    }
    

    And this is wrong:

    // global scope
    cv::Mat img1, img2, diffImage;
    
    void yourFunction()
    {
       ...
       if(condition)
       {
          // wrong: you are creating a local variable that shadows the global one
          cv::Mat img1 = cv::imread("/home/pi/test/Gray_2Image1.jpg", 0);
       }
       ...
       diffImage = abs(img1-img2); // img1 is the global variable and not the local one in the previous if block!
       ...
    }