我正在尝试学习C和OpenCV。我使用的是受O'Reilly Learning OpenCV启发的以下代码,但出现错误,并且图像未按预期显示。这段代码有什么问题吗?

# include "cv.h"
# include "highgui.h"

IplImage * doCanny(IplImage *in, double lowThresh, double highThresh, int aperture) {

    if(1 != in->nChannels){
        return 0;
    }

    IplImage *out = cvCreateImage(cvGetSize(in), IPL_DEPTH_8U, 1);
    cvCanny(in, out, lowThresh, highThresh, aperture);
    return out;
}

/* This layout works with other functions like cvPyrdown, but for some reason it doesn't work with cvCanny */
int main() {

    double lowThresh = 50;
    double highThresh = 150;
    int aperture = 3;

    IplImage *img = cvLoadImage("/tmp/lena.jpg", CV_LOAD_IMAGE_UNCHANGED);
    IplImage *out = doCanny(img, lowThresh, highThresh, aperture);

    cvNamedWindow("Example2-6", CV_LOAD_IMAGE_UNCHANGED);
    cvShowImage("Example2-6", out);
    cvWaitKey(0);
    cvReleaseImage(&img);
    cvReleaseImage(&out);
    cvDestroyWindow("Example2-6");

    return 0;
}

我在Mac OS X Yosemite上获得的输出是:

最佳答案

您的jpg图像很可能是三通道图像。您可以将此图像作为in传递到doCanny()函数中。以下代码将使doCanny()函数返回0:

if(1 != in->nChannels){
    return 0;
}

然后,您无需检查doCanny()函数的返回值是否有效。因此,您将空指针传递给以下函数,这可能会导致空指针错误:
cvShowImage("Example2-6", out);

为了使您的代码可以使用三通道图像,您应该将in函数中的doCanny()图像转换为单通道图像:
IplImage * doCanny(IplImage *in, double lowThresh, double highThresh, int aperture) {
    IplImage *out = cvCreateImage(cvGetSize(in), IPL_DEPTH_8U, 1);

    /* Convert the three-channel input image into a single-channel image. */
    IplImage* oneChannel = cvCreateImage(cvGetSize(in), IPL_DEPTH_8U, 1);
    cvCvtColor(in, oneChannel, CV_BGR2GRAY);

    cvCanny(oneChannel, out, lowThresh, highThresh, aperture);
    return out;
}

另外,您可以通过将CV_LOAD_IMAGE_GRAYSCALE作为第二个参数传递给cvLoadImage(),将输入图像直接加载为单通道图像:
IplImage *img = cvLoadImage("/tmp/lena.jpg", CV_LOAD_IMAGE_GRAYSCALE);

无论如何,您应该始终检查函数返回的值是否有效。

09-12 16:34