利用Opencv4.9为图像添加边框

 返回:OpenCV系列文章目录(持续更新中......)
上一篇利用OpenCV4.9制作自己的线性滤波器!
下一篇 :OpenCV系列文章目录(持续更新中......)

目标

在本教程中,您将学习如何:

  • 使用 OpenCV 函数 copyMakeBorder() 设置边框(图像的额外填充)。

理论

注意

下面的解释属于 Bradski 和 Kaehler 的 Learning OpenCV 一书。

  1. 在之前的教程中,我们学习了使用卷积对图像进行操作。自然而然地出现的一个问题是如何处理边界。如果被评估的点位于图像的边缘,我们如何对它们进行卷积?
  2. 大多数 OpenCV 函数所做的是将给定的图像复制到另一个稍大的图像上,然后自动填充边界(通过下面示例代码中解释的任何方法)。这样,卷积可以在所需的像素上毫无问题地执行(操作完成后会剪切额外的填充)。
  3. 在本教程中,我们将简要探讨为图像定义额外填充(边框)的两种方法:

    1. BORDER_CONSTANT:用常量值填充图像(即黑色或0)
    2. BORDER_REPLICATE:原稿边缘的行或列将复制到额外的边框。

    这将在“代码”部分中更清楚地看到。

  • 这个程序是做什么的?
    • 加载图像
    • 让用户选择在输入图像中使用哪种填充。有两种选择:

      1. 常量值边框:为整个边框应用常量值的填充。此值将每 0.5 秒随机更新一次。
      2. 复制的边框:边框将从原始图像边缘的像素值复制。

      用户通过按“c”(常量)或“r”(复制)来选择任一选项

    • 当用户按下“ESC”时,程序完成

C++代码:

教程代码如下所示。

您也可以从这里下载

#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"using namespace cv;// Declare the variables
Mat src, dst;
int top, bottom, left, right;
int borderType = BORDER_CONSTANT;
const char* window_name = "copyMakeBorder Demo";
RNG rng(12345);int main( int argc, char** argv )
{const char* imageName = argc >=2 ? argv[1] : "lena.jpg";// Loads an imagesrc = imread( samples::findFile( imageName ), IMREAD_COLOR ); // Load an image// Check if image is loaded fineif( src.empty()) {printf(" Error opening image\n");printf(" Program Arguments: [image_name -- default lena.jpg] \n");return -1;}// Brief how-to for this programprintf( "\n \t copyMakeBorder Demo: \n" );printf( "\t -------------------- \n" );printf( " ** Press 'c' to set the border to a random constant value \n");printf( " ** Press 'r' to set the border to be replicated \n");printf( " ** Press 'ESC' to exit the program \n");namedWindow( window_name, WINDOW_AUTOSIZE );// Initialize arguments for the filtertop = (int) (0.05*src.rows); bottom = top;left = (int) (0.05*src.cols); right = left;for(;;){Scalar value( rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255) );copyMakeBorder( src, dst, top, bottom, left, right, borderType, value );imshow( window_name, dst );char c = (char)waitKey(500);if( c == 27 ){ break; }else if( c == 'c' ){ borderType = BORDER_CONSTANT; }else if( c == 'r' ){ borderType = BORDER_REPLICATE; }}return 0;
}

解释:

声明变量

首先,我们声明将要使用的变量:

// Declare the variables
Mat src, dst;
int top, bottom, left, right;
int borderType = BORDER_CONSTANT;
const char* window_name = "copyMakeBorder Demo";
RNG rng(12345);

特别值得一提的是变量 rng,它是一个随机数生成器。我们用它来生成随机边框颜色,我们很快就会看到。

加载图像

像往常一样,我们加载源图像 src

 const char* imageName = argc >=2 ? argv[1] : "lena.jpg";// Loads an imagesrc = imread( samples::findFile( imageName ), IMREAD_COLOR ); // Load an image// Check if image is loaded fineif( src.empty()) {printf(" Error opening image\n");printf(" Program Arguments: [image_name -- default lena.jpg] \n");return -1;}

创建窗口

在简要介绍了如何使用该程序之后,我们创建了一个窗口:

 // Initialize arguments for the filtertop = (int) (0.05*src.rows); bottom = top;left = (int) (0.05*src.cols); right = left;

循环

程序在无限循环中运行,而未按下 ESC 键。如果用户按“c”或“r”,则 borderType 变量将分别取值 BORDER_CONSTANT 或 BORDER_REPLICATE

 char c = (char)waitKey(500);if( c == 27 ){ break; }else if( c == 'c' ){ borderType = BORDER_CONSTANT; }else if( c == 'r' ){ borderType = BORDER_REPLICATE; }

随机颜色

在每次迭代中(0.5 秒后),随机边框颜色()都会更新......

 Scalar value( rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255) );

此值是在 [0,255] 范围内随机选择的三个数字的集合。

在图像周围形成边框

最后,我们调用函数 copyMakeBorder()来应用相应的填充:

copyMakeBorder( src, dst, top, bottom, left, right, borderType, value );
  • 参数是:
    1. src:源图片
    2. dst:目标图像
    3. :图像两侧边框的长度(以像素为单位)。我们将它们定义为图像原始大小的 5%。
    4. borderType:定义应用的边框类型。在此示例中,它可以是常量或复制的。
    5. value:如果 borderType 为 BORDER_CONSTANT,则这是用于填充边框像素的值。

显示结果

我们在之前创建的图像中显示输出图像

 imshow( window_name, dst );

结果

  1. 编译上面的代码后,您可以执行它,并给出图像的路径作为参数。结果应为:

    • 默认情况下,它以设置为 BORDER_CONSTANT 的边框开头。因此,将显示一系列随机彩色边框。
    • 如果按“r”,边框将成为边缘像素的复制品。
    • 如果按“c”,随机彩色边框将再次出现
    • 如果按“ESC”,程序将退出。

    下面的一些屏幕截图显示了边框如何改变颜色以及BORDER_REPLICATE选项的外观:

参考文献 :

1、《Adding borders to your images》----Ana Huamán

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

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

相关文章

[Spring Cloud] (4)搭建Vue2与网关、微服务通信并配置跨域

文章目录 前言gatway网关跨域配置取消微服务跨域配置 创建vue2项目准备一个原始vue2项目安装vue-router创建路由vue.config.js配置修改App.vue修改 添加接口访问安装axios创建request.js创建index.js创建InfoApi.js main.jssecurityUtils.js 前端登录界面登录消息提示框 最终效…

故障诊断 | 用于跨机器工况下故障诊断的深度判别迁移学习网络附Pytorch代码

目录 基础代码小结基础 目前,研究者已经提出了很多用于解决目标域和源域之间的分布对齐和知识迁移问题的领域自适应方法。然而,大多数研究方法只关注到边缘分布对齐,忽略了目标域和源域之间判别性特征的学习。因此,在某些案例中,这些方法仍然不能很好地满足故障诊断要求。…

【iOS安全】iOS ARM汇编

mov指令 MOV X22, X0 将X0的值移到X22中 参数传递 参数1:寄存器X0传递 参数2:寄存器X1传递 参数3:寄存器X2传递 参数4:寄存器X3传递 (这里的X0传递的就是第一个实际参数,而不是self、selector之类的&…

InFusion:通过从扩散先验学习深度完成来修复3D高斯

InFusion: Inpainting 3D Gaussians via Learning Depth Completion from Diffusion Prior InFusion:通过从扩散先验学习深度完成来修复3D高斯 Zhiheng Liu * 刘志恒 *1144Hao Ouyang * 欧阳浩 *2233Qiuyu Wang 王秋雨33Ka Leong Cheng 郑家亮2233Jie Xiao 街小…

Elasticsearch常用查询语法及RestClient操作

DSL Query基本语法 1,查询所有数据matchall(当然并不是会显示所有数据) #查询所有数据 GET /索引名/_search {"query": {"查询类型": {"查询条件":"条件值"}} }2,全文搜索检索-分词搜索…

从零实现诗词GPT大模型:实现Transformer架构

专栏规划: https://qibin.blog.csdn.net/article/details/137728228 首先说明一下,跟其他文章不太一样,在本篇文章中不会对Transformer架构中的自注意力机制进行讲解,而是后面单独1~2篇文章详细讲解自注意力机制,我认为由浅入深的先了解Transformer整体架构和其中比较简单…

IDEA JAVA项目如何设置JVM参数

问题背景: 有时候项目在本地启动时会报参数引用不到,如果确实找不到在哪里添加的话,我们可以先加JVM参数来暂时解决本地环境的调试。 解决方案: 编辑配置Edit Configurations 选择需要配置的项目,点击Modify options 选…

React基础知识大汇总

函数组件和类组件 函数组件与类组件有什么区别呢? function getName(params:{name:string}){const count 0;return params.name -count; } getName({name:"test"}) getName({name:"哈哈哈"})getName是一个纯函数,不产生任何副作用…

mfc140.dll丢失如何修复,分享多种有效的修复方法

在日常操作和使用电脑的过程中,我们可能会遇到一种较为常见的问题,即在尝试启动或运行某个应用程序时,系统突然弹出一个错误提示窗口,明确指出“mfc140.dll文件丢失”。这个mfc140.dll实际上是一个动态链接库文件(DLL&…

mysql基础19——日志

日志 mysql的日志种类非常多 通用查询日志 慢查询日志 错误日志 与时间有关联 二进制日志 中继日志 与主从服务器的同步有关 重做日志 回滚日志 与数据丢失有关 通用查询日志 记录了所有用户的连接开始时间和截至时间 以及给mysql服务器发送的所有指令 当数据异常时&…

计算机体系结构

体系结构 CPU:运算器和控制器 运算器:进行算术和逻辑运算控制器: 输入设备:鼠标、键盘、显示器、磁盘、网卡等输出设备:显卡,磁盘、网卡、打印机等存储器:内存,掉电易失总线&#xf…

借助 NVivo 彻底改变业务创新

在收集定性数据时,通常很难确定信息的情感底蕴。尤其是在金融行业,当涉及到经济金融状况和股票走势等问题时,通过文章、社交媒体和其他消费者平台了解市场的真实整体感受至关重要。这就是对数据应用情绪分析可以提供帮助的地方。 在德勤 针对…

代码随想录第42天|416. 分割等和子集

416. 分割等和子集 416. 分割等和子集 - 力扣(LeetCode) 代码随想录 (programmercarl.com) 动态规划之背包问题,这个包能装满吗?| LeetCode:416.分割等和子集_哔哩哔哩_bilibili 给你一个 只包含正整数 的 非空 数组…

软件测试之【软件测试概论一】

读者大大们好呀!!!☀️☀️☀️ 🔥 欢迎来到我的博客 👀期待大大的关注哦❗️❗️❗️ 🚀欢迎收看我的主页文章➡️寻至善的主页 文章目录 前言软件生命周期软件项目开发过程软件项目组织架构软件开发相关模型 软件测试…

深入理解与实践“git add”命令的作用

文章目录 **git add命令的作用****git add命令的基本作用****高级用法与注意事项** git add命令的作用 引言: 在Git分布式版本控制系统中,git add命令扮演着至关重要的角色,它是将本地工作区的文件变动整合进版本控制流程的关键步骤。本文旨…

JVM 引用的分类

引用计数算法和根搜索算法都需要通过判断引用的方式判断对象是否可回收。 JDK1.2 之前,Java 中引用的定义很传统:如果 reference 类型的数据存储的数值代表的是另一块内存的起始地址,就称这块内存代表一个引用。 在 JDK 1.2 之后,…

每周一算法:负环判断

题目链接 负环 题目描述 给定一个 n n n 个点的有向图,请求出图中是否存在从顶点 1 1 1 出发能到达的负环。 负环的定义是:一条边权之和为负数的回路。 输入格式 本题单测试点有多组测试数据。 输入的第一行是一个整数 T T T,表示测…

《乱弹篇(30)厌战的杜诗》

时下地球村有一伙成天叫嚣着“打打杀杀”、鼓吹快快发动战争的狂人,他们视老百姓的生命如草芥,毫不珍惜。没有遭受过战火焚烧的人,也跟着成天吠叫“快开战吧”。然而中国唐朝大诗人却是个“厌战派”,他对战争的厌恶集中表现在诗《…

[系统安全] 五十七.恶意软件分析 (9)利用MS Defender实现恶意样本家族批量标注(含学术探讨)

您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列。因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全、逆向分析和恶意代码检测,“系统安全”系列文章会更加聚焦,更加系…

WebRTC的3A和SpeexDSP如何选择

SpeexDSP 是一个专门用于语音处理的开源库,它是从 Speex 项目中分离出来的。SpeexDSP 提供了多种音频处理功能,包括回声消除(AEC)、噪声抑制(ANS)、自动增益控制(AGC)以及声音的预处…