Bootstrap

Opencv学习笔记-掩模操作

(小白一只,刚刚步入视觉领域,因为导师的项目需要用c++,所以想通过博客记录我的学习历程,有不对之处请大神及时指正,千万不要留有情面【笑哭】)

前言

学习过冈萨雷斯的《数字图像处理》的小伙伴们对掩模的功能肯定了解,掩模其实就是一个奇数乘奇数(如3*3,5*5,7*7等)的一个窗口,我们将窗口滑过整幅图像,并同时进行乘加操作,便可得到新的图像,主要用于滤波或锐化等操作。

正题

如何用Opencv进行掩模操作

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;

int main()
{
	Mat src, dst,dst1;//定义MAT头
	src = imread("2.jpg");//读取图像
	if (!src.data) {
		cout << "Sorry,your arrys is error!" << endl;
		return -1;
	}						//判断图片是否为空
	namedWindow("Input Mat", CV_WINDOW_AUTOSIZE);
	imshow("Dog", src);//显示图像

	int channels_us = src.channels();//读取图像通道数
	int rows = src.rows;//读取图像行数
	int cols = (src.cols - 1)*channels_us;//读取图像列数,并乘以通道数

	dst = Mat::zeros(src.size(), src.type());//初始化dst
	double t0 = getTickCount();//定时
	for (int row = 1; row < (rows-1); row++)//!!!重点
	{
		uchar* output = dst.ptr<uchar>(row);//指针读取图像行
		const uchar* last = src.ptr<uchar>(row-1);
		const uchar* current = src.ptr<uchar>(row);
		const uchar* next = src.ptr<uchar>(row+1);
		//掩模为:
		/*
		[ 0 -1  0
		 -1  5 -1
		  0 -1  0]
		*/
		for (int j = channels_us; j < cols; j++)
		{
			output[j] =saturate_cast<uchar> (5 * current[j] - (current[j - channels_us] + current[j + channels_us] + last[j] + next[j]));
		}
	}
	t0 = (double)(getTickCount() - t0) / getTickFrequency();
	imshow("output dog", dst);
	cout << "自己写的函数所用时间为:" << t0<<"s" << endl;

	Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
	double t1 = getTickCount();
	filter2D(src, dst1, src.depth(), kernel);
	t1 = (double)(getTickCount() - t1) / getTickFrequency();
	cout << "Opencv自带的的函数所用时间为:" << t1 << "s" << endl;
	imshow("output2 dog", dst1);

	waitKey(0);
}

1,自己写程序

注意事项:

(1),用指针访问像素,很快,还可以用迭代器,经测试用指针比较方便并比较容易理解。

(2),dst在进行赋值前需进行初始化操作

           dst = Mat::zeros(src.size(), src.type());//初始化dst

(3),掩模进行乘加操作后需将数据进行转化,用saturate_cast<uchar>()

  这个函数功能是:saturate_cast<uchar>(x),若x大于uchar的最大值,即255,则返回255;若x小于uchar的最小值,即0,则返回0。

(4),掩模操作时,需要注意行和列的最大值和最小值(可以去查掩模处理像素的工作原理),即没有进行边缘操作。

2,采用Opencv自带的filter2D函数,程序如上

注意事项:

(1),需提前定义一个核,即[0,-1,0;-1,5,-1;0,-1,0];

(2),图像深度,与原函数一致即可。

(3),Opencv中,核不会进行180°的旋转,单一般的滤波的核都是对称的,若不对称,则需要考虑180°旋转。

(4),filter2D是边缘拷贝,通过边缘拷贝补全矩阵进行计算。

3,运行时间比较

差不多处理时间是三倍多,不过opencv的函数已经优化了很多年很多代,建议今后直接用filter2D函数。

若有错误请及时指正!

 

 

 

 

;