OpenCV 图像金字塔+通道分离+Canny算子求取边缘

OpenCV 图像金字塔+通道分离+Canny边缘的一个实例


学习OpenCV上一个不太完整的例子,对图像做两次金字塔缩小,做一次三通道分离得到一通道,再做Canny算子求边缘。把它完整填补了一下,写一下心得:

// CannyWay.cpp -- Try Canny to find the contours
#include 
#include 
#include 
#include 
#define _CRT_SECURE_NO_WARNINGS

using namespace std;
using namespace cv;

IplImage* doCanny(
    IplImage* in,
    double lowThresh,
    double highThresh,
    int aperture
    ){
    if (in->nChannels != 1)
        return(0); //Canny only handles gray scale images
    IplImage* out = cvCreateImage(
        cvSize(in->width, in->height),
        IPL_DEPTH_8U,
        1);
    cvCanny(in, out, lowThresh, highThresh, aperture);
    return(out);
}

IplImage* doPyrDown(
    IplImage* in,
    int filter = IPL_GAUSSIAN_5x5
    ){
    // Best to make sure input image is divisable by two.
    //
    assert(in->width % 2 == 0 && in->height % 2 == 0);

    IplImage* out = cvCreateImage(
        cvSize(in->width / 2, in->height / 2),
        in->depth,
        in->nChannels);
    cvPyrDown(in, out);
    return(out);
};

int main()
{
    IplImage* img0 = cvLoadImage("timg.jpg");
    IplImage* img1 = doPyrDown(img0, IPL_GAUSSIAN_5x5);
    IplImage* img2 = doPyrDown(img1, IPL_GAUSSIAN_5x5);

    IplImage* bimg2 = cvCreateImage(cvSize(img2->width, img2->height), 8, 1);
    IplImage* gimg2 = cvCreateImage(cvSize(img2->width, img2->height), 8, 1);
    IplImage* rimg2 = cvCreateImage(cvSize(img2->width, img2->height), 8, 1);

    cvSplit(img2, bimg2, gimg2, rimg2, 0);

    IplImage* img3 = doCanny(bimg2, 10, 100, 3);


    cvNamedWindow("OriginalPic", CV_WINDOW_AUTOSIZE);
    cvShowImage("OriginalPic", img0);
    cvNamedWindow("ZoomOUT1", CV_WINDOW_AUTOSIZE);
    cvShowImage("ZoomOUT1", img1);
    cvNamedWindow("ZoomOUT2", CV_WINDOW_AUTOSIZE);
    cvShowImage("ZoomOUT2", img2);
    cvNamedWindow("ZoomOUT3", CV_WINDOW_AUTOSIZE);
    cvShowImage("ZoomOUT3", img3);

    cvWaitKey(0);
    cvReleaseImage(&img0);
    cvReleaseImage(&img1);
    cvReleaseImage(&img2);
    cvReleaseImage(&img3);
    cvReleaseImage(&bimg2);
    cvReleaseImage(&gimg2);
    cvReleaseImage(&rimg2);
    cvDestroyAllWindows;
    return 0;

}

OpenCV 图像金字塔+通道分离+Canny算子求取边缘_第1张图片
OpenCV 图像金字塔+通道分离+Canny算子求取边缘_第2张图片
OpenCV 图像金字塔+通道分离+Canny算子求取边缘_第3张图片
OpenCV 图像金字塔+通道分离+Canny算子求取边缘_第4张图片

  1. 图像金字塔要点

    每次缩小之前做一次判断,如果长宽不都能被2整除,就放弃进行缩小。原因是cvPyrDown只能对可整除的长宽进行处理。
    *这里有一些可以优化的地方,如果不能被2整除,可以考虑把不能被2整除的长或宽切掉一个像素。

IplImage* doPyrDown(
    IplImage* in,
    int filter = IPL_GAUSSIAN_5x5
    ){
    // Best to make sure input image is divisable by two.
    //
    assert(in->width >= 2 && in->height >= 2);
    IplImage* in2 = cvCreateImage(cvSize(floor(in->width/2)*2,floor(in->height/2)*2), in->depth, in->nChannels);
    CvRect Rect = cvRect(0, 0, floor(in->width/2)*2, floor(in->height/2)*2);
    cvSetImageROI(in, Rect);
    cvCopy(in, in2);

    IplImage* out = cvCreateImage(
        cvSize(in2->width / 2, in2->height / 2),
        in2->depth,
        in2->nChannels);
    cvPyrDown(in2, out);
    return(out);
};

如下图所示大小变化
OpenCV 图像金字塔+通道分离+Canny算子求取边缘_第5张图片

  1. 通道分离要点
    注意到三个通道的命名,是反过来的,蓝色通道在前,红色通道在最后。
    cvSplit(img2, bimg2, gimg2, rimg2, 0);

  2. Canny算子求边缘要点
    Canny只能对单通道图像直接运算,如果图像本身含有多个通道需要首先进行分离。

你可能感兴趣的:(OpenCV+Qt,opencv,图像金字塔,多通道图像分离,Canny分离)