OpenCV4.9图像金字塔

news2024/9/24 7:13:56

目标

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

  • 使用 OpenCV 函数 pyrUp()和 pyrDown()对给定图像进行下采样或上采样。

理论

注意

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

  • 通常,我们需要将图像转换为与原始图像不同的大小。为此,有两种可能的选择:
    1. 放大图像(放大)或
    2. 缩小它(缩小)。
  • 尽管 OpenCV 中有一个几何变换函数,可以从字面上调整图像大小(调整大小,我们将在以后的教程中展示),但在本节中,我们首先分析了图像金字塔的使用,它广泛应用于广泛的视觉应用。

图像金字塔

  • 图像金字塔是图像的集合 - 所有图像都来自单个原始图像 - 这些图像被连续下采样,直到达到某个所需的停止点。
  • 图像金字塔有两种常见的类型:
    • 高斯金字塔:用于对图像进行缩减采样
    • 拉普拉斯金字塔:用于从金字塔下部的图像(分辨率较低)重建上采样图像
  • 在本教程中,我们将使用高斯金字塔

高斯金字塔

  • 将金字塔想象成一组层,其中层越高,尺寸越小。

  • 每一层都从下到上编号,因此层(i+1)(表示为 G_(i+1)小于层I(Gi)。
  • 为了在高斯金字塔中生成层(I+1)我们执行以下操作:

    • 用高斯核卷积Gi:
    • 删除每个偶数行和列。
    • 您可以很容易地注意到,生成的图像将恰好是其前身的四分之一。在输入图像 \(G_{0}\)(原始图像)上迭代此过程将生成整个金字塔。
    • 上述过程对于图像的缩减采样非常有用。如果我们想让它变大怎么办?:用零填充的列 ( \(0 \))
      • 首先,将图像在每个维度上放大到原始图像的两倍,使用新的偶数行和
      • 使用上面显示的相同内核(乘以 4)执行卷积,以近似“缺失像素”的值
    • 这两个过程(如上所述的下采样和上采样)由 OpenCV 函数 pyrUp() 和 pyrDown() 实现,我们将在下面代码的示例中看到:

注意

当我们减小图像的大小时,我们实际上丢失了图像的信息。

演示代码:

C++

本教程代码如下所示。

您也可以从这里下载

#include "iostream"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
 
using namespace std;
using namespace cv;
 
const char* window_name = "Pyramids Demo";
 
int main( int argc, char** argv )
{
 cout << "\n Zoom In-Out demo \n "
 "------------------ \n"
 " * [i] -> Zoom in \n"
 " * [o] -> Zoom out \n"
 " * [ESC] -> Close program \n" << endl;
 
 const char* filename = argc >=2 ? argv[1] : "chicky_512.png";
 
 // Loads an image
 Mat src = imread( samples::findFile( filename ) );
 
 // Check if image is loaded fine
 if(src.empty()){
 printf(" Error opening image\n");
 printf(" Program Arguments: [image_name -- default chicky_512.png] \n");
 return EXIT_FAILURE;
 }
 
 for(;;)
 {
 imshow( window_name, src );
 char c = (char)waitKey(0);
 
 if( c == 27 )
 { break; }
 else if( c == 'i' )
 { pyrUp( src, src, Size( src.cols*2, src.rows*2 ) );
 printf( "** Zoom In: Image x 2 \n" );
 }
 else if( c == 'o' )
 { pyrDown( src, src, Size( src.cols/2, src.rows/2 ) );
 printf( "** Zoom Out: Image / 2 \n" );
 }
 }
 
 return EXIT_SUCCESS;
}

解释

C++

让我们检查一下程序的一般结构:

加载图像

 const char* filename = argc >=2 ? argv[1] : "chicky_512.png";
 
 // Loads an image
 Mat src = imread( samples::findFile( filename ) );
 
 // Check if image is loaded fine
 if(src.empty()){
 printf(" Error opening image\n");
 printf(" Program Arguments: [image_name -- default chicky_512.png] \n");
 return EXIT_FAILURE;
 }

创建窗口

 imshow( window_name, src );

消息循环:

 for(;;)
 {
 imshow( window_name, src );
 char c = (char)waitKey(0);
 
 if( c == 27 )
 { break; }
 else if( c == 'i' )
 { pyrUp( src, src, Size( src.cols*2, src.rows*2 ) );
 printf( "** Zoom In: Image x 2 \n" );
 }
 else if( c == 'o' )
 { pyrDown( src, src, Size( src.cols/2, src.rows/2 ) );
 printf( "** Zoom Out: Image / 2 \n" );
 }
 }

执行无限循环,等待用户输入。如果用户按 ESC,我们的程序将退出。此外,它有两个选项:

  • 执行上采样 - 缩放 'i'n(按下“i”后)

    我们使用带有三个参数的函数 pyrUp():

    • src:当前和目标图像(显示在屏幕上,应该是输入图像的双倍)
    • Size( tmp.cols*2, tmp.rows*2 ) :目标大小。由于我们是上采样,pyrUp() 的大小是输入图像的两倍(在本例中为 src)。
 else if( c == 'i' )
 { pyrUp( src, src, Size( src.cols*2, src.rows*2 ) );
 printf( "** Zoom In: Image x 2 \n" );
 }
  • 执行缩减采样 - 缩放 'o'ut(按下 'o' 后)

    我们使用带有三个参数的函数 pyrDown() (类似于 pyrUp()):

    • src:当前和目标图像(显示在屏幕上,应该是输入图像的一半)
    • Size(tmp.cols/2, tmp.rows/2 ) :目标大小。由于我们正在缩减采样,pyrDown() 需要输入图像的一半大小(在本例中为 src)。
 else if( c == 'o' )
 { pyrDown( src, src, Size( src.cols/2, src.rows/2 ) );
 printf( "** Zoom Out: Image / 2 \n" );
 }

请注意,输入图像可以除以 2 倍(在两个维度上)非常重要。否则,将显示错误。

结果

  • 默认情况下,samples/data程序调用文件夹中的图像chicky_512.png。请注意,此图像是 \(512 \times 512\),因此下采样不会生成任何错误 ( \(512 = 2^{9}\))。原图如下图所示:

  • 首先,我们通过按“d”来应用两个连续的 pyrDown()操作。我们的输出是:

  • 注意,由于我们正在减小图像的大小,我们应该会失去一些分辨率。在我们应用 pyrUp() 两次(按“u”)后,这一点很明显。我们现在的输出是:

参考文献:

1、《Image Pyramids》-----Ana Huamán

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

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

相关文章

函数的参数命名和默认参数

在Kotlin中&#xff0c;函数可以有多个参数&#xff0c;记住参数的顺序或者仅靠位置理解他们的作用可能会很具有挑战性&#xff0c;特别是对于接受多个参数或者有相同类型参数的函数。命名参数通过允许开发者指定传递给函数的每个参数的名称来解决这个问题。 有一个用来展示用户…

了解 Vue 工程化开发中的组件通信

目录 1. 组件通信语法 1.1. 什么是组件通信&#xff1f; 1.2. 为什么要使用组件通信&#xff1f; 1.3. 组件之间有哪些关系&#xff08;组件关系分类&#xff09;&#xff1f; 1.4. 组件通信方案有哪几类 &#xff1f; 2. 父子通信流程图 3. 父传子 3.1. 父传子核心流程…

【C++成长记】C++入门 | 类和对象(中) |类的6个默认成员函数、构造函数、析构函数

&#x1f40c;博主主页&#xff1a;&#x1f40c;​倔强的大蜗牛&#x1f40c;​ &#x1f4da;专栏分类&#xff1a;C❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、类的6个默认成员函数 二、构造函数 1、概念 2、特性 三、析构函数 1、概念 2、特性 一、…

LabVIEW专栏六、LabVIEW项目

一、梗概 项目&#xff1a;后缀是.lvproj&#xff0c;在实际开发的过程中&#xff0c;一般是要用LabVIEW中的项目来管理代码&#xff0c;也就是说相关的VI或者外部文件&#xff0c;都要放在项目中来管理。 在LabVIEW项目中&#xff0c;是一个互相依赖的整体&#xff0c;可以包…

51-40 Align your Latents,基于LDM的高分辨率视频生成

由于数据工程、仿真测试工程&#xff0c;咱们不得不进入AIGC图片视频生成领域。兜兜转转&#xff0c;这一篇与智驾场景特别密切。23年4月&#xff0c;英伟达Nvidia联合几所大学发布了带文本条件融合、时空注意力的Video Latent Diffusion Models。提出一种基于LDM的高分辨率视…

【简单讲解如何安装与配置Composer】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

深入探索:Zookeeper+消息队列(kafka)集群

目录 前言 一、Zookeeper概述 1、Zookeeper概念 2、Zookeeper 特点 3、Zookeeper工作机制 4、Zookeeper 选举机制 4.1 第一次启动选举机制 4.2 非第一次启动选举机制 5、Zookeeper 数据结构 6、Zookeeper 应用场景 二、部署 Zookeeper 集群 1、环境部署 2、安装 z…

构建鸿蒙ACE静态库

搭建开发环境 根据说明文档下载鸿蒙全部代码&#xff0c;一般采取第四种方式获取最新代码(请保证代码为最新) 源码获取Windows下载编译环境 MinGW GCC 7.3.0版本 请添加环境变量IDE 可以使用两种 CLion和Qt,CLion不带有环境需要安装MinGW才可以开发,Qt自带MinGW环境&#xff0…

【Canvas与艺术】绘制磨砂黄铜材质Premium Quality徽章

【关键点】 渐变色的使用、斜纹的实现、底图的寻觅 【成果图】 ​​​​​​​ 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><tit…

跑腿平台隐藏服务用法,搭建平台这些跑腿服务也能做!

跑腿场景竞争愈发激烈激烈 事实上&#xff0c;跑腿行业早已群狼环伺&#xff0c;尽管跑腿领域仍有很大的发展空间&#xff0c;但新晋玩家都普遍把目光投向了外卖配送这个细分领域&#xff0c;难免会增加后来者的市场拓展和发展难度。那么&#xff0c;在跑腿服务行业中还有哪些…

springboot上传模块到私服,再用pom引用下来

有时候要做一个公司的公共服务模块。不能说大家都直接把代码粘贴进去&#xff0c;因为会需要维护很多份&#xff1b;这样就剩下两个方式了。 方式一&#xff1a;自己独立部署一个公共服务的服务&#xff0c;全公司都调用&#xff0c;通过http、rpc或者grpc的方式&#xff0c;这…

Http响应报文介绍

所有HTTP消息(请求与响应)中都包含&#xff1a; 一个或几个单行显示的消息头(header)&#xff0c; 在消息头部分主要包含&#xff1a;响应行信息和响应头信息 一个强制空白行&#xff1b; 最后是响应消息主体&#xff1b; 以下是一个典型的HTTP响应: HTTP/1.1 200 OK -- 响…

【MATLAB源码-第15期】基于matlab的MSK的理论误码率与实际误码率BER对比仿真,采用差分编码IQ调制解调。

1、算法描述 在数字调制中&#xff0c;最小频移键控&#xff08;Minimum-Shift Keying&#xff0c;缩写&#xff1a;MSK&#xff09;是一种连续相位调制的频移键控方式&#xff0c;在1950年代末和1960年代产生。[1] 与偏移四相相移键控&#xff08;OQPSK&#xff09;类似&…

nodejs解析url参数

需要引入 url 模块&#xff1b; var http require(http); var url require(url);http.createServer(function (req, res) {res.writeHead(200, {Content-Type: text/plain});// 解析 url 参数var params url.parse(req.url, true).query;res.write("name: " par…

解决Git 不相关的分支合并

可以直接调到解决方案,接下来是原因分析和每步的解决方式 问题原因: 我之前在自己本机创建了一个初始化了Git仓库,后来有在另一个电脑初始化仓库,并没有clone自己在本机Git远程仓库地址,导致Git历史版本不相关 错误信息 From https://gitee.com/to-uphold-justice-for-other…

MES管理系统中生产物料管理的设计

在数字化工厂建设的浪潮中&#xff0c;MES管理系统作为执行层的核心管理系统&#xff0c;其重要性日益凸显。特别是在生产物料管理方面&#xff0c;MES管理系统不仅承担物料计划指令的接收&#xff0c;还负责物料派工及使用反馈的数据收集&#xff0c;其业务流程的设计对数字化…

【Leetcode】2923. 找到冠军 I

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接&#x1f517; 一场比赛中共有 n n n 支队伍&#xff0c;按从 0 0 0 到 n − 1 n - 1 n−1 编号。 给你一个下标从 0 0 0 开始、大小为 n ∗ n n * n n∗n 的二维布尔矩阵 g r i d grid gr…

改进的注意力机制的yolov8和UCMCTrackerDeepSort的多目标跟踪系统

基于yolov8和UCMCTracker/DeepSort的注意力机制多目标跟踪系统 本项目是一个强大的多目标跟踪系统&#xff0c;基于[yolov8]链接和[UCMCTracker/DeepSot]/链接构建。 &#x1f3af; 功能 多目标跟踪&#xff1a;可以实现对视频中的多目标进行跟踪。目标检测&#xff1a;可以实…

Linux系统搭建FastDFS文件服务结合内网穿透实现公网访问本地文件

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…