OpenCV 【十三】矩阵的掩码操作
目录
1 Mask掩膜/滤波核
1.1 原理
1.2 实例
1.3 结果对比
2. filter2D函数
2.1 原理
2.2 实例
2.3 结果
1 Mask掩膜/滤波核
1.1 原理
矩阵的掩码操作很简单。其思想是:根据掩码矩阵(也称作核)重新计算图像中每个像素的值。掩码矩阵中的值表示近邻像素值(包括该像素自身的值)对新像素值有多大影响。从数学观点看,我们用自己设置的权值,对像素邻域内的值做了个加权平均。
思考一下图像对比度增强的问题。我们可以对图像的每个像素应用下面的公式:
上面那种表达法是公式的形式,而下面那种是以掩码矩阵表示的紧凑形式。使用掩码矩阵的时候,我们先把矩阵中心的元素(上面的例子中是(0,0)位置的元素,也就是5)对齐到要计算的目标像素上,再把邻域像素值和相应的矩阵元素值的乘积加起来。虽然这两种形式是完全等价的,但在大矩阵情况下,下面的形式看起来会清楚得多。
我们创建了一个与输入有着相同大小和类型的输出图像。根据图像的通道数,我们有一个或多个子列。我们用指针在每一个通道上迭代,因此通道数就决定了需计算的元素总数。
Result.create(myImage.size(),myImage.type()); const int nChannels = myImage.channels();
利用C语言的[]操作符,我们能简单明了地访问像素。因为要同时访问多行像素,所以我们获取了其中每一行像素的指针(分别是前一行、当前行和下一行)。此外,还需要一个指向计算结果存储位置的指针。有了这些指针后,我们使用[]操作符,就能轻松访问到目标元素。为了让输出指针向前移动,我们在每一次操作之后对输出指针进行了递增(移动一个字节):
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); for(int i= nChannels;i < nChannels*(myImage.cols-1); ++i){*output++ = saturate_cast<uchar>(5*current[i]-current[i-nChannels] - current[i+nChannels] - previous[i] - next[i]);} }
在图像的边界上,上面给出的公式会访问不存在的像素位置(比如(0,-1))。因此我们的公式对边界点来说是未定义的。一种简单的解决方法,是不对这些边界点使用掩码,而直接把它们设为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)); // 右边界
函数如下实例中Sharpen所示。
1.2 实例
#include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/features2d/features2d.hpp> #include <opencv2/highgui/highgui.hpp> using namespace std; using namespace cv; void Sharpen(const Mat& myImage, Mat& Result); int main(int argc, char* argv[]) {Mat I, J;I = imread("C:\\code\\sdk_for_thinmanmini\\data\\rgb.jpg");int times = 1;double t = (double)getTickCount(); for (int i = 0; i < times; ++i)Sharpen(I, J); t = 1000 * ((double)getTickCount() - t) / getTickFrequency();t /= times; cv::imwrite("C:\\code\\sdk_for_thinmanmini\\data\\rgb2.jpg", J);cout << "Time of Sharpen (averaged for "<< times << " runs): " << t << " milliseconds." << endl; getchar();return 0; } void Sharpen(const Mat& myImage, Mat& Result) {CV_Assert(myImage.depth() == CV_8U); // 仅接受uchar图像 Result.create(myImage.size(), myImage.type());const int nChannels = myImage.channels(); 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); for (int i = nChannels; i < nChannels*(myImage.cols - 1); ++i){*output++ = saturate_cast<uchar>(5 * current[i]- current[i - nChannels] - current[i + nChannels] - previous[i] - next[i]);}} 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)); }
1.3 结果对比
可以看出,实验后的结果明显细节更加的突出
2. filter2D函数
2.1 原理
滤波器在图像处理中的应用太广泛了,因此OpenCV也有个用到了滤波器掩码(某些场合也称作核)的函数。不过想使用这个函数,你必须先定义一个表示掩码的 Mat 对象:
Mat kern = (Mat_<char>(3,3) << 0, -1, 0,-1, 5, -1,0, -1, 0);
然后调用 filter2D 函数,参数包括输入、输出图像以及用到的核:
filter2D(I, K, I.depth(), kern );
它还带有第五个可选参数——指定核的中心,和第六个可选参数——指定函数在未定义区域(边界)的行为。使用该函数有一些优点,如代码更加清晰简洁、通常比 自己实现的方法 速度更快(因为有一些专门针对它实现的优化技术)等等。
2.2 实例
#include <opencv2/imgproc.hpp>Mat I, J;I = imread("C:\\code\\sdk_for_thinmanmini\\data\\rgb.jpg");//![filter2D]filter2D(I, J, I.depth(), kernel);//![filter2D]t = ((double)getTickCount() - t) / getTickFrequency();cout << "Built-in filter2D time passed in seconds: " << t << endl; imshow("Output", J); waitKey();return EXIT_SUCCESS;
2.3 结果
相关文章:

【ArrayList】为什么java.util.concurrent 包里没有并发的ArrayList实现?
2019独角兽企业重金招聘Python工程师标准>>> 为什么java.util.concurrent 包里没有并发的ArrayList实现? 问:JDK 5在java.util.concurrent里引入了ConcurrentHashMap,在需要支持高并发的场景,我们可以使用它代替HashMa…

Android实现买卖商品小游戏
之前为了学习GreenDao,写的练手项目,欢迎指点 仿手游《混》《买房记》,单机游戏,无需联网 1、主界面 2、游戏界面 可以选择地区出发随机事件,进行贷款/还款,治疗,还债,买卖商品&…

OpenCV 【十四】改变图像的对比度和亮度高度关联章节:OpenCV 【十】——Gamma校正 ——图像灰度变化
目录 0 提问 1.1 原理 trick: 1.2 代码 1.3 结果 0 提问 访问像素值 用0初始化矩阵 saturate_cast 是做什么用的,以及它为什么有用 1.1 原理 图像处理 一般来说,图像处理算子是带有一幅或多幅输入图像、产生一幅输出图像的函数。 图像变换可分…

getRotationMatrix2D 函数
cv::Mat cv::getRotationMatrix2D( Point2f center, double angle, double scale ) {// 角度转换angle * CV_PI/180;// 计算旋转矩阵角度double alpha cos(angle)*scale;double beta sin(angle)*scale;Mat M(2, 3, CV_64F);double* m (double*)M.data;// 构建旋转矩阵m[0] …

java学习笔记-java中运算符号的优先顺序
java中各种运算符具有优先级顺序,一般会先计算优先级高的,再计算优先级低的。可以使用()使得优先级变为最高。在算术运算中,优先级为 --* / -在在逻辑运算中的优先级是 ! 取反&& || & |在位运算中的优先级 ÿ…

红帽发布第四季度和2019财年报告,多项指标维持两位数增速
近日,红帽公司发布了其第四季度和2019财年报告。这是在被 IBM以340亿美元的价格收购 后,红帽公布的第一份财报,数据颇为亮眼。 报告显示,红帽公司第四季度总收入8.79亿美元,同比增长14%;整个财年营收34亿美…

OpenCV 【十五】绘直线/椭圆/矩形/圆及其填充
目录 1. 概况 2. 原理 2.1 Point 2.2 Scalar 3. 代码 4.结果 1. 概况 如何用 Point 在图像中定义 2D 点 如何以及为何使用 Scalar 用OpenCV的函数 line 绘 直线 用OpenCV的函数 ellipse 绘 椭圆 用OpenCV的函数 rectangle 绘 矩形 用OpenCV的函数 circle 绘 圆 用Op…

spring-boot Junit4单元测试
2019独角兽企业重金招聘Python工程师标准>>> 如果是使用spring-boot 1.4以下的版本 RunWith(SpringJUnit4ClassRunner.class) SpringApplicationConfiguration(classes 启动类.class) public class ApplicationTest {//代码省略 } 使用SpringApplicationConfigurat…

VideoCapture 读取视频文件,显示视频(帧)信息
#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> using namespace std; using namespace cv; int main() {// 定义相关VideoCapture对象VideoCapture capture;…

Go 1.12发布:改进了运行时性能以及模块支持
Go最新版本1.12于近日发布,该版本并没有改动语法规范,它主要对运行时性能、编译工具链以及模块系统等进行了优化。另外,它还为TLS 1.3提供了opt-in支持,同时改进了对MacOS和iOS等系统的支持。 Go 1.12最大的更新亮点是改进了Go运行…

OpenCV 【十六】RNG随机数发生器putText绘制文字
1 目的 使用 随机数发生器类 (RNG) 并得到均匀分布的随机数。 通过使用函数 putText 显示文字。 第一步是实例化一个 Random Number Generator(随机数发生器对象) (RNG): RNG rng( 0xFFFFFFFF ); 初始化一个 0 矩阵(代表一个全黑的图像), 并且指定它…

分享一段Java搞笑的代码注释
原文:http://www.cnblogs.com/xdp-gacl/p/4198935.html // _ooOoo_ // o8888888o // 88" . "88 // (| -_- |) // …

视频写操作,通道分离与合并
#include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> using namespace std; using namespace cv; int main() { // 视频读入与输出路径设置 string sourceVideoPath "..\\images\\test.avi"; st…

JAVA中的并发工具 -- CountDownLatch、CyclicBarrier、Semaphore
2019独角兽企业重金招聘Python工程师标准>>> CountDownLatchCountDownLatch允许一个或多个线程等待其他线程完成操作。 CountDownLatch的构造函数接受一个int类型的参数作为计数器,如果你想等待N个点完成,这里就传入N。 当我们调用CountDownL…

OpenCV 【十七】离散傅立叶变换
目录 1 key 2 原理 3 实例 3代码 4运行结果 5应用举例 1 key 什么是傅立叶变换及其应用? 如何使用OpenCV提供的傅立叶变换? 相关函数的使用,如: copyMakeBorder(), merge(), dft(), getOptimalDFTSize(), log() 和 normalize() . 简单点说就是…

ubuntu下nginx+php5的部署
ubuntu下nginxphp5环境的部署和centos系统下的部署稍有不同,废话不多说,以下为操作记录:1)nginx安装rootubuntutest01-KVM:~# sudo apt-get update && sudo apt-get upgraderootubuntutest01-KVM:~# sudo apt-get install…

图像质量评价,图片放大和缩小
#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <iostream>using namespace cv;using namespace std;// PSNR 峰值信噪比计算 返回数值为30-50dB 值越大越好double PSNR(con…

软件开发--深入理解程序的结构
程序由不同的段构成(代码段,数据段)1.程序的静态特征就是指令和数据2.程序的动态特征就是执行指令处理数据 A.段传统上,一个程序一般会有这几个段:.text 、.data、.bss段a.如果处理器由内存管理单元,那么可执行程序被加载到内存以后ÿ…

OpenCV 【十八】图像平滑处理/腐蚀与膨胀(Eroding and Dilating)/开闭运算,形态梯度,顶帽,黑帽运算
图像滤波总结(面试经验总结)https://blog.csdn.net/Darlingqiang/article/details/79507468 目录 part one 图像平滑处理 1原理 2代码 3效果 part two 腐蚀与膨胀(Eroding and Dilating) 1原理 2代码 3运行结果 part three更多形态学变换 1 原…

第九章 大网高级 ASA 高级设置
url 过滤实验要求:1、 创建class-map 类映射,识别传输流量。2、 创建policy-map策略映射,关联class-map。3、 应用到policy-map到接口上。一、 配置接口地址二、 配置路由,网络互通三、 创建特权和vty 密码四、 验证网络互通五、 …

linux基础知识-链接列表
linux基础知识-链接列表 1. 安装centos 7 1.1 Linux的初识1.2 centOS 7安装教程1.3 centOS 7配置ip和网络问题排查1.4 PuTTY和Xshell远程连接与密钥认证登录1.5 单用户和救援模式2. 文件与目录管理 1.6 系统目录结构、文件类型及相关命令1.7 文件目录管理及相关的命令使用方法…

OpenCV 【十九】图像金字塔/基本的阈值操作/实现自己的线性滤波器
目录 1.part one 图像金字塔 1.1原理 1.1.1图像金字塔 1.1.2高斯金字塔 1.2代码 1.3运行结果 2.part two 基本的阈值操作 2.1原理 2.1.1阈值化的类型: 2.1.2阈值类型1:二进制阈值化 2.1.3阈值类型2:反二进制阈值化 2.1.4阈值类型…

Get started with ros -- 1
原创博文:转载请标明出处(周学伟):http://www.cnblogs.com/zxouxuewei/tag/ 一.Introduction: 机器人操作系统(ROS)是使机器人系统的不同部分能够发现,发送和接收数据的通信接口。MA…

利用 createTrackbar 进行二值化
#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include <iostream> //createTrackbar的回调响应函数 void onChangeTrackBar (int pos,void* data) {// 强制类型转换cv::Mat srcImage *(cv::Mat*)(data); cv:…

ASP.NET Core 2.2中的Endpoint路由
Endpoint路由 在ASP.NET Core 2.2中,新增了一种路由,叫做Endpoint(终结点)路由。本文将以往的路由系统称为传统路由。 本文通过源码的方式介绍传统路由和Endpoint路由部分核心功能和实现方法,具体功能上的差异见官方文…

OpenCV 【二十】给图像添加边界
目录 1原理 2 代码 3 运行结果 1原理 前一节我们学习了图像的卷积操作。一个很自然的问题是如何处理卷积边缘。当卷积点在图像边界时会发生什么,如何处理这个问题? 大多数用到卷积操作的OpenCV函数都是将给定图像拷贝到另一个轻微变大的图像中&#…

Linux账户安全管理--useradd、groupadd、passwd、chown、chmod工具
groupadd-g 设置组id号实例: groupadd tomcatgroupadd -g600 tomcat删除组用groupdelgroupdel tomcatuseradd-c comment 给新用户添加备注 -d home_dir 为主目录指定一个名字(如果不想用登录名作为主目录名的话) -e expire_date 用Y…

Rect 选择感兴趣区域
#include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> // 全局变量源图像 cv::Mat srcImage; // 方法1 利用Rect选择区域(100, 180, 150, 50) void regionExtraction(int xRoi, int yRoi, int widthRoi, int…

paramiko的使用
1 import paramiko2 import sys3 4 5 user "root"6 pwd "123456"7 8 9 10 # 上传文件 11 def sftp_upload_file(server_path, local_path): 12 try: 13 t paramiko.Transport((ip, 22)) 14 t.connect(usernameuser, passwordpwd) …

【C++】多线程与并发【一】
文章目录part 0:多线程简介part 1:多线程构造它用于构造线程对象。参量part 2:多线程析构它破坏线程对象。part 3:多线程operator参量 Parameters返回值Data racespart 4:joinable 它返回线程ive对象是否可连接,则返回true,否则返回false。 表示的是否可…