【秣厉科技】LabVIEW工具包——OpenCV 教程(19):拾遗 - imgproc 基础操作(上)

文章目录

  • 前言
  • imgproc 基础操作(上)
    • 1. 颜色空间
    • 2. 直方图
    • 3. 二值化
    • 4. 腐蚀、膨胀、开闭运算
    • 5. 梯度与轮廓
    • 6. 简易绘图
    • 7. 重映射
  • 总结


前言

  1. 需要下载安装OpenCV工具包的朋友,请前往 此处 ;
  2. 系统要求:Windows系统,LabVIEW>=2018,兼容32位和64位。

imgproc 基础操作(上)

本文对于之前教程中,未曾集中详细讲解的基础图像处理内容,进行必要的补充

这些功能基本都来源于 imgproc 模块,大概可以分为以下几个方面。

1. 颜色空间

此内容之前已有教程,详见:【秣厉科技】LabVIEW工具包——OpenCV 教程(4):颜色空间


2. 直方图

直方图是一种统计表示方法,用于展示图像中不同像素强度出现的频率分布。

OpenCV中,用 calcHist 函数计算直方图,简单用法如下:

  • 例2-1:灰度图的直方图统计,区间数为5,均匀分割 8U 范围(0~255)

  • 作为常用的一维直方图,其输出结果 Hist 是个列向量,每一个数值代表相应灰度区间内的像素数。
    在这里插入图片描述

  • calcHist 参数含义:

参数含义
ImageArrayMat 数组,存储一张或多张输入图像,尺寸必须一致
Hist一个 Mat 对象,直方图统计结果的输出容器,类型为 32F
channelsint 数组,指定需要做直方图统计的通道序号。当 ImageArray 包含多张图片时,通道序号依次递增,比如第一张包含3个通道,序号为0、1、2;第二张也包含3个通道,序号为3、4、5,以此类推。

channels 只包含一个通道序号时,代表最常用的一维直方图;当包含多个通道序号时,则是多维直方图。
histSizeint 数组,指定每个通道(维度)的直方图数量
rangesfloat 数组,指定每个通道中像素强度(灰度)值的统计范围。
当 uniform 为真,ranges 每通道只需两个数值,即(总下限,总上限),将自动平均分割成 histSize 指定的份数;
当 uniform 为假,ranges 每通道需手动分割,如(h0,h1,h2,h3)代表三个范围 h0-h1,h1-h2,h2-h3 ;

以上的每个范围都遵循 “包含左端,不包含右端” 的原则,即左闭右开。
uniform布尔值,均一化标志,其功能如上面 ranges 所述。
accumulate布尔值,累加标志。
当 accumulate 为假,函数左端传入的 Hist 将被清空后,再写入本次直方图统计结果;
当 accumulate 为真,函数左端传入的 Hist 不会被清空,而是直接累加上本次直方图统计结果。
MaskMat 类型的掩码,可选参数,不连接代表全图参与统计。
  • 例2-2:灰度图的直方图统计,自定义非均匀分割区间

在这里插入图片描述

  • 例2-3:将两张彩色图片的 R通道 直方图累加在一起
  • 通道顺序是BGR,所以两张图片R通道的序号分别是2和5;
  • 第一次 calcHist 的 accumulate 参数是真、假都可以,因为传入的 Hist 初始为空矩阵;
  • 但第二次 calcHist 的 accumulate 参数必须为真,才能实现累加。

在这里插入图片描述

  • 例2-4:二维直方图范例
  • channels 同时给定2个通道序号,histSize 和 ranges 指定两组分割区间,将进行二维直方图统计;
  • 假如两组区间数分别为 M 和 N,那么输出的二维直方图尺寸就是 M x N;
  • 每个元素 Hist (i,j) 代表 同时满足 “第1个通道强度值落在第1组的第 i 区间,第2个通道强度值落在第2组的第 j 区间” 的像素数;
  • 不难看出,将二维直方图 “行向累加” 成一列,就是第1个通道的一维直方图;“列向累加” 成一行,就是第2个通道的一维直方图。

在这里插入图片描述


3. 二值化

二值化的任务,是将一张灰度图,按照设定的阈值,转化成仅有黑白两种颜色的单通道图像。

OpenCV中,用 threshold 函数实现灰度图的二值化,简单用法如下:

  • 例3-1:灰度图二值化,阈值127,最大值255,反向模式(大于阈值时置0,小于等于阈值时置最大值)

在这里插入图片描述

  • threshold 参数含义:
参数含义
srcImage源图像
dstImage目标图像,即二值化的结果
thresh阈值
maxval最大值,即二值中的较大值(最小值固定为0)
type转化类型,共 8 种,含义见下表
retValue(返回值)当 type 设为 OTSU 或 TRIANGLE 时,返回自适应的阈值;否则原样返回 thresh 参数值。
type类型含义
THRESH_BINARY阈值二值化模式,大于阈值时置 maxval ,小于等于阈值时置 0
THRESH_BINARY_INV反向阈值二值化模式,大于阈值时置 0 ,小于等于阈值时置 maxval
THRESH_TRUNC截断模式,大于阈值时置 thresh ,小于等于阈值时维持原值
THRESH_TOZERO取零模式,大于阈值时维持原值,小于等于阈值时置 0
THRESH_TOZERO_INV反向取零模式,大于阈值时置 0 ,小于等于阈值时维持原值
THRESH_MASK返回掩码(本类型已不支持,冗余残留)
THRESH_OTSUOTSU 自适应 阈值, 基于区分前景和背景。通常与其他模式叠加使用
THRESH_TRIANGLETRIANGLE 自适应 阈值, 基于寻找直方图双峰之间的谷底。 通常与其他模式叠加使用
  • 例3-2:灰度图二值化,采用OTSU自动确定阈值,再按 THRESH_BINARY_INV 模式转化

在这里插入图片描述


4. 腐蚀、膨胀、开闭运算

腐蚀、膨胀、开闭运算都属于形态学操作,这些通常在二值化图像上进行。通过特殊的滤波规则,实现二值图中白色区域的收缩、扩张、去噪、联通、边缘润滑等效果。先腐蚀后膨胀,称为开运算;先膨胀后腐蚀,称为闭运算。

相关函数如下表:

函数功能
erode腐蚀,白色区域收缩,孤立的小型白色区域(噪声点)甚至完全消失
dilate膨胀, 白色区域扩张,孤立的小型黑色区域(噪声点)甚至完全消失
morphology可实现多种形态学运算,包括腐蚀、膨胀、开运算 和 闭运算(取决于 op 参数)
getStructuringElement生成结构元素(一个小型二维Mat),作为上述运算的滤波 “核”
  • 例4-1:对同一个二值图,用 9x9 的矩形核,分别进行腐蚀、膨胀、开运算
  • 参考范例:examples/Molitec/OpenCV/imgproc/imgproc_3(binary).vi
  • 简单说明参数:
    anchor 是锚点,即 “核” 在图像上移动时的参考点,默认(-1,-1)代表中心点‌;
    iterations 是迭代次数;
    borderType 边界像素外推的方法,默认为 BORDER_CONSTANT ,即常量填充;
    borderValue 边界填充值,默认为 64F 的最大值 1.797693134862E+308 ;
    op 是 morphology 函数独有的参数,定义操作类型。开运算 MORPH_OPEN ,闭运算 MORPH_CLOSE;

在这里插入图片描述

在这里插入图片描述


5. 梯度与轮廓

图像梯度指的是像素强度(灰度)的变化率,可以用来确定图像的边缘轮廓。

OpenCV中,常用的边缘检测函数包括:Canny、Scharr、Sobel 和 Laplacian。

其中 Canny 是个多态VI,包含 image 输入 和 dxdy 输入 两种模式。

  • 例5-1:对同一个灰度图,分别用 Canny、Scharr、Sobel 和 Laplacian 进行梯度计算和边缘检测
  • 参考范例:examples/Molitec/OpenCV/imgproc/imgproc_4(gradient).vi

在这里插入图片描述
在这里插入图片描述

  • 各函数的 params 参数说明
Canny参数含义
threshold1低阈值,像素梯度低于这个阈值的,一定不是边缘。
threshold2高阈值,像素梯度高于这个阈值的,一定是边缘,且为 “强边缘”。
如果介于两个阈值之间,只有与强边缘相邻时,才被视为边缘的一部分。
apertureSizeSobel 算子尺寸,必须取1、3、5 或 7。 默认为3,代表使用 3x3 的卷积核计算梯度。
L2gradient布尔值,为真代表使用L2范数(欧几里得距离),为假代表使用L1范数(曼哈顿距离)
Scharr参数
ddepth目标图像深度(数据类型,如 CV_8U 等),默认为-1,代表与源图像深度相同。
dxx方向的求导阶数。0表示不计算x方向导数。
dyy方向的求导阶数。0表示不计算y方向导数。
scale计算导数时的缩放因子,默认为1。
delta增量值,加到计算出的导数上,默认值为0。
borderType边界类型,默认为 BORDER_DEFAULT,等同于 BORDER_REFLECT_101
Sobel参数
ddepth同上
dx同上
dy同上
ksizeSobel 算子尺寸,必须取1、3、5 或 7。
scale同上
delta同上
borderType同上
Laplacian参数
ddepth同上
ksizeLaplacian 算子尺寸,必须是奇数。
scale同上
delta同上
borderType同上
  • 例5-2:采用 spatialGradient 分别计算dx、dy,再用 Canny 的dxdy模式进行边缘检测
  • 这相当于把 例5-1 的 Canny 计算过程一分为二。

在这里插入图片描述

在经过 Canny、Scharr、Sobel 和 Laplacian 计算之后,我们往往需要把其中的边缘轮廓提取出来,也就是把输出的二值图中 “连续的白色像素” 的坐标连接在一起,形成轮廓线条。

在OpenCV中,可以使用 findContours 提取梯度二值图中的轮廓线条。

  • 例5-3:使用 Canny + findContours 计算梯度并提取轮廓,最后用 drawContours 绘制轮廓
  • findContours 参数
  • mode 定义轮廓检索模式,默认 RETR_EXTERNAL 代表只检索最外层的轮廓;
  • method 定义轮廓近似方法,默认 CHAIN_APPROX_SIMPLE 代表简单近似法;
  • offset 是坐标偏移量,默认(0,0);
  • 输出 contours‌ 是轮廓结果,其中 pts 数组是全部点坐标序列,npts 代表每个轮廓包含的点数,ncontours 代表轮廓个数。这与之前教程(5)中 drawContours 的输入参数定义相同;
  • 输出 hierarchy 代表轮廓的层次结构,是1个(轮廓个数 x 4)的二维数组。每行4个整数,依次代表本行索引号轮廓的 “上一个、下一个、第一个、最后一个” 轮廓的索引号。-1 表示没有。

在这里插入图片描述

在这里插入图片描述

从上图 hierarchy 输出可以分析:
第0行(1,-1,-1,-1)代表0号轮廓的上一个是1号轮廓,下一个是 -1(没有);
第1行(2,0,-1,-1)代表1号轮廓的上一个是2号轮廓,下一个是0号轮廓;
第2行(3,1,-1,-1)代表2号轮廓的上一个是3号轮廓,下一个是1号轮廓;

最终得出,这6个轮廓的先后顺序为:5,4,3,2,1,0


6. 简易绘图

此内容之前已有教程,详见:【秣厉科技】LabVIEW工具包——OpenCV 教程(5):简易绘图


7. 重映射

图像重映射,指的是按照一定规则,重新排布源图像中的像素坐标位置,并渲染到目标图像中。

之前教程提到的 resize 就是一种重映射,用于实现图片的缩放。

  • 例7-1:使用 resize 将源图像尺寸缩小到原来的一半
  • resize 参数
  • dsize:目标图像尺寸。如果 dsize 不为0,输出图像尺寸以 dsize 为准;否则,将由下面的 fx、fy 计算决定;
  • fx:水平方向缩放因子;
  • fy:垂直方向缩放因子;
  • interpolation:插值方法,指的是当放大图像时,填补空缺的方法。默认 ‌INTER_LINEAR 双线性插值法。

在这里插入图片描述

下面,再介绍两种可以扭曲源图像形状的重映射:仿射变换(warpAffine)和 透视变换(warpPerspective)。

  • 例7-2:分别使用 warpAffine 和 warpPerspective,将图片中一块 “四边形” 区域重映射成 “矩形”
  • 参考范例:examples/Molitec/OpenCV/imgproc/imgproc_7(wrap).vi
  • 首先,锚定源图像四边形的4个顶点,再给定输出矩形的4个顶点,将这两组顶点分别输入到 getAffineTransform 和 getPerspectiveTransform 中,运行得到各自的变换矩阵 M;
  • 接着,使用 warpAffine 配合 getAffineTransform 输出的 M,完成仿射变换;
  • 使用 warpPerspective 配合 getPerspectiveTransform 输出的 M,完成透视变换;

在这里插入图片描述

在这里插入图片描述

如果你想完全自定义一种映射关系,即手动给定每一个像素在新图像中的坐标位置,那么可以使用 remap 函数。

  • 例7-3:使用 remap 实现图片的水平翻转
  • remap 函数 VI 的上方需要输入两个 Mat 参数,名称分别为 map1 和 map2,用于逐像素指定映射后的新坐标;
  • 上述 map1 和 map2 有两种组织方式:
    其一,map1 和 map2 都是单通道矩阵,那么 map1 指定所有像素映射之后的X坐标,map2 指定Y坐标;
    其二,map1 是双通道矩阵,那么由 map1 独自指定(X,Y)坐标,而 map2 为空矩阵 即可。
  • 参考范例:examples/Molitec/OpenCV/imgproc/imgproc_6(remap).vi

在这里插入图片描述

顺便一提,如果只是需要进行图片翻转、旋转这样常规的操作,那完全没必要用到 remap。使用 core 模块下的 flip 和 rotate 等函数,就完全可以做到,而且更为简洁。

core 模块下也有不少重映射的方法,感兴趣的读者可以试一试。

在这里插入图片描述


总结

  1. 本系列博文作为LabVIEW工具包—OpenCV的教程,将以专栏的形式陆续发布和更新。
  2. 对工具包感兴趣的朋友,欢迎下载试用:秣厉科技 - LabVIEW工具包 - OpenCV
  3. 各位看官有什么想法、建议、吐槽、批评,或新奇的需求,也欢迎留言讨论。

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

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

相关文章

Linux 下 Module 工具的介绍与使用

参考: https://www.fasteda.cn/post/22.html https://modules.readthedocs.io/en/latest/module.html Linux 下 Module 工具的介绍与使用 一、前言 在 Linux 中,当同一款编辑器、运行库、软件存在多个版本且多个版本都需要在不同的场景或人员使用时&a…

空间信息可视化——WebGIS前端实例(一)

技术栈:原生HTML 源代码:CUGLin/WebGIS: This is a project of Spatial information visualization 4 全国贫困县可视化系统 4.1 系统设计思想 党的十九大报告明确指出,要“确保到2020年我国现行标准下农村贫困人口实现脱贫,贫困县全部摘帽,解决区域…

单双线程的理解 和 lua基础语法

1.什么是单进程 ,什么是多进程 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源。而一个进程又是由单个或多个线程所组成的。 1.1 像apache nginx 这类 服务器中间件就是多进程的软件 &#xff0…

【Linux】VIM 编辑器,编辑加速引擎

目录 vim中的五种常见模式介绍VIM的基本操作安装VIMVIM中的模式切换 VIM指令集命令模式指令集底行模式指令集视图模式指令集替换和插入模式 end vim中的五种常见模式介绍 正常/普通/命令模式【Normal mode】 控制屏幕光标的移动,字符、字或行的删除,移动…

【Linux网络】Socket 编程TCP

🌈个人主页:秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343 🔥 系列专栏:https://blog.csdn.net/qinjh_/category_12891150.html 目录 TCP socket API 详解 socket(): bind(): listen(): accept(): connect V0…

记一次 .NET某固高运动卡测试 卡慢分析

一:背景 1. 讲故事 年前有位朋友找到我,说他们的程序会偶发性卡慢 10s 钟,在某些组合下会正常,某些组合下就会出现问题,解释不了其中的原因,让我帮忙看下怎么回事?截图如下: priva…

硬件知识积累 单片机+ 光耦 + 继电器需要注意的地方

1. 电路图 与其数值描述 1.1 单片机引脚信号为 OPtoCoupler_control_4 PC817SB 为 光耦 继电器 SRD-05VDC-SL-A 的线圈电压为 67Ω。 2. 需注意的地方 1. 单片机的推挽输出的电流最大为 25mA 2. 注意光耦的 CTR 参数 3. 注意继电器线圈的 内阻 4. 继电器的开启电压。 因为光耦…

IP组播技术与internet

1.MAC地址分为三类:广播地址;组播地址;单播地址 2.由一个源向一组主机发送信息的传输方式称为组播。 3.组播MAC地址,第一个字节的最后一位为1; 单播MAC地址,第一个字节的最后一位为0; 4.不能…

vue3+vite+ts使用daisyui/tailwindcss

vite创建vue3脚手架 npm init vitelatest myVue3 – --template vue cd .\myVue3\ npm i npm run dev 安装tailwindcss/daisyui 依赖安装 npm install -D tailwindcss postcss autoprefixer daisyui npx tailwindcss init -p 这条命令将生成postcss.config.js(因为加了…

大数据(7)Kafka核心原理揭秘:从入门到企业级实战应用

目录 一、大数据时代的技术革命1.1 消息中间件演进史1.2 Kafka核心设计哲学 二、架构深度解构2.1 核心组件拓扑2.1.1 副本同步机制(ISR) 2.2 生产者黑科技2.3 消费者演进路线 三、企业级应用实战3.1 金融行业实时风控3.2 物联网数据管道 四、生产环境优化…

spring boot大文件与多文件下载

一、简单大文件下载&#xff1a; /*** 下载大文件* param path 路径* param fileName 文件名* return* throws IOException*/ public static ResponseEntity<InputStreamResource> downloadFile(String path, String fileName) throws IOException {Path filePath Path…

第二节:React 基础篇-受控组件 vs 非受控组件

一、场景题&#xff1a;设计一个实时搜索输入框&#xff0c;说明选择依据 受控组件 vs 非受控组件 核心区别 特征受控组件非受控组件数据管理由React状态&#xff08;state&#xff09;控制通过DOM元素&#xff08;ref&#xff09;直接访问更新时机每次输入触发onChange提交…

局部路由守卫

局部路由守卫为我们提供了更细粒度的路由控制&#xff0c;允许我们在特定的路由或组件级别添加鉴权和逻辑处理。局部路由守卫分为 path 守卫和 component 守卫&#xff0c;它们分别适用于不同的场景。 path 守卫&#xff08;路由守卫&#xff09; path 守卫用于在进入特定路由…

Android 16应用适配指南

Android 16版本特性介绍 https://developer.android.com/about/versions/16?hlzh-cn Android 16 所有功能和 API 概览 https://developer.android.com/about/versions/16/features?hlzh-cn#language-switching Android 16 发布时间 Android 16 适配指南 Google开发平台&…

android display 笔记(十二)CPU,GPU,DPU的区别

CPU&#xff08;Central Processing Unit&#xff09;通用计算&#xff1a;处理复杂逻辑、分支预测、多任务调度。 低延迟&#xff1a;优先快速响应单线程任务。 GPU&#xff08;Graphics Processing Unit&#xff09; 高吞吐量并行计算&#xff1a;适合大规模数据并行处理。…

音频转文本:如何识别音频成文字

Python脚本:MP4转MP3并语音识别为中文 以下是一个完整的Python脚本,可以将MP4视频转换为MP3音频,然后使用语音识别模型将音频转换为中文文本。 准备工作 首先需要安装必要的库: pip install moviepy pydub SpeechRecognition openai-whisper完整脚本 import os from m…

理解 MCP 协议的数据传递:HTTP 之上的一层“壳子

以下是以 CSDN 博客的风格记录你对 MCP 协议数据传递的理解和发现&#xff0c;内容涵盖了 MCP 协议基于 HTTP 的本质、JSON-RPC 的“壳子”作用&#xff0c;以及为什么熟悉 HTTP 协议就足以理解 MCP 的数据传递。文章面向技术社区&#xff0c;结构清晰&#xff0c;适合分享。 理…

基于ssm网络游戏推荐系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 当今社会进入了科技进步、经济社会快速发展的新时代。国际信息和学术交流也不断加强&#xff0c;计算机技术对经济社会发展和人民生活改善的影响也日益突出&#xff0c;人类的生存和思考方式也产生了变化。传统网络游戏管理采取了人工的管理方法&#xff0c;但这种管理方…

vue入门:指令

文章目录 vue的内置指令说明&#xff1a; 自定义指令 vue的内置指令 Vue 指令的本质是&#xff1a; 声明式的 DOM 操作接口&#xff08;隐藏底层 JavaScript 代码&#xff09;。响应式数据的绑定媒介&#xff08;连接数据和视图&#xff09;。模板编译的标记&#xff08;最终…

oracle 索引失效

在 Oracle 11g 中&#xff0c;索引失效的常见原因包括函数修改列、隐式类型转换、统计信息过时等&#xff0c;解决方法需结合版本特性&#xff08;如虚拟列、索引跳跃扫描&#xff09;。通过执行计划分析、统计信息维护和合理使用提示&#xff08;Hints&#xff09;&#xff0c…