C++OpenCV(4):图像截取与掩膜操作

🔆 文章首发于我的个人博客:欢迎大佬们来逛逛
🔆 OpenCV项目地址及源代码:点击这里


文章目录

  • 图像截取
  • 图像掩膜操作

图像截取

ROI操作,指的是:region of interest,感兴趣区域。

我们可以对一张图片的某个感兴趣的部分进行截取然后操作,这个截取的过程叫做**ROI**操作。

通过三种方法实现ROI操作:

  • Rect选定范围
Rect::Rect(int x, int y, int width, int height);
/*******************************************************************
*			x: 					左上角x坐标
*			y:					左上角y坐标
*			width:				宽度
*			height:				 高度
*********************************************************************/
Mat roi= img(Rect(x, y, w, h));
  • Range选定范围
Range::Range(int _start, int _end) ;
/*******************************************************************
*			_start: 			 起点
*			_end:				 终点	
*********************************************************************/
Mat roi= img(Range(x,xx),Range(y,yy));
  • selectROI 专用API选择感兴趣区域,
Rect selectROI(InputArray img, bool showCrosshair = true, bool fromCenter = false);
/*******************************************************************
*			img: 					原图
*			showCrosshair:			鼠标选框,是否显示十字线
*			fromCenter:				是否以起始鼠标位置为中心
*********************************************************************/
//Rect rect= selectROI(img, false, false);
//1.显示img
//2.鼠标选择区域
//3.使用“空格”或“enter”来完成当前选择并开始一个新的选择,使用“esc”终止多个ROI选择过程  
void selectROIs(const String& windowName, InputArray img,CV_OUT std::vector<Rect>& boundingBoxes, bool showCrosshair = true, bool fromCenter = false);

案例代码:

其中具有一个selectROIs的版本,可以让我们选择多个区域。

选择一个区域后按下回车,即可保存这个部分到一个std::vector<Rect>& 中,因此最终的全部选择的区域都在这个Rect的容器中。

其中我们选择好区域后,在使用Mat重载的() 运算符即可做到在这张图片中截取一部分:

原型如下:

Mat operator()( Range rowRange, Range colRange ) const;
Mat operator()( const Rect& roi ) const
#include <iostream>
#include <opencv2/opencv.hpp>
#include <string>
#include <map>class testROI {
public:testROI() :mt(cv::imread("dog.png")) {}void show(const std::string& title = "原图") {for (auto& x : save) {cv::imshow(x.first, x.second);}cv::waitKey(0);}void testRect(int x = 50, int y = 0, int w = 200, int h = 200) {save["rect"] = mt(cv::Rect(x, y, w, h));}void testRange(int x = 50, int y = 0, int w = 200, int h = 200) {save["range"] = mt(cv::Range(x, x + h), cv::Range(y, y + w));}void testSelect() {save["select"] = mt(cv::selectROI(mt,false,false));}void testSelect2(const std::string& windowName) {std::vector<cv::Rect> mts;cv::selectROIs(windowName, mt, mts, false, false);char name = 'a';for (auto& x : mts) {save[std::to_string(name)] = mt(x);name += 1;}}
private:cv::Mat mt;std::map<std::string, cv::Mat> save;
};int main() {testROI* roi = new testROI();//roi->testRange();//roi->testRect();//roi->testSelect();cv::namedWindow("dog");roi->testSelect2("dog");roi->show();return 0;
}

在这里插入图片描述


图像掩膜操作

掩膜操作指的是:用一个矩阵和原图像进行卷积运算,重新计算像素值。

因此我们需要定义一个权重表:

  • 掩膜矩阵
  • 计算公式

掩膜操作可以提高图像的对比度,对比度提高可以增加图像感官度、锐化,让看起来有点模糊的图像更清晰。

使用以下公式可以提高图像的对比度:

F ( i , j ) = 5 ∗ F ( i , j ) − F ( i − 1 , j ) − F ( i + 1 , j ) − F ( i , j − 1 ) − F ( i , j + 1 ) F(i,j) = 5*F(i,j)-F(i-1,j)-F(i+1,j)-F(i,j-1)-F(i,j+1) F(i,j)=5F(i,j)F(i1,j)F(i+1,j)F(i,j1)F(i,j+1)

对于这个公式的掩膜矩阵可以表示成如下的形式:

在这里插入图片描述

因此我们在定义掩膜矩阵的时候就可以使用这个。

我们通过两种方式实现图片的掩膜操作:

  • filter2D实现

    • 我们使用Mat_来创建一个指定为3*3的掩膜矩阵,并且完成赋值
    • 接着使用 filter2D来实现操作。
    //定义掩膜矩阵
    Mat dst;
    Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
    filter2D(img, dst, img.depth(), kernel);
    /*******************************************************************
    *			img: 					原图
    *			dst:					存储结果图
    *			img.depth():			原图深度
    *			kernel:				 	 掩膜矩阵
    *********************************************************************/
    
  • 像素点实现,即对每个像素点执行上面的公式计算

完整代码实现:

  • testFilter2D 使用 filter2D完成掩膜计算。
  • testPixel 使用像素点完成掩膜计算。
#include <iostream>
#include <opencv2/opencv.hpp>
#include <map>class Mask {
public:Mask():mt(cv::imread("dog.png")) {saves["origin"] = mt;}void testFilter2D() {//APIcv::Mat kernel = (cv::Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);cv::filter2D(mt, saves["mask"], mt.depth(), kernel);}void testPixel() {saves["pixel"] = cv::Mat::zeros(mt.size(), mt.type());int dims = mt.channels();int rows = mt.rows - 1;int cols = (mt.cols - 1) * dims;for (int i = 1; i < rows ; i++) {uchar* pre = mt.ptr<uchar>(i - 1);	//ptr获取某一行,pre指前一行uchar* next = mt.ptr<uchar>(i + 1);	//next指下一行uchar* cur = mt.ptr<uchar>(i);		//cur是当前行uchar* output = saves["pixel"].ptr<uchar>(i); //对当前行操作for (int j = dims; j < cols; j++) {		//output[j] = cv::saturate_cast<uchar>(5 * cur[j] - pre[j] - next[j] - cur[j - dims] - cur[j + dims]);}	}}void show() {for (auto& x : saves) {cv::imshow(x.first, x.second);}cv::waitKey(0);}private:cv::Mat mt;std::map<std::string, cv::Mat> saves;
};
int main()
{Mask* pmask = new Mask();pmask->testFilter2D();pmask->testPixel();pmask->show();return 0;
}

在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/5800.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android Studio 修改AVD模拟器文件默认存储路径

AndroidStudio默认的模拟器文件路径为&#xff1a;C:\Users\用户名\.android\avd路径&#xff0c;通常windows系统上&#xff0c;C盘不是太大&#xff0c;而avd文件却不小&#xff0c;通常几个GB&#xff0c;所以有必要将avd路径换到一个非系统盘。 更换方法如下&#xff1a;H…

LocalDateTime、OffsetDateTime、ZonedDateTime之间的关系

什么是LocalDateTime&#xff1f; ISO-8601日历系统中不带时区的日期时间。 该类不存储时区&#xff0c;所以适合日期的描述&#xff0c;比如用于生日、deadline等等。 但是如果没有偏移量/时区等附加信息&#xff0c;一个时间是不能表示时间线上的某一时刻的。 什么是Offset…

20230720在ubuntu22.04系统下载+解密+合并ts切片的步骤(STEP-BY-STEP版本)

20230720在ubuntu22.04系统下载解密合并ts切片的步骤&#xff08;STEP-BY-STEP版本&#xff09; 2023/7/20 23:06 https://app1ce7glfm1187.h5.xiaoeknow.com/v2/course/alive/l_64af6130e4b03e4b54da1681?type2&app_idapp1cE7gLFM1187&pro_idterm_645c69388953e_Nhew…

论文工具——ChatGPT结合PlotNeuralNet快速出神经网络深度学习模型图

文章目录 引言正文PlotNeuralNet安装使用使用python进行编辑使用latex进行编辑 样例利用chatGPT使用chatGPT生成Latex代码利用chatGPT生成对应的python代码 总结引用 引言 介绍如何安装PlotNeuralNet工具&#xff0c;并结合chatGPT减少学习成本&#xff0c;快速出图。将按照软…

前端Web实战:从零打造一个类Visio的流程图拓扑图绘图工具

前言 大家好&#xff0c;本系列从Web前端实战的角度&#xff0c;给大家分享介绍如何从零打造一个自己专属的绘图工具&#xff0c;实现流程图、拓扑图、脑图等类Visio的绘图工具。 你将收获 免费好用、专属自己的绘图工具前端项目实战学习如何从0搭建一个前端项目等基础框架项…

java学习(二):反射

系列文章目录 https://editor.csdn.net/md/?articleId131757340 文章目录 系列文章目录参考【1】注解1. 什么是注解2. 内置注解3. 元注解4.自定义注解 【2】反射--基本概念一、反射的基本概念1. 为什么要用反射&#xff1f;2. 什么是反射&#xff1f;3. 用和不用反射的区别&a…

代码随想录-回溯(组合问题)|ACM模式

目录 前言&#xff1a; 77.组合 题目描述&#xff1a; 输入输出示例&#xff1a; 思路和想法&#xff1a; 216. 组合总和 III 题目描述&#xff1a; 输入输出示例&#xff1a; 思路和想法&#xff1a; 17. 电话号码的字母组合 题目描述&#xff1a; 输入输出描述&a…

MyBatis的多表操作

1 MyBatis的多表操作 1.1 多表模型介绍 我们之前学习的都是基于单表操作的&#xff0c;而实际开发中&#xff0c;随着业务难度的加深&#xff0c;肯定需要多表操作的。 多表模型分类 一对一&#xff1a;在任意一方建立外键&#xff0c;关联对方的主键。 一对多&#xff1a;在…

实用便捷!一站式BI系统推荐

在企业数字化转型过程中&#xff0c;BI系统可以建立业务、数据的双驱引擎&#xff0c;形成业务、数据的互补作用&#xff0c;通过建立数字化技术架构&#xff0c;明确企业的战略定位和业务目标&#xff0c;从而支撑实现这个目标。而一站式BI系统&#xff0c;则是指可以轻松从数…

【MySQL】SQL性能分析 (七)

&#x1f697;MySQL学习第七站~ &#x1f6a9;本文已收录至专栏&#xff1a;MySQL通关路 ❤️文末附全文思维导图&#xff0c;感谢各位点赞收藏支持~ 假如我们需要对SQL进行优化&#xff0c;我们就必须对他足够的了解&#xff0c;比如 对哪一类SQL进行优化&#xff08;增删改查…

基于物联网网关的工业数据可视化平台有什么功能?

随着数字化浪潮的不断发展&#xff0c;工业数据的价值越来越重要。在企业利用数据的过程中&#xff0c;数据可视化是数字化系统中十分重要的一部分。然而&#xff0c;工厂多种设备、多种协议影响到系统的搭建使得企业无法获得全面的数据视图&#xff0c;也无法对整个生产流程进…

OJ练习第142题——路径总和 II

113. 路径总和 II 力扣链接&#xff1a;113. 路径总和 II 题目描述 给你二叉树的根节点 root 和一个整数目标和 targetSum &#xff0c;找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。 叶子节点 是指没有子节点的节点。 示例 Java代码&#xff08;深度优先搜…

六边形架构

六边形架构 微服务系统架构微服务定义微服务系统设计 传统分层架构六边形架构参考资料 微服务系统架构 需求描述做什么的问题&#xff0c;架构描述怎么做的问题(描述组成系统的各部件及其之间的关系) 微服务定义 下面的定义来自周志明老师的 凤凰架构 微服务是一种通过多个小型…

【Linux】 由“进程”过渡到“线程” -- 什么是线程(thread)?

知识引入初识线程1.什么叫做进程&#xff1f;2.什么叫做线程&#xff1f;3.如何看待我们之前学习的进程&#xff1f; 理解线程创建线程函数调用1.线程一旦被创建&#xff0c;几乎所有资源都是被线程所共享的2.与进程之间切换相比&#xff0c;线程的切换 初识线程总结&#xff1…

使用 Docker 快速上手中文版 LLaMA2 开源大模型

本篇文章&#xff0c;我们聊聊如何使用 Docker 容器快速上手朋友团队出品的中文版 LLaMA2 开源大模型&#xff0c;国内第一个真正开源&#xff0c;可以运行、下载、私有部署&#xff0c;并且支持商业使用。 写在前面 感慨于昨天 Meta LLaMA2 模型开放下载之后&#xff0c;Git…

操作系统练习:进程间通信(共享内存方式)

说明 本文是《操作系统概念(第九版)》3.4节“进程间通信”的练习。 进程间通信主要由两种模型&#xff1a; 共享内存消息传递 本文使用共享内存的方式实现进程间的通信 创建消息生产者 创建生产者的主要操作包括&#xff1a; 定义共享内存的大小、名称&#xff0c;以及通…

netty知识集锦2

粘包半包 粘包半包解决方案&#xff0c; 1短链接&#xff0c;它的消息边界是从链接建立到链接断开 2.定长解码器&#xff1a;服务器端选最大长度的消息作为定长&#xff0c;客户端不足补齐&#xff0c;缺点造成浪费 netty协议设计与解析 Message编码解码

AWS IAM介绍

前言 AWS是世界上最大的云服务提供商&#xff0c;它提供了很多组件供消费者使用&#xff0c;其中进行访问控制的组件叫做IAM(Identity and Access Management)&#xff0c; 用来进行身份验证和对AWS资源的访问控制。 功能 IAM的功能总结来看&#xff0c;主要分两种&#xff1…

《零基础入门学习Python》第060讲:论一只爬虫的自我修养8:正则表达式4

有了前面几节课的准备&#xff0c;我们这一次终于可以真刀真枪的干一场大的了&#xff0c;但是呢&#xff0c;在进行实战之前&#xff0c;我们还要讲讲正则表达式的实用方法和扩展语法&#xff0c;然后再来实战&#xff0c;大家多把持一会啊。 我们先来翻一下文档&#xff1a;…

openGauss学习笔记-17 openGauss 简单数据管理-表达式

文章目录 openGauss学习笔记-17 openGauss 简单数据管理-表达式17.1 简单表达式17.2 条件表达式17.3 子查询表达式17.4 数组表达式17.5 行表达式 openGauss学习笔记-17 openGauss 简单数据管理-表达式 表达式类似一个公式&#xff0c;我们可以将其应用在查询语句中&#xff0c…