当前位置: 首页 > news >正文

【opencv】示例-distrans.cpp 距离变换

f02abca910ffc3f94b0faa6a95826163.jpeg

stuff.jpg

006de25e1ba1b3b6f6ca809008149052.png

6513471157952e94cd5538403c8b60b8.gif

69547acc388be9200f8c0300ad6c81b5.png

#include <opencv2/core/utility.hpp>  // 包含OpenCV中的核心功能支持库
#include "opencv2/imgproc.hpp"       // 包含OpenCV中的图像处理库
#include "opencv2/imgcodecs.hpp"     // 包含OpenCV中的图像编解码库
#include "opencv2/highgui.hpp"       // 包含OpenCV中的高级用户界面库#include <stdio.h>   // 包含标准输入输出库using namespace std; // 使用标准命名空间
using namespace cv;  // 使用OpenCV命名空间int maskSize0 = DIST_MASK_5;   // 定义默认的掩膜大小为5x5
int voronoiType = -1;          // 定义维诺图模式的初始类型,-1表示未激活维诺图模式
int edgeThresh = 100;          // 边缘检测的阈值
int distType0 = DIST_L1;       // 定义默认的距离变换类型为L1// 输出图像和临时图像
Mat gray;// 亮度阈值的回调函数
static void onTrackbar( int, void* )
{static const Scalar colors[] =  // 预定义的颜色数组{Scalar(0,0,0),Scalar(255,0,0),Scalar(255,128,0),Scalar(255,255,0),Scalar(0,255,0),Scalar(0,128,255),Scalar(0,255,255),Scalar(0,0,255),Scalar(255,0,255)};int maskSize = voronoiType >= 0 ? DIST_MASK_5 : maskSize0; // 根据是否启用维诺图模式来选择掩膜大小int distType = voronoiType >= 0 ? DIST_L2 : distType0;     // 根据是否启用维诺图模式来选择距离变换类型Mat edge = gray >= edgeThresh, dist, labels, dist8u;       // 生成边缘图,距离图,标签图和8位显示图// 执行距离变换计算if( voronoiType < 0 )distanceTransform( edge, dist, distType, maskSize );   // 距离变换操作elsedistanceTransform( edge, dist, labels, distType, maskSize, voronoiType ); // 包含标签的距离变换// 如果没有激活维诺图模式,进行以下处理if( voronoiType < 0 ){// "绘画"距离变换结果的过程开始dist *= 5000;pow(dist, 0.5, dist); // 对距离变换结果取平方根以获得较好的显示效果Mat dist32s, dist8u1, dist8u2; // 用于转换数据类型的中间Mat变量dist.convertTo(dist32s, CV_32S, 1, 0.5); // 转换数据类型dist32s &= Scalar::all(255); // 将数值截断到[0, 255]范围内dist32s.convertTo(dist8u1, CV_8U, 1, 0); // 转换数据类型到8位无符号整型dist32s *= -1; // 取反dist32s += Scalar::all(255); // 增加255以避免负数值dist32s.convertTo(dist8u2, CV_8U); // 再次转换数据类型Mat planes[] = {dist8u1, dist8u2, dist8u2}; // 创建用于合并的平面数组merge(planes, 3, dist8u); // 合并三个平面成为一个3通道图像}// 如果激活了维诺图模式,进行以下处理else{dist8u.create(labels.size(), CV_8UC3); // 创建用于显示的8位3通道图像// 遍历图像中的所有像素for( int i = 0; i < labels.rows; i++ ){   //获取第i行的指针,并将其转换为指向int类型的指针。这样,ll就是指向labels图像第i行数据的指针,labels图像包含了沃罗诺伊图的标签信息。const int* ll = (const int*)labels.ptr(i);const float* dd = (const float*)dist.ptr(i);//获取dist图像第i行的指针,并将其转换为指向float类型的指针。dist图像包含了每个像素到最近的零像素点的距离uchar* d = (uchar*)dist8u.ptr(i);//获取输出图像(假设是dist8u)第i行的指针,并将其转换为指向uchar类型的指针。这里的dist8u是一个三通道的8位无符号整型图像,它将会被用来显示沃罗诺伊图及其颜色化的距离映射。for( int j = 0; j < labels.cols; j++ ){int idx = ll[j] == 0 || dd[j] == 0 ? 0 : (ll[j]-1)%8 + 1; // 计算颜色索引float scale = 1.f/(1 + dd[j]*dd[j]*0.0004f); // 根据距离计算颜色缩放因子int b = cvRound(colors[idx][0]*scale); // 计算蓝色分量int g = cvRound(colors[idx][1]*scale); // 计算绿色分量int r = cvRound(colors[idx][2]*scale); // 计算红色分量d[j*3] = (uchar)b;     // 设置蓝色分量d[j*3+1] = (uchar)g;   // 设置绿色分量d[j*3+2] = (uchar)r;   // 设置红色分量}}}imshow("Distance Map", dist8u ); // 显示距离图
}// 辅助输出函数,主要用于输出帮助信息
static void help(const char** argv)
{printf("\n本程序用于演示利用距离变换函数处理边缘图像之间的关系。\n""用法:\n""%s [image_name -- 默认图片为stuff.jpg]\n""\n快捷键:\n""\tESC - 退出程序\n""\tC - 使用C/Inf度量\n""\tL1 - 使用L1度量\n""\tL2 - 使用L2度量\n""\t3 - 使用3x3掩码\n""\t5 - 使用5x5掩码\n""\t0 - 使用精确距离变换\n""\tv - 切换到Voronoi图模式\n""\tp - 切换到基于像素的Voronoi图模式\n""\tSPACE - 遍历所有的模式\n\n", argv[0]);
}const char* keys =
{"{help h||}{@image |stuff.jpg|input image file}"
};int main( int argc, const char** argv )
{CommandLineParser parser(argc, argv, keys); // 使用命令行解析器来处理输入参数help(argv); // 显示帮助信息if (parser.has("help")) // 如果命令行包含帮助标志(例如-h或--help)return 0; // 返回0并退出,不执行接下来的代码string filename = parser.get<string>(0); // 获取命令行中的第一个参数,通常是输入图像的文件名gray = imread(samples::findFile(filename), 0); // 读取输入的图像,并转换为灰度图if(gray.empty()) // 判断读取的图像是否为空{printf("无法读取图像文件:%s\n", filename.c_str()); // 如果为空,打印错误信息help(argv); // 再次显示帮助信息return -1; // 返回-1表示错误退出}namedWindow("Distance Map", 1); // 创建一个名为"Distance Map"的窗口createTrackbar("Brightness Threshold", "Distance Map", &edgeThresh, 255, onTrackbar, 0); // 创建一个调整‘亮度阀值’的trackbarfor(;;) // 创建一个无限循环{onTrackbar(0, 0); // 调用回调函数,更新显示的视图char c = (char)waitKey(0); // 等待用户按键if( c == 27 ) // 如果按下ESC键(键码27)break; // 退出循环if( c == 'c' || c == 'C' || c == '1' || c == '2' || // 根据按键设置相关参数c == '3' || c == '5' || c == '0' )voronoiType = -1; // 重置voronoiTypeif( c == 'c' || c == 'C' )distType0 = DIST_C; // 设置距离变换为C类型else if( c == '1' )distType0 = DIST_L1; // 设置距离变换为L1类型else if( c == '2' )distType0 = DIST_L2; // 设置距离变换为L2类型else if( c == '3' )maskSize0 = DIST_MASK_3; // 设置掩码大小为3x3else if( c == '5' )maskSize0 = DIST_MASK_5; // 设置掩码大小为5x5else if( c == '0' )maskSize0 = DIST_MASK_PRECISE; // 设置掩码大小为精确模式else if( c == 'v' )voronoiType = 0; // 切换到Voronoi图模式else if( c == 'p' )voronoiType = 1; // 切换到基于像素的Voronoi图模式else if( c == ' ' ) // 当用户按下空格键时{if( voronoiType == 0 ) // 如果当前是Voronoi图模式(基于标签)voronoiType = 1; // 切换到pixel-based Voronoi diagram mode(像素级)else if( voronoiType == 1 ) // 如果当前是像素级的Voronoi图模式{voronoiType = -1; // 关闭Voronoi图模式maskSize0 = DIST_MASK_3; // 重置掩码大小为3x3distType0 = DIST_C; // 重置距离类型为C/Inf度量}else if( distType0 == DIST_C ) // 如果当前距离类型为C/Inf度量distType0 = DIST_L1; // 切换到L1度量else if( distType0 == DIST_L1 ) // 如果当前距离类型为L1度量distType0 = DIST_L2; // 切换到L2度量else if( maskSize0 == DIST_MASK_3 ) // 如果当前掩码大小为3x3maskSize0 = DIST_MASK_5; // 切换到5x5掩码大小else if( maskSize0 == DIST_MASK_5 ) // 如果当前掩码大小为5x5maskSize0 = DIST_MASK_PRECISE; // 切换到精确的距离变换else if( maskSize0 == DIST_MASK_PRECISE ) // 如果当前是精确的距离变换voronoiType = 0; // 开启Voronoi图模式(基于标签)}}return 0; // 程序正常退出
}

这段代码是一个使用OpenCV库函数,实现了基于距离变换的图像边缘检测,并由用户输入不同键值来调节距离度量方式、掩码大小及是否进入Voronoi图模式的C++程序示例。程序的主体会根据用户输入的图像文件,展示并允许用户通过交互式的方式(例如调节阈值的trackbar),来实时观察不同算法参数下的距离变换结果。程序还支持展示Voronoi图,用户可以通过键盘输入控制变换参数,探索对图像处理的影响。

distanceTransform( edge, dist, distType, maskSize );

2b6d82ecc5235f3ee496fb4ef3b24532.png

distanceTransform( edge, dist, labels, distType, maskSize, voronoiType );

774d3b324a7dcb36bf154310567abef7.png

5f8a476b598420621be1e7a0b1587ed5.png

v

5f483cc797ff0d0296fdefcffd2cce6e.png

p

这段代码是一个OpenCV的示例程序,演示了如何使用距离变换函数(distance transform)在边缘图像之间的应用。

  • 全局变量:

    • maskSize0: 用于调整掩码大小,初始设置为 DIST_MASK_5

    • voronoiType: 用于切换绘制沃罗诺伊图,初始值为 -1,表示未激活该模式。

    • edgeThresh: 边缘阈值,默认为100。

    • distType0: 距离类型,默认是 DIST_L1

    • gray: 一个Mat对象,用来存储灰度图像。

  • 主要函数:

    • 解析命令行参数,加载灰度图像。

    • 创建一个显示距离映射的窗口和对应的滑动条。

    • 进入一个无限循环,监听按键事件以改变距离变换的参数或是退出程序。

    • 首先根据是否在沃罗诺伊模式下设置距离类型和掩码大小。

    • 使用 distanceTransform 函数计算边缘图像的距离变换。

    • 如果不是沃罗诺伊模式,则对结果进行渲染并显示在窗口中。

    • 如果是沃罗诺伊模式,则根据距离和标签值对颜色进行缩放,以绘制沃罗诺伊图。

    • onTrackbar: 这个回调函数会响应滑动条变化,它计算边缘图像的距离变换,并将结果绘制在窗口中。

    • help: 显示帮助信息,列出了程序的用法和键盘操作指南。

    • main: 程序的主入口。

按键指南包括对距离计算方法(C/Inf、L1、L2)、掩码大小(3x3、5x5)、距离变换精确度以及绘制沃罗诺伊图模式的切换支持。输入图片名称可以通过命令行参数提供,如果未提供参数则默认使用 "stuff.jpg" 图片。

整体来说,这个程序可以让用户通过改变参数来探索不同的距离度量和掩码对距离变换效果的影响,以及如何生成沃罗诺伊图。

相关文章:

【opencv】示例-distrans.cpp 距离变换

stuff.jpg #include <opencv2/core/utility.hpp> // 包含OpenCV中的核心功能支持库 #include "opencv2/imgproc.hpp" // 包含OpenCV中的图像处理库 #include "opencv2/imgcodecs.hpp" // 包含OpenCV中的图像编解码库 #include "open…...

LVGL V8 代码细读——极致的链表使用

极致的链表的使用 序章碎碎念从redis源码里掏出来的adlist极致的精简的list.hlvgl对链表的巧思lv_ll尾记 序章碎碎念 对于链表&#xff0c;大家应该都不陌生。学过数据结构的&#xff0c;都知道它作为链式储存的基础&#xff0c;重要性不言而喻。 由于本人自动化专业&#xff…...

蓝桥杯第十二届c++大学B组详解

目录 1.空间 2.直线 3.路径 4.卡片 5.货物摆放 6.时间显示 7.砝码称重 8.杨辉三角 9.双向排序 10.括号序列 1.空间 题目解析&#xff1a;1Byte 8bit 1kb 1024B 1MB 1024kb; 先将256MB变成Byte 256 * 1024 * 1024; 再将32位 变成Byte就是 32 / 8 4&#xff1b;…...

Tubi 十岁啦!

Tubi 今年十岁了&#xff0c;这十年不可思议&#xff0c;充满奇迹&#xff01; 从硅谷一个名不见经传的创业小作坊&#xff0c;转变成为四分之一美国电视家庭提供免费流媒体服务的北美领先的平台&#xff1b; 从费尽心力终于签下第一笔内容合作协议&#xff0c;到现在与 450 …...

Qt C++ 实现文件监视源码

以下是使用Qt C++实现文件监视的一个简单示例代码: #include <QCoreApplication> #include <QFileSystemWatcher> #include <QDebug>int main(int argc, char *argv[...

蓝桥杯第十一届c++大学B组详解

目录 1.字符串排序 2.门牌制作 3.即约分数 4.蛇型填数 5.跑步锻炼 6.七段码 7.成绩统计 8.回文日期 9.字串分值和 10.平面切分 1.字符串排序 题目解析&#xff1a;这个题目真没搞懂。有会的大佬教我一下谢谢。 2.门牌制作 题目解析&#xff1a;出过超级多这类题目&am…...

大模型日报2024-04-10

大模型日报 2024-04-10 大模型资讯 微软研究者提出通过可视化思维提升大型语言模型的空间推理能力 摘要: 微软研究者近日提出了一种新方法&#xff0c;旨在通过可视化思维来增强大型语言模型&#xff08;LLMs&#xff09;的空间推理能力。尽管LLMs在语言理解和推理任务方面表现…...

redis修改协议改了,有哪些替代品?

Redis 是一款广泛使用的开源内存数据结构存储&#xff0c;它支持多种数据结构&#xff0c;如字符串、哈希表、列表、集合、有序集合等。然而&#xff0c;由于 Redis 最近更改了其开源许可证&#xff0c;一些用户和开发者可能正在寻找替代品。以下是一些 Redis 的替代品&#xf…...

《QT实用小工具·十六》IP地址输入框控件

1、概述 源码放在文章末尾 该项目为IP地址输入框控件&#xff0c;主要包含如下功能&#xff1a; 可设置IP地址&#xff0c;自动填入框。 可清空IP地址。 支持按下小圆点自动切换。 支持退格键自动切换。 支持IP地址过滤。 可设置背景色、边框颜色、边框圆角角度。 下面…...

windows 系统下 mysql 数据库的下载与安装(包括升级安装)

windows 系统下 mysql 数据库的下载与安装&#xff08;包括升级安装&#xff09; 一、mysql 介绍&#xff1a; MySQL 是一个关系型数据库管理系统&#xff0c;由瑞典 MySQL AB 公司开发&#xff0c;属于 Oracle 旗下产品。 MySQL 是最流行的关系型数据库管理系统之一&#xf…...

Redis Stack十部曲之三:理解Redis Stack中的数据类型

文章目录 前言String字符串作为计数器限制 List限制列表阻塞列表自动创建和删除聚合类型键限制 Set限制 Hash限制 Sorted Set范围操作字典操作更新分数 JSON路径限制 BitMapBitfieldProbabilisticHyperLogLogBloom filterCuckoo filtert-digestTop-KCount-min sketchConfigurat…...

OneForAll安装使用

OneForAll简介 OneForAll是一款功能强大的子域收集工具 原项目地址&#xff1a;GitHub - shmilylty/OneForAll: OneForAll是一款功能强大的子域收集工具 gitee项目地址&#xff1a;OneForAll: OneForAll是一款功能强大的子域收集工具 # 安装Python Windows系统安装python参…...

【现代C++】线程支持库

现代C&#xff08;C11及其之后的版本&#xff09;引入了标准的线程支持库&#xff0c;使得多线程编程变得更加简单和可移植。这个库提供了线程管理、互斥量、条件变量和其他同步原语。 1. std::thread - 基本线程 std::thread允许创建执行特定任务的线程。 #include <ios…...

游戏引擎架构01__引擎架构图

根据游戏引擎架构预设的引擎架构来构建运行时引擎架构 ​...

[Java、Android面试]_15_Android为什么使用Binder?

Android为什么使用Binder&#xff1f;用 Linux原有的IPC不行吗&#xff1f; 本人今年参加了很多面试&#xff0c;也有幸拿到了一些大厂的offer&#xff0c;整理了众多面试资料&#xff0c;后续还会分享众多面试资料。 整理成了面试系列&#xff0c;由于时间有限&#xff0c;每天…...

Python+Selenium+Unittest 之Unittest3(TestSuite()和TextTestRunner())

目录 1&#xff1a;addTest() 2、addTests() 3&#xff1a;discover() 上一篇说了Unittest的一个基本的执行顺序&#xff0c;那如果我们想要调整用例的执行先后顺序的话&#xff0c;可以用TestSuite()和TextTestRunner()了&#xff0c;可以这么理解&#xff0c;比如一个班级…...

3D桌面端可视化引擎HOOPS Visualize如何实现3D应用快速开发?

HOOPS Visualize是一个开发平台&#xff0c;可实现高性能、跨平台3D工程应用程序的快速开发。一些主要功能包括&#xff1a; 高性能、以工程为中心的可视化&#xff0c;使用高度优化的OpenGL或DirectX驱动程序来充分利用可用的图形硬件线程安全的C和C#接口&#xff0c;内部利用…...

Vue探索之Vue2.x源码分析(二)

一.Virtual Dom 虚拟DOM是一种轻量级的抽象&#xff0c;它允许我们在Javascript中创建、更新和删除DOM元素。它是React等现代Javascript框架的核心概念之一。 Vue的虚拟dom是一种抽象层的概念&#xff0c;它使得Vue可以高效地更新Dom。虚拟Dom是通过Javascript对象来表示DOM结…...

人工智能分类算法概述

文章目录 人工智能主要分类算法决策树随机森林逻辑回归K-均值 总结 人工智能主要分类算法 人工智能分类算法是用于将数据划分为不同类别的算法。这些算法通过学习数据的特征和模式&#xff0c;将输入数据映射到相应的类别。分类算法在人工智能中具有广泛的应用&#xff0c;如图…...

理解 Golang 变量在内存分配中的规则

为什么有些变量在堆中分配、有些却在栈中分配&#xff1f; 我们先看来栈和堆的特点&#xff1a; 简单总结就是&#xff1a; 栈&#xff1a;函数局部变量&#xff0c;小数据 堆&#xff1a;大的局部变量&#xff0c;函数内部产生逃逸的变量&#xff0c;动态分配的数据&#x…...

《QT实用小工具·二十四》各种数学和数据的坐标演示图

1、概述 源码放在文章末尾 该项目实现了各种数学和数据的坐标演示图&#xff0c;下面是demo演示&#xff1a; 项目部分代码如下&#xff1a; #ifndef FRMMAIN_H #define FRMMAIN_H#include <QWidget> class QAbstractButton;namespace Ui { class frmMain; }class fr…...

【S32K3 MCAL配置】-3.1-CANFD配置-经典CAN切换CANFD(基于MCAL+FreeRTOS)

"><--返回「Autosar_MCAL高阶配置」专栏主页--> 目录(共5页精讲,基于评估板: NXP S32K312EVB-Q172,手把手教你S32K3从入门到精通) 实现的架构:基于MCAL层 前期准备工作:...

IEC101、IEC103、IEC104、Modbus报文解析工具

一、概述 国际电工委员会第57技术委员会&#xff08;IEC TC57&#xff09;1995年出版IEC 60870-5-101后&#xff0c;得到了广泛的应用。为适应网络传输&#xff0c;2000年IEC TC57又出版了IEC 60870-5-104&#xff1a;2000《远东设备及系统 第5-104部分&#xff1a;传输规约-采…...

node res.end返回json格式数据

使用 Node.js 内置 http 模块的createServer()方法创建一个新的HTTP服务器并返回json数据&#xff0c;代码如下&#xff1a; const http require(http);const hostname 127.0.0.1; const port 3000;const data [{ name: 测试1号, index: 0 },{ name: 测试2号, index: 1 },…...

产品开发流程

产品开发流程 时间&#xff1a;2024年04月10日 作者&#xff1a;小蒋聊技术 邮箱&#xff1a;wei_wei10163.com 微信&#xff1a;wei_wei10 产品开发流程_小蒋聊技术_免费在线阅读收听下载 - 喜马拉雅欢迎收听小蒋聊技术的类最新章节声音“产品开发流程”。时间&#xff1a;…...

Python蓝桥杯赛前总结

1.进制转换 (1) 2进制转换为其他进制 # 2转10 int(n, 2) # 2转8 oct(int(n, 2)) # 2转16 hex(int(n, 2)) (2) 8进制转换为其他进制 #8转10 int(n, 8) #8转2 bin(int(n, 8)) #8转16 hex(int(n, 8)) (3) 10进制转换为其他进制 #10转2 bin(n) #10转8 oct(n) #10转16 hex(n) …...

20240326-1-KNN面试题

KNN面试题 1.简述一下KNN算法的原理 KNN算法利用训练数据集对特征向量空间进行划分。KNN算法的核心思想是在一个含未知样本的空间&#xff0c;可以根据样本最近的k个样本的数据类型来确定未知样本的数据类型。 该算法涉及的3个主要因素是&#xff1a;k值选择&#xff0c;距离度…...

【论文速读】| MASTERKEY:大语言模型聊天机器人的自动化越狱

本次分享论文为&#xff1a;MASTERKEY: Automated Jailbreaking of Large Language Model Chatbots 基本信息 原文作者&#xff1a;Gelei Deng, Yi Liu, Yuekang Li, Kailong Wang, Ying Zhang, Zefeng Li, Haoyu Wang, Tianwei Zhang, Yang Liu 作者单位&#xff1a;南洋理工…...

jvm运行情况预估

相关系统 jvm优化原则-CSDN博客 执行下面指令 jstat gc -pid 能计算出一些关键数据&#xff0c;有了这些数据&#xff0c;先给JVM参数一些的初始的&#xff0c;比堆内存大小、年轻代大小 、Eden和Srivivor的比例&#xff0c;老年代的大小&#xff0c;大对象的阈值&#xff0c;…...

Day105:代码审计-PHP原生开发篇SQL注入数据库监控正则搜索文件定位静态分析

目录 代码审计-学前须知 Bluecms-CNVD-1Day-常规注入审计分析 emlog-CNVD-1Day-常规注入审计分析 emlog-CNVD-1Day-2次注入审计分析 知识点&#xff1a; 1、PHP审计-原生态开发-SQL注入&语句监控 2、PHP审计-原生态开发-SQL注入&正则搜索 3、PHP审计-原生态开发-SQ…...