您的位置:首页 > 运维架构

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

2016-12-29 16:47 471 查看

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

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

// CannyWay.cpp -- Try Canny to find the contours
#include <iostream>
#include <opencv2/opencv.hpp>
#include <ctime>
#include <opencv/cv.h>
#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;

}










图像金字塔要点

每次缩小之前做一次判断,如果长宽不都能被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);
};


如下图所示大小变化



通道分离要点

注意到三个通道的命名,是反过来的,蓝色通道在前,红色通道在最后。

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


Canny算子求边缘要点

Canny只能对单通道图像直接运算,如果图像本身含有多个通道需要首先进行分离。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息