本系列学习笔记参考自OpenCV2.4.10之
opencv\sources\samples\cpp\tutorial_code和
http://www.opencv.org.cn/opencvdoc/2.3.2/html/genindex.html
在图像处理中,往往需要对图像提取有效的边缘。本博文将介绍Laplace边缘检测和Sobel边缘检测,以及图像的重映射。
1.Laplace_Demo.cpp(Laplace边缘检测)
Demo源码及注释如下:
#include "stdafx.h" //预编译头文件
/**
Laplace变换检测边缘
*/
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
using namespace cv;
/**
*主函数
*/
int main( int, char** argv )
{
Mat src, src_gray, dst;
int kernel_size = 3;
int scale = 1;
int delta = 0;
int ddepth = CV_16S;
const char* window_name = "Laplace Demo";
///载入图片
src = imread("D:\\opencv\\lena.png");
if( !src.data )
{ return -1; }
///高斯滤波器进行模糊进而去除噪声
GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );
///将图像转换为灰度图
cvtColor( src, src_gray, COLOR_RGB2GRAY );
///创建窗口
namedWindow( window_name, WINDOW_AUTOSIZE );
Mat abs_dst;
///Laplace变换
Laplacian( src_gray, dst, ddepth, kernel_size, scale, delta, BORDER_DEFAULT );
convertScaleAbs( dst, abs_dst );
///显示
imshow( window_name, abs_dst );
waitKey(0);
return 0;
}
运行截图:
函数Laplacian用于计算图像的Laplace边缘,函数原型为:C++: void Laplacian(InputArray src, OutputArray dst, int ddepth, int ksize=1, double scale=1, double delta=0, int borderType=BORDER_DEFAULT)参数src为灰度图,dst为与src大小相同,类型相同的Laplace边缘检测后的图像,ddepth用于描述图像的位深,ksize用于计算二阶导数滤波器的孔径大小,其值为奇数。scale为计算拉普拉斯值可选比例因子。delta为叠加在dst上的可选常量值。
2.Sobel_Demo.cpp(Sobel边缘检测)
demo源码及注释如下:
#include "stdafx.h" //预编译头文件
/**
Sobel边缘检测Demo
*/
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
using namespace cv;
/**
* 主函数
*/
int main( int, char** argv )
{
Mat src, src_gray;
Mat grad;
const char* window_name = "Sobel Demo - Simple Edge Detector";
int scale = 1;
int delta = 0;
int ddepth = CV_16S;
///载入图片
src = imread("D:\\opencv\\lena.png");
if( !src.data )
{ return -1; }
GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );
///转换为灰度图
cvtColor( src, src_gray, COLOR_RGB2GRAY );
///创建窗口
namedWindow( window_name, WINDOW_AUTOSIZE );
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y;
///X方向的梯度边缘
Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT );
convertScaleAbs( grad_x, abs_grad_x );
//Y方向的梯度边缘
Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT );
convertScaleAbs( grad_y, abs_grad_y );
///图像总体边缘
addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );
imshow( window_name, grad );
waitKey(0);
return 0;
}
运行截图:
Sobel函数的功能为通过Sobel算子计算 图像边缘,其函数声明为:C++: void Sobel(InputArray src, OutputArray dst, int ddepth, int xorder, int yorder, int ksize=3, double scale=1, double delta=0, intborderType=BORDER_DEFAULT ) 第一个参数src为输入图像,dst为输出图像,ddepth为输出图像位深,xorder与yorder分别为x方向与y方向的导数的阶数,ksize为sobel算子的大小,该值必须为奇数。
3.Remap_Demo.cpp(图像重映射)
demo源码及注释如下:
#include "stdafx.h" //预编译头文件
/**
图像重映射Demo
*/
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace cv;
///全局变量
Mat src, dst;
Mat map_x, map_y;
const char* remap_window = "Remap demo";
int ind = 0;
///函数声明
void update_map( void );
/**
* 主函数
*/
int main( int, char** argv )
{
///加载图片
src = imread("D:\\opencv\\lena.png", 1 );
///创建于src图像大小小童的dst,map_x,map_y
dst.create( src.size(), src.type() );
map_x.create( src.size(), CV_32FC1 );
map_y.create( src.size(), CV_32FC1 );
///创建窗口
namedWindow( remap_window, WINDOW_AUTOSIZE );
///循环
for(;;)
{
int c = waitKey( 1000 );
if( (char)c == 27 )
{ break; }
///重映射
update_map();
remap( src, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0) );
//显示结果
imshow( remap_window, dst );
}
return 0;
}
/**
* 四种类型的重映射
*/
void update_map( void )
{
ind = ind%4;
for( int j = 0; j < src.rows; j++ )
{ for( int i = 0; i < src.cols; i++ )
{
switch( ind )
{
case 0: //高度缩小一半,并显示在中间
if( i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75 )
{
map_x.at<float>(j,i) = 2*( i - src.cols*0.25f ) + 0.5f ;
map_y.at<float>(j,i) = 2*( j - src.rows*0.25f ) + 0.5f ;
}
else
{ map_x.at<float>(j,i) = 0 ;
map_y.at<float>(j,i) = 0 ;
}
break;
case 1: //图像上下颠倒
map_x.at<float>(j,i) = (float)i ;
map_y.at<float>(j,i) = (float)(src.rows - j) ;
break;
case 2://图像左右颠倒
map_x.at<float>(j,i) = (float)(src.cols - i) ;
map_y.at<float>(j,i) = (float)j ;
break;
case 3://图像上下颠倒的同时左右颠倒
map_x.at<float>(j,i) = (float)(src.cols - i) ;
map_y.at<float>(j,i) = (float)(src.rows - j) ;
break;
}
}
}
ind++;
}
运行截图如下:
函数原型为:C++: void remap(InputArray src, OutputArray dst, InputArray map1, InputArray map2, int interpolation, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())其中src为源图像,dst为目的图像。map1为x方向的映射关系,map2为y方向的映射关系。interpolation为插值方式。