OpenCv-002-矩阵的掩膜操作

所谓的掩膜就是用选定的图像、图形或物体,对处理的图像(全部或局部)进行遮挡,来控制图像处理的区域或处理过程。用于覆盖的特定图像或物体称为掩模或模板。光学图像处理中,掩模可以足胶片、滤光片等。
数字图像处理中,掩模为二维矩阵数组,有时也用多值图像。数字图像处理中,图像掩模主要用于:

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

一,方法一:自定义方法

1,打开图像

Mat src, dst; //定义cv变量
	src = imread("F:/opencv/InputImg/h4.jpg");
	if (!src.data) { cout << "open failed" << endl; return -1; }
	namedWindow("input window", CV_WINDOW_AUTOSIZE);
	imshow("input img", src);

2,获取图像矩阵的宽度
src.cols 获取图像的列数
src.channels() 获取图像的通道数

int cols = src.cols*src.channels();  //图像矩阵的宽度(列数)等于图像的列数*通道数(红绿蓝三通道)(每个像素点存的是三通道的像素值)

3,获取图像矩阵的高度

	int rows = src.rows;

在这里插入图片描述
图像存储过程中,每个单元存放各个通道的数值,所以列数需要乘通道数,而行数不用
4,初始化要输出的Mat图像对象,使其和原来的图像大小一致

	dst = Mat::zeros(src.size(), src.type());//初始化要输出的图像变量

5,遍历操作每个像元值
src.ptr<uchar>(row) 获取当前行的头指针

for (int row = 1; row < (rows - 1); row++) {  //从第二行到倒数第二行进行操作
		const uchar* current = src.ptr<uchar>(row);  //获取当前行的头指针
		const uchar* previous=src.ptr<uchar>(row + 1); //获取上一行的指针
		const uchar* next = src.ptr<uchar>(row-1);  //获取下一行的指针
		uchar *output = dst.ptr<uchar>(row); //获取要输出图像的每行的头指针便于赋值操作
		for (int col = src.channels(); col < cols; col++) {  //对每列进行遍历
			output[col] = saturate_cast<uchar>(5 * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col]));//利用公式进行锐化处理
		}//saturate_cast<uchar> 处理数据在0到255之间
	}

saturate_cast<uchar> 处理数据在0到255之间
6,输出图像

namedWindow("output window", CV_WINDOW_AUTOSIZE);
	imshow("new img", dst);

当然,在实际操作过程中,不用这么麻烦,因为系统以及集成了api,下面介绍第二种方法

二,方法二:调用系统api

	Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);//定义研磨方式
	filter2D(src, dst, src.depth(), kernel);//调用系统api进行研磨

两段代码就取代了第一种方法的几个for循环

三,案例演示

#include <opencv2\opencv.hpp>
#include <iostream>
#include <math.h>
using namespace std;
using namespace cv;
int main(int argc,char **argv)
{
	Mat src, dst; //定义cv变量
	src = imread("F:/opencv/InputImg/h4.jpg");
	if (!src.data) { cout << "open failed" << endl; return -1; }
	namedWindow("input window", CV_WINDOW_AUTOSIZE);
	imshow("input img", src);
	int cols = src.cols*src.channels();  //图像矩阵的宽度(列数)等于图像的列数*通道数(红绿蓝三通道)(每个像素点存的是三通道的像素值)
	int offsetx = src.channels(); //获取图像的通道数
	int rows = src.rows;
	dst = Mat::zeros(src.size(), src.type());//初始化要输出的图像变量
	for (int row = 1; row < (rows - 1); row++) {  //从第二行到倒数第二行进行操作
		const uchar* current = src.ptr<uchar>(row);  //获取当前行的头指针
		const uchar* previous=src.ptr<uchar>(row + 1); //获取上一行的指针
		const uchar* next = src.ptr<uchar>(row-1);  //获取下一行的指针
		uchar *output = dst.ptr<uchar>(row); //获取要输出图像的每行的头指针便于赋值操作
		for (int col = src.channels(); col < cols; col++) {  //对每列进行遍历
			output[col] = saturate_cast<uchar>(5 * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col]));//利用公式进行锐化处理
		}//saturate_cast<uchar> 处理数据在0到255之间
	}
	namedWindow("output window", CV_WINDOW_AUTOSIZE);
	imshow("new img", dst);
	//方法2 调用系统api
	Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);//定义研磨方式
	filter2D(src, dst, src.depth(), kernel);//调用系统api进行研磨

	namedWindow("output window", CV_WINDOW_AUTOSIZE);
	imshow("api img", dst);
	waitKey(0);
	return 0;
}

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值