结合前面学习的空间滤波基础知识:http://blog.sina.com.cn/s/blog_a98e39a201010v17.html以及
Mat的详细介绍:http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/core/mat - the basic image container/mat - the basic image container.html#matthebasicimagecontainer,
下面开始研究矩阵的掩码操作,即滤波操作。
代码来源:D:\OpenCv2.3.1\opencv\samples\cpp\tutorial_code\core\mat_mask_operations
用到的函数:filte2D,卷积函数
void filter2D(InputArray src, OutputArray dst, int ddepth, InputArray kernel, Point anchor=Point(-1,-1), double delta=0, intborderType=BORDER_DEFAULT )
Parameters: |
- src – Source image.
- dst – Destination image of the same size and the same number of channels as src .
- ddepth – Desired depth of the destination image. If it is negative, it will be the same as src.depth() .
- kernel – Convolution kernel (or rather a correlation kernel), a single-channel floating point matrix. If you want to apply different kernels to different channels, split the image into separate color planes using split() and process them individually.
- anchor – Anchor of the kernel that indicates the relative position of a filtered point within the kernel. The anchor should lie within the kernel. The special default value (-1,-1) means that the anchor is at the kernel center.
- delta – Optional value added to the filtered pixels before storing them in dst .
- borderType – Pixel extrapolation method. See borderInterpolate() for details
|
// 025 矩阵掩码操作,滤波.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
void Sharpen(const Mat& myImage,Mat& Result);
int _tmain(int argc, _TCHAR* argv[])
{
// help(argv[0]);
// const char* filename = argc >=2 ? argv[1] : "lena.jpg";
const char* filename = "lena.jpg";
Mat I, J, K;
I = imread( filename, CV_LOAD_IMAGE_COLOR);
namedWindow("Input", CV_WINDOW_AUTOSIZE);
namedWindow("Output", CV_WINDOW_AUTOSIZE);
imshow("Input", I);
double t = (double)getTickCount();
Sharpen(I, J);
t = ((double)getTickCount() - t)/getTickFrequency();
cout << "Hand written function times passed in seconds: " << t << endl;
imshow("Output", J);
cvWaitKey(0);
//表示掩码的 Mat 对象
Mat kern = (Mat_<char>(3,3) << 0, -1, 0,
-1, 5, -1,
0, -1, 0);
t = (double)getTickCount();
filter2D(I, K, I.depth(), kern );
t = ((double)getTickCount() - t)/getTickFrequency();
cout << "Built-in filter2D time passed in seconds: " << t << endl;
imshow("Output", K);
cvWaitKey(0);
return 0;
}
void Sharpen(const Mat& myImage,Mat& Result)
{
CV_Assert(myImage.depth() == CV_8U); // 仅接受uchar图像
const int nChannels = myImage.channels();
Result.create(myImage.size(),myImage.type());
for(int j = 1 ; j < myImage.rows-1; ++j)
{
//获取了其中每一行像素的指针(分别是前一行、当前行和下一行)
const uchar* previous = myImage.ptr<uchar>(j - 1);
const uchar* current = myImage.ptr<uchar>(j );
const uchar* next = myImage.ptr<uchar>(j + 1);
uchar* output = Result.ptr<uchar>(j); //指向计算结果存储位置的指针,第j行的指针
for(int i= nChannels;i < nChannels*(myImage.cols-1); ++i) //通道数*列数
{
*output++ = saturate_cast<uchar>(5*current[i] //saturate_cast<uchar>,类型转换为uchar
-current[i-nChannels] - current[i+nChannels] - previous[i] - next[i]);
}
}
//边界点置0
Result.row(0).setTo(Scalar(0)); //上边界
Result.row(Result.rows-1).setTo(Scalar(0)); // 下边界
Result.col(0).setTo(Scalar(0)); //左边界
Result.col(Result.cols-1).setTo(Scalar(0)); //右边界
}
运行结果:
从运行结果可以看出,系统自带的filter2D函数效率更高!