OpenCV学习02-矩阵的掩膜操作 4-测量程序运行时间;getTickCount()与getTickFrequency()

自编掩膜(Mask)程序:得到图像

调用 //调用filter2D得到的图像:


在图像处理中,经常会碰到掩膜(Mask)这个词。那么这个词到底是什么意思呢?下面来简单解释一下。

1.什么是掩膜

首先我们从物理的角度来看看mask到底是什么过程。 
在半导体制造中,许多芯片工艺步骤采用光刻技术,用于这些步骤的图形“底片”称为掩膜(也称作“掩模”),其作用是:在硅片上选定的区域中对一个不透明的图形模板遮盖,继而下面的腐蚀或扩散将只影响选定的区域以外的区域。 
图像掩膜与其类似,用选定的图像、图形或物体,对处理的图像(全部或局部)进行遮挡,来控制图像处理的区域或处理过程。

2.掩膜的用法

2.1 提取感兴趣区:用预先制作的感兴趣区掩膜与待处理图像相乘,得到感兴趣区图像,感兴趣区内图像值保持不变,而区外图像值都为0; 
2.2 屏蔽作用:用掩膜对图像上某些区域作屏蔽,使其不参加处理或不参加处理参数的计算,或仅对屏蔽区作处理或统计; 
2.3 结构特征提取:用相似性变量或图像匹配方法检测和提取图像中与掩膜相似的结构特征; 
2.4 特殊形状图像的制作。

3.掩膜运算的一个小实例

以图和掩膜的与运算为例: 
原图中的每个像素和掩膜中的每个对应像素进行与运算。比如1 & 1 = 1;1 & 0 = 0; 
比如一个3 * 3的图像与3 * 3的掩膜进行运算,得到的结果图像就是: 
这里写图片描述

4.小结

1.图像中,各种位运算,比如与、或、非运算与普通的位运算类似。 
2.如果用一句话总结,掩膜就是两幅图像之间进行的各种位运算操作。

#include <opencv2\opencv.hpp>
#include <iostream>

#include <math.h>

using namespace std;
using namespace cv;


int main()
{
	Mat src, dst;
	src = imread("D:/demo01.jpg");
	if (!src.data)
	{
		cout << "could not load image..." << endl;
		return -1;
	}
	namedWindow("source image", CV_WINDOW_AUTOSIZE);
	imshow("source image", src);

	//1).empty() 判断文件读取是否正确
	//2).rows 获取图像行数(高度)
	//3).cols 获取图像列数(长度)
	//4).channels() 获取图像通道数
	//5).depth() 获取图像位深度
	//【1】记录程序开始点timeStart
	double timeStart = (double)getTickCount();//计算时间语句

	//进行矩阵的掩膜操作
	int cols = (src.cols - 1)*src.channels();//837 //获取图像的列数,一定不要忘记图像的通道数
	int offsetx = src.channels();//图像的通道数 3 
	int rows = src.rows;//220

	dst = Mat::zeros(src.size(),src.type());//返回指定的大小和类型的数组 创建一个跟src一样大小 类型的图像矩阵
	for (int row = 1; row < (rows - 1); row++)
	{
		//Mat.ptr<uchar>(int i=0) 获取像素矩阵的指针,索引i表示第几行,从0开始计行数。
		//获得当前行指针const uchar*  current= myImage.ptr<uchar>(row );
		//获取当前像素点P(row, col)的像素值 p(row, col) =current[col]
		//Mat.ptr<uchar>(row):获取第row行的图像像素指针。图像的行数从0开始计数
		//获取点P(row, col)的像素值:P(row.col) = Mat.ptr<uchar>(row)[col]
		const uchar *previous = src.ptr<uchar>(row - 1);//获取上一行指针
		const uchar *current = src.ptr<uchar>(row);//获取当前行的指针
		const uchar *next = src.ptr<uchar>(row + 1);//获取下一行的指针
		uchar *output = dst.ptr<uchar>(row);//目标对象像素
		for (int col = offsetx; col < cols; col++)
		{
			//像素范围处理saturate_cast<uchar>
			output[col] = saturate_cast<uchar>(5 * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col]));
			//current[col-offsetx]是当前的像素点的左边那个像素点的位置,因为一个像素点有三个通道
			//current[col+offsetx]是当前的像素点的右边那个像素点的位置,因为一个像素点有三个通道
			//previous[col]表示当前像素点对应的上一行的那个像素点
			//next[col]表示当前像素点对应的下一行的那个像素点
		}

	}

	//OpenCV提高了函数filter2D来实现掩膜操作:
	//Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);//定义掩膜
	//调用filter2D
	//filter2D(src, dst, src.depth(), kernel);

	double timeconsume = ((double)getTickCount() - timeStart) / getTickFrequency();
	cout << "运行上面程序共耗时: " << timeconsume << endl;

	//输出 掩膜操作后的图像
	namedWindow("contrast image",CV_WINDOW_AUTOSIZE);
	imshow("contrast image",dst);

	waitKey(0);
	return 0;
}

所谓掩膜其实就是一个矩阵,然后根据这个矩阵重新计算图片中像素的值。 
掩膜主要有以下用途:

  • 提取感兴趣区,用预先制作的感兴趣区掩模与待处理图像相乘,得到感兴趣区图像,感兴趣区内图像值保持不变,而区外图像值都为0。
  • 屏蔽作用,用掩模对图像上某些区域作屏蔽,使其不参加处理或不参加处理参数的计算,或仅对屏蔽区作处理或统计。
  • 结构特征提取,用相似性变量或图像匹配方法检测和提取图像中与掩模相似的结构特征。
  • 特殊形状图像的制作。

掩膜操作实现图像对比度的提高:

图像像素指针的获取:

Mat.ptr<uchar>(row):获取第row行的图像像素指针。图像的行数从0开始计数

获取点P(row,col)的像素值:P(row.col)= Mat.ptr<uchar>(row)[col]
  • 1
  • 2
  • 3

使用的掩膜: 
这里写图片描述

红色是中心元素I(i,j)。掩膜操作公式: 

I(i,j)=5∗I(i,j)−[I(i−1,j)+I(i+1,j)+I(i,j−1)+I(i,j+1)]

用此掩膜从上至下,从左至右对图像进行操作,得到的图像就是增强对比度的图像。

4-测量程序运行时间;getTickCount()与getTickFrequency()

有的时候,想知道要我们的程序一共运行了多长时间,这个很常用,也很简单,仅仅需要两个函数即可。

opencv里使用getTickCount()与getTickFrequency()函数记录时间;

函数解释:

getTickCount()函数:它返回从操作系统启动到当前所经的计时周期数。

getTickFrequency()函数:返回CPU的频率。

#include <opencv2\opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
	//1 记录程序开始运行点 timeStart
	double timeStart = (double)getTickCount();

	//2 此部分为需要测试运行时间的程序
	int a = 0;
	while (a < 50000000)
	{
		a++;
	}
	//3 记录程序消耗的总时间timeConsume 
	double timeConsume = ((double)getTickCount() - timeStart) / getTickFrequency();
	//getTickCount() 返回从操作系统启动到当前所经历的计时周期数
	//getTickFrequency 返回CPU的频率
	cout << "运行上面程序共耗时:" << timeConsume << "秒\n" << endl;
	system("pause");
	return 0;
}

程序说明

想要测量程序运行时间,只需要添加代码中第【1】步,和【3】步两行代码即可。 
中间内容替换为自己编写好的程序。


猜你喜欢

转载自blog.csdn.net/weixin_40807247/article/details/80893385