简体   繁体   中英

OpenCV: Data type assertion fail with split() function

I'm trying to follow the discreet fourier transform (dft) example here: http://docs.opencv.org/doc/tutorials/core/discrete_fourier_transform/discrete_fourier_transform.html

I'm running 2.4.8 on Visual Studio 2013 Express in Windows 8.

I've modified the example so that instead of loading a greyscale image I'm using a colour image captured from my webcam (loaded into a Mat variable).

When I run the example above, I get the following error:

"Assertion Failed Tp>::channels == m.channels()) in cv::Mat::operator"

and a break at the following line:

Mat planes[] = { Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F) };

Looking around, I saw that this is the old way of converting between types, so I added these lines to convert everything to CV_32F:

padded.convertTo(padded32, CV_32F);
Mat planes[] = { padded32, Mat::zeros(padded32.size(), CV_32F) };

Now the problem is that I get another assertion fail a few lines down at:

split(complexI, planes); 

The Error is:

"Assertion Failed (Type == CV_32FC1 || Type == CV_32FC2 || ... || Type == CV_64FC2) in cv::dft"

So now it seems like it doesn't like the CV_32F data type. I tried making the data type CV_32FC1, but it had the same error. I suspect it's related to the output data type of complexI from the dft() function but I'm not sure what to do. It may also be related to the number of channels in my input (3 channel colour vs 1 channel greyscale image).

Thanks for the help.

Complete code from the linked example:

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
int main(int argc, char ** argv)
{
    const char* filename = argc >=2 ? argv[1] : "lena.jpg";

    Mat I = imread(filename, CV_LOAD_IMAGE_GRAYSCALE);
    if( I.empty())
        return -1;

    Mat padded;                            //expand input image to optimal size
    int m = getOptimalDFTSize( I.rows );
    int n = getOptimalDFTSize( I.cols ); // on the border add zero values
    copyMakeBorder(I, padded, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT, Scalar::all(0));

    Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
    Mat complexI;
    merge(planes, 2, complexI);         // Add to the expanded another plane with zeros

    dft(complexI, complexI);            // this way the result may fit in the source matrix

    // compute the magnitude and switch to logarithmic scale
    // => log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2))
    split(complexI, planes);                   // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))
    magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitude
    Mat magI = planes[0];

    magI += Scalar::all(1);                    // switch to logarithmic scale
    log(magI, magI);

    // crop the spectrum, if it has an odd number of rows or columns
    magI = magI(Rect(0, 0, magI.cols & -2, magI.rows & -2));

    // rearrange the quadrants of Fourier image  so that the origin is at the image center
    int cx = magI.cols/2;
    int cy = magI.rows/2;

    Mat q0(magI, Rect(0, 0, cx, cy));   // Top-Left - Create a ROI per quadrant
    Mat q1(magI, Rect(cx, 0, cx, cy));  // Top-Right
    Mat q2(magI, Rect(0, cy, cx, cy));  // Bottom-Left
    Mat q3(magI, Rect(cx, cy, cx, cy)); // Bottom-Right

    Mat tmp;                           // swap quadrants (Top-Left with Bottom-Right)
    q0.copyTo(tmp);
    q3.copyTo(q0);
    tmp.copyTo(q3);

    q1.copyTo(tmp);                    // swap quadrant (Top-Right with Bottom-Left)
    q2.copyTo(q1);
    tmp.copyTo(q2);

    normalize(magI, magI, 0, 1, CV_MINMAX); // Transform the matrix with float values into a
                                            // viewable image form (float between values 0 and 1).

    imshow("Input Image"       , I   );    // Show the result
    imshow("spectrum magnitude", magI);
    waitKey();

    return 0;
}

You cannot use dft on an imagine that has more than 2 channels .

Even if the image has 2 channels the second one is interpreted as the imaginary part of a complex number so this probably not what you want anyway.

So you have 2 options: either convert the colour image that you get from your webcam to a single channel image, like a grayscale image, or apply the dft for each channel independently.

You can take a look over mix channels or split , both of them can extract the individual channels from your image and then apply dft on each of them,

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM