c/c++的opencv的轮廓匹配初识
OpenCV 轮廓匹配:形状识别与比较 📐✨
轮廓匹配是计算机视觉中一个重要的技术,它允许我们比较两个形状的相似度。OpenCV 提供了强大的函数来实现这一功能,核心是 cv::matchShapes()
。本文将引导你了解轮廓匹配的基本原理、OpenCV 中的实现方法,并提供一个 C++ 示例。
1. 什么是轮廓?
在图像处理中,轮廓可以简单理解为连接具有相同颜色或灰度强度值的连续点的曲线。轮廓对于形状分析、对象检测和识别非常有用。在进行轮廓匹配之前,通常需要以下步骤:
- 图像加载:读取源图像和模板图像。
- 预处理:
- 灰度转换:将彩色图像转换为灰度图像。
- 二值化:将灰度图像转换为二值图像(黑白)。这通常通过阈值化实现,例如使用
cv::threshold()
。 - (可选)形态学操作:如腐蚀、膨胀,用于去除噪声或连接断裂的轮廓。
- 轮廓查找:使用
cv::findContours()
在二值图像中提取轮廓。
2. 轮廓匹配原理:Hu矩
OpenCV 中的 cv::matchShapes()
函数使用 Hu矩 (Hu Moments) 来计算两个轮廓(或形状)之间的相似度。Hu矩是一组由中心矩计算得出的七个矩不变量。这些不变量具有平移、旋转和缩放不变性,这意味着即使形状的位置、朝向或大小发生变化,Hu矩的值也基本保持不变。这使得它们非常适合进行形状匹配。
cv::matchShapes()
函数返回一个浮点数,表示两个轮廓之间的“距离”或“不相似度”。返回值越小,表示两个轮廓越相似。
3. OpenCV 实现:cv::matchShapes()
函数原型 (C++):
double cv::matchShapes(InputArray contour1, InputArray contour2, int method, double parameter);
参数说明:
contour1
: 第一个轮廓或灰度图像。contour2
: 第二个轮廓或灰度图像。method
: 比较方法。OpenCV 提供了三种方法:cv::CONTOURS_MATCH_I1
cv::CONTOURS_MATCH_I2
cv::CONTOURS_MATCH_I3
(常用且推荐)
parameter
: 特定比较方法的参数,通常设置为0
。
4. C++ 示例代码
下面的示例代码演示了如何加载两张图像,分别提取它们的轮廓,然后比较这些轮廓的相似度。
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>// 辅助函数:预处理图像并提取最大轮廓
cv::Mat preprocessAndGetMainContour(const cv::Mat& image, std::vector<cv::Point>& mainContour) {if (image.empty()) {std::cerr << "错误: 图像为空!" << std::endl;mainContour.clear();return cv::Mat();}cv::Mat gray, binary;// 1. 转换为灰度图cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);// 2. 二值化// 使用OTSU方法自动确定阈值,对于黑白分明的物体效果较好// 如果背景复杂,可能需要手动调整阈值或使用自适应阈值cv::threshold(gray, binary, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);// THRESH_BINARY_INV 假设物体是亮的,背景是暗的,如果相反则用THRESH_BINARY// (可选) 显示二值化图像,方便调试// cv::imshow("Binary " + std::to_string(rand()), binary);// 3. 查找轮廓std::vector<std::vector<cv::Point>> contours;std::vector<cv::Vec4i> hierarchy;cv::findContours(binary, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);if (contours.empty()) {std::cerr << "未找到轮廓!" << std::endl;mainContour.clear();return binary; // 返回二值图供参考}// 4. 假设最大的轮廓是我们要匹配的目标轮廓double maxArea = 0;int maxAreaIdx = -1;for (size_t i = 0; i < contours.size(); i++) {double area = cv::contourArea(contours[i]);if (area > maxArea) {maxArea = area;maxAreaIdx = i;}}if (maxAreaIdx != -1) {mainContour = contours[maxAreaIdx];} else {mainContour.clear();}return binary; // 返回二值图供参考
}int main() {// 加载模板图像和待匹配图像// 请替换为你自己的图像路径cv::Mat templateImage = cv::imread("template_shape.png");cv::Mat targetImage = cv::imread("target_shape_to_match.png");if (templateImage.empty() || targetImage.empty()) {std::cout << "无法加载模板或目标图像!" << std::endl;return -1;}std::vector<cv::Point> templateContour;std::vector<cv::Point> targetContour;// 预处理并获取模板轮廓cv::Mat templateBinary = preprocessAndGetMainContour(templateImage, templateContour);if (templateContour.empty()) {std::cout << "模板图像中未找到有效轮廓。" << std::endl;return -1;}// 预处理并获取目标轮廓cv::Mat targetBinary = preprocessAndGetMainContour(targetImage, targetContour);if (targetContour.empty()) {std::cout << "目标图像中未找到有效轮廓。" << std::endl;return -1;}// 显示包含轮廓的图像 (可选)cv::Mat templateContourDrawing = templateImage.clone();cv::Mat targetContourDrawing = targetImage.clone();if (!templateContour.empty())cv::drawContours(templateContourDrawing, std::vector<std::vector<cv::Point>>{templateContour}, -1, cv::Scalar(0, 255, 0), 2);if (!targetContour.empty())cv::drawContours(targetContourDrawing, std::vector<std::vector<cv::Point>>{targetContour}, -1, cv::Scalar(0, 0, 255), 2);cv::imshow("模板轮廓", templateContourDrawing);cv::imshow("目标轮廓", targetContourDrawing);if(!templateBinary.empty()) cv::imshow("模板二值图", templateBinary);if(!targetBinary.empty()) cv::imshow("目标二值图", targetBinary);// 进行轮廓匹配// 使用 cv::CONTOURS_MATCH_I3 方法double similarity = cv::matchShapes(templateContour, targetContour, cv::CONTOURS_MATCH_I3, 0.0);std::cout << "轮廓相似度 (越小越相似): " << similarity << std::endl;// 根据相似度值设定一个阈值来判断是否匹配if (similarity < 0.5) { // 0.5 是一个经验阈值,需要根据实际情况调整std::cout << "结论: 轮廓匹配!" << std::endl;} else {std::cout << "结论: 轮廓不匹配。" << std::endl;}cv::waitKey(0);return 0;
}
编译和运行说明:
- 保存代码: 将代码保存为
.cpp
文件,例如contour_matching.cpp
。 - 准备图像: 创建两张图像:
template_shape.png
(包含你想要匹配的形状) 和target_shape_to_match.png
(包含待测试的形状)。确保这些图像中的目标物体与背景有较好的对比度,以便于二值化。 - 编译:
(如果你的 OpenCV 版本是 3.x,使用g++ contour_matching.cpp -o contour_matcher $(pkg-config --cflags --libs opencv4)
opencv
而不是opencv4
) - 运行:
./contour_matcher
5. 注意事项与局限性
- 预处理非常关键:
cv::findContours()
的输入通常是二值图像。合适的灰度化、阈值化方法对提取准确的轮廓至关重要。 - Hu矩的局限性:虽然Hu矩具有平移、旋转和缩放不变性,但它们对噪声、遮挡和非刚性形变比较敏感。如果形状有轻微的非刚性变化(如手写数字),匹配效果可能会下降。
- 选择合适的轮廓:如果图像中包含多个物体,
cv::findContours()
会返回所有物体的轮廓。你需要有策略地选择你感兴趣的轮廓进行比较(例如,基于轮廓的面积、周长或其他属性)。示例代码中选择了面积最大的轮廓。 - 相似度阈值:
cv::matchShapes()
返回的值没有固定的“匹配”或“不匹配”界限。你需要根据你的应用场景和测试数据,通过实验来确定一个合适的阈值。 - 比较方法的选择:
cv::CONTOURS_MATCH_I1
,cv::CONTOURS_MATCH_I2
,cv::CONTOURS_MATCH_I3
是基于不同的Hu矩组合计算的。CONTOURS_MATCH_I3
通常被认为是比较鲁棒的一个。
轮廓匹配是一个强大的工具,尤其适用于识别具有固定或相似形状的物体。通过结合良好的预处理技术和对匹配结果的合理评估,你可以在多种计算机视觉应用中有效地利用它。祝你编码愉快!🚀
相关文章:
c/c++的opencv的轮廓匹配初识
OpenCV 轮廓匹配:形状识别与比较 📐✨ 轮廓匹配是计算机视觉中一个重要的技术,它允许我们比较两个形状的相似度。OpenCV 提供了强大的函数来实现这一功能,核心是 cv::matchShapes()。本文将引导你了解轮廓匹配的基本原理、OpenCV…...
Oracle APEX IR报表下载CSV文件的方法
目录 0. 准备工作 1. 下载--自定义SQL 2. 下载--检索结果 0. 准备工作 -- 建表 CREATE TABLE T_DL_EMP(EMPNO NUMBER(4) NOT NULL -- 雇员编号,由四个数字组成。, ENAME VARCHAR2(10) -- 雇员姓名,由10个字符组成。, JOB …...
JVM 双亲委派机制
一、从 JDK 到 JVM:Java 运行环境的基石 在 Java 开发领域,JDK(Java Development Kit)是开发者的核心工具包。它不仅包含了编译 Java 代码的工具(如 javac),还内置了 JRE(Java Run…...
shell脚本之条件判断,循环控制,exit详解
if条件语句的语法及案例 一、基本语法结构 1. 单条件判断 if [ 条件 ]; then命令1命令2... fi2. 双分支(if-else) if [ 条件 ]; then条件为真时执行的命令 else条件为假时执行的命令 fi3. 多分支(if-elif-else) if [ 条件1 ]…...
什么是私有IP地址?如何判断是不是私有ip地址
在互联网的世界中,IP地址是设备之间通信的基础标识。无论是浏览网页、发送邮件还是在线游戏,IP地址都扮演着至关重要的角色。然而,并非所有的IP地址都是公开的,有些IP地址被保留用于内部网络,这就是我们所说的私有IP地…...
BGP路由策略 基础实验
要求: 1.使用Preva1策略,确保R4通过R2到达192.168.10.0/24 2.用AS_Path策略,确保R4通过R3到达192.168.11.0/24 3.配置MED策略,确保R4通过R3到达192.168.12.0/24 4.使用Local Preference策略,确保R1通过R2到达192.168.1.0/24 …...
Java 原生网络编程(BIO | NIO | Reactor 模式)
1、基本常识 Socket 是应用层与 TCP/IP 协议族通信的中间软件抽象层,是一组接口,使用了门面模式对应用层隐藏了传输层以下的实现细节。TCP 用主机的 IP 地址加上主机端口号作为 TCP 连接的端点,该端点叫做套接字 Socket。 比如三次握手&…...
大语言模型 11 - 从0开始训练GPT 0.25B参数量 MiniMind2 准备数据与训练模型 DPO直接偏好优化
写在前面 GPT(Generative Pre-trained Transformer)是目前最广泛应用的大语言模型架构之一,其强大的自然语言理解与生成能力背后,是一个庞大而精细的训练流程。本文将从宏观到微观,系统讲解GPT的训练过程,…...
【Java ee初阶】HTTP(4)
构造HTTP请求 1)开发中,前后端交互。浏览器运行的网页中,构造出HTTP请求 2)调试阶段,通过构造HTTP请求测试服务器 朴素的方案: 通过tcp socket 的方式构造HTTP请求 按照HTTP请求格式,往TCP…...
永久免费!专为 Apache Doris 打造的可视化数据管理工具 SelectDB Studio V1.1.0 重磅发布!
作为全球领先的开源实时数据仓库, Apache Doris Github Stars 已超过 13.6k,并在 5000 余家中大型企业生产环境得到广泛应用,支撑业务核心场景,成为众多企业数据分析基础设施不可或缺的重要基座。过去,Apache Doris 用…...
React中useDeferredValue与useTransition终极对比。
文章目录 前言一、核心差异对比二、代码示例对比1. useDeferredValue:延迟搜索结果更新2. useTransition:延迟路由切换 三、应用场景总结四、注意事项五、原理剖析1. 核心机制对比2. 关键差异3. 代码实现原理 总结 前言 在React的并发模式下,…...
Git 项目切换到新的远程仓库地址
已存在的 Git 项目切换到新的远程仓库地址,比如你要换成: gitgithub.com:baoing/test-app.git步骤如下: 查看当前的远程仓库地址(可选) git remote -v你会看到类似: origin gitgithub.com:old-user/old…...
科技晚报 AI 速递:今日科技热点一览 丨 2025 年 5 月 17 日
科技晚报AI速递:今日科技热点一览 丨2025年5月17日 我们为您汇总今日的科技领域最新动向,带您快速了解前沿技术、突破性研究及行业趋势。 黄仁勋劝特朗普:AI 芯片出口规则得改,中国紧追其后:英伟达 CEO 黄仁勋在华盛顿 “山与谷论…...
基于OpenCV的SIFT特征和FLANN匹配器的指纹认证
文章目录 引言一、概述二、代码解析1. 图像显示函数2. 核心认证函数3. 匹配点筛选4. 认证判断 三、主程序四、技术要点五、总结 引言 在计算机视觉领域,图像特征匹配是一个非常重要的技术,广泛应用于物体识别、图像拼接、运动跟踪等场景。今天将介绍一个…...
【Linux】共享内存
🌻个人主页:路飞雪吖~ 🌠专栏:Linux 目录 ☃️共享内存 🪄 shmget函数 用来创建共享内存 ✨共享内存的管理指令: 🌠 shmid VS key ✨共享内存函数 🍔 shmget() 创建共享内存 &a…...
Cookie、Session、Token
Cookie 1. 什么是cookie? Cookie 是一种由服务器发送到客户端浏览器的小数据片段,用于存储用户的状态信息。例如,用户登录状态或用户偏好设置可以通过Cookie进行管理。计算机cookie更正式地称为 HTTP cookie、网络 cookie、互联网 cookie 或浏览器 coo…...
设计模式Java
UML类图 概述 类图(Class diagram)是显示了模型的静态结构,特别是模型中存在的类、类的内部结构以及它们与其他类的关系等。类图不显示暂时性的信息。类图是面向对象建模的主要组成部分。 类图的作用 在软件工程中,类图是一种静态的结构图,…...
Word文档图片排版与批量处理工具推荐
先放下载链接:夸克网盘下载 前几天给大家推荐了 Excel 图片调整软件,当时好多小伙伴问有没有 Word 相关的软件。我在网上找了一圈都没找到合适的,最后在我好久之前记录的一个文档里发现了,这不,马上就来给大家推荐,有…...
[案例五] 实体——赋值质量
最近翻阅了实验室其他人编写的一个“质量赋值”功能,能够直接为实体或组件设定质量。出于好奇,我对其进行了分析。由于自己平时没有用到该功能,所以也借此机会学习一下。 在分析过程中,我发现NX 官方其实并没有提供直接修改质量的功能。一般来说,质量是通过“密度 体积”…...
手撕四种常用设计模式(工厂,策略,代理,单例)
工厂模式 一、工厂模式的总体好处 解耦:客户端与具体实现类解耦,符合“开闭原则”。统一创建:对象创建交由工厂处理,便于集中控制。增强可维护性:新增对象种类时不需要大改动调用代码。便于扩展:易于管理…...
C# 深入理解类(静态函数成员)
静态函数成员 除了静态字段,还有静态函数成员。 如同静态字段,静态函数成员独立于任何类实例。即使没有类的实例,仍然可以调用静 态方法。静态函数成员不能访问实例成员,但能访问其他静态成员。 例如,下面的类包含一…...
数据类型转换
文章目录 基本数据类型(primitive type)整数类型:浮点类型字符类型boolean类型 类型转换类型转换注意点 基本数据类型(primitive type) 整数类型: byte占1个字节范围:-128-127 short占…...
深入理解 TypeScript 中的 unknown 类型:安全处理未知数据的最佳实践
在 TypeScript 的类型体系中,unknown 是一个极具特色的类型。它与 any 看似相似,却在安全性上有着本质差异。本文将从设计理念、核心特性、使用场景及最佳实践等方面深入剖析 unknown,帮助开发者在处理动态数据时既能保持灵活性,又…...
AI:人形机器人的应用场景以及商业化落地潜力分析
应用场景分析 人形机器人的设计使其能够适应人类环境,执行多样化任务。以下是未来主要的应用场景及其详细分析: 医疗与护理 具体应用: 老年护理:协助老年人穿衣、洗澡、喂食,或提供情感陪伴。康复辅助:帮助…...
JavaScript入门【3】面向对象
1.对象: 1.概述: 在js中除了5中基本类型之外,剩下得都是对象Object类型(引用类型),他们的顶级父类是Object;2.形式: 在js中,对象类型的格式为key-value形式,key表示属性,value表示属性的值3.创建对象的方式: 方式1:通过new关键字创建(不常用) let person new Object();// 添…...
亲测有效!OGG 创建抽取进程报错 OGG-08241,如何解决?
前言 今天在测试 OGG 一个功能的时候,需要重新初始化 oggca,所以重装了一下 OGG。重建完之后重新添加抽取进程报错,一直无法添加成功: 经过一翻分析,找到了解决方案,本文记录一下解决过程。 问题描述 OG…...
【第二篇】 初步解析Spring Boot
简介 SpringBoot是由Pivotal团队提供的全新框架,其设计目的是为了用来简化Spring应用的初始搭建以及开发过程的。本文章将详细介绍SpringBoot为什么能够简化项目的搭建以及普通的Spring程序的开发。文章内容若存在错误或需改进的地方,欢迎大家指正&#…...
JVM 机制
目录 一、什么是 JVM: 二、JVM 的运行流程: 三、JVM 内存区域划分: 1、( 1 ) 程序计数器: 1、( 2 ) 元数据区: 1、( 3 ) 栈: 1、( 4 ) 堆: 四、类加载: 1、什么时候会触…...
Java泛型详解
文章目录 1. 引言1.1 什么是泛型1.2 为什么需要泛型1.3 泛型的优势2. 泛型基础2.1 泛型类多个类型参数2.2 泛型方法2.3 泛型接口2.4 类型参数命名约定3. 类型擦除3.1 什么是类型擦除3.2 类型擦除的影响1. 无法获取泛型类型参数的实际类型2. 无法创建泛型类型的数组3. 无法使用`…...
机器学习,深度学习,神经网络,深度神经网络之间有何区别?
先说个人观点:机器学习>神经网络>深度学习≈深度神经网络。深度学习是基于深度神经网络的,深度神经网络和浅层神经网络都是神经网络,而机器学习是包括神经网络在内的算法。 一、机器学习 先说涵盖范围最广的机器学习。机器学习&#…...
AtomicInteger
AtomicInteger 是 Java 并发包 (java.util.concurrent.atomic) 中的一个原子类,用于在多线程环境下对整数进行原子操作。 核心特性 原子性 提供线程安全的原子操作(如自增、加法、比较并交换等),确保在多线程环境中操作不会被中…...
威布尔比例风险模型(Weibull Proportional Hazards Model, WPHM)详解:原理、应用与实施
威布尔比例风险模型(Weibull Proportional Hazards Model, WPHM)详解:原理、应用与实施 一、核心原理:从威布尔分布到比例风险模型 1. 威布尔分布的数学本质 威布尔分布通过两个关键参数(形状参数 (k) 和尺度参数 (\…...
Dubbo:Docker部署Zookeeper、Dubbo Admin的详细教程和SpringBoot整合Dubbo的实战与演练
🪁🍁 希望本文能给您带来帮助,如果有任何问题,欢迎批评指正!🐅🐾🍁🐥 文章目录 一、背景二、Dubbo概述三、Dubbo与SpringCloud的关系四、Dubbo技术架构五、Docker安装Zoo…...
Windows 上安装下载并配置 Apache Maven
1. 下载 Maven 访问官网: 打开 Apache Maven 下载页面。 选择版本: 下载最新的 Binary zip archive(例如 apache-maven-3.9.9-bin.zip)。 注意:不要下载 -src 版本(那是源码包)。 2. 解压 Mave…...
Unbuntu 命令
Ubuntu 命令速查表 分类命令功能描述示例/常用选项文件与目录ls列出目录内容ls -a(显示隐藏文件); ls -lh(详细列表易读大小) cd切换目录cd ~(主目录); cd ..(上级…...
机器学习-人与机器生数据的区分模型测试-数据处理1
附件为训练数据,总体的流程可以作为参考。 导入依赖 import pandas as pd import os import numpy as np from sklearn.model_selection import train_test_split,GridSearchCV from sklearn.ensemble import RandomForestClassifier,VotingClassifier from skle…...
【Linux】进程间通信(一):认识管道
📝前言: 这篇文章我们来讲讲进程间通信——认识管道 🎬个人简介:努力学习ing 📋个人专栏:Linux 🎀CSDN主页 愚润求学 🌄其他专栏:C学习笔记,C语言入门基础&a…...
AMD Vivado™ 设计套件生成加密比特流和加密密钥
概括 重要提示:有关使用AMD Vivado™ Design Suite 2016.4 及更早版本进行 eFUSE 编程的重要更新,请参阅AMD设计咨询 68832 。 本应用说明介绍了使用AMD Vivado™ 设计套件生成加密比特流和加密密钥(高级加密标准伽罗瓦/计数器模式 (AES-GCM)…...
第三十四节:特征检测与描述-SIFT/SURF 特征 (专利算法)
一、特征检测:计算机视觉的基石 在计算机视觉领域中,特征检测与描述是实现图像理解的核心技术。就像人类通过识别物体边缘、角点等特征来认知世界,算法通过检测图像中的关键特征点来实现: 图像匹配与拼接 物体识别与跟踪 三维重建 运动分析 其中,SIFT(Scale-Invariant F…...
【AI】SpringAI 第二弹:基于多模型实现流式输出
目录 一、基于多模型实现流式输出 1.1 什么是流式输出 1.2 多模型引入 1.3 代码实现 1.3.1 流式输出的API介绍 1.3.2 Flux 源码分析 二、了解 Reactor 模型 三、SSE 协议 一、基于多模型实现流式输出 1.1 什么是流式输出 流式输出(Streaming Output)是指数据在生成过程…...
SQL语句执行问题
执行顺序 select [all|distinct] <目标列的表达式1> AS [别名], <目标列的表达式2> AS [别名]... from <表名1或视图名1> [别名],<表名2或视图名2> [别名]... [where <条件表达式>] [group by <列名>] [having <条件表达式>] [ord…...
模型量化AWQ和GPTQ哪种效果好?
环境: AWQ GPTQ 问题描述: 模型量化AWQ和GPTQ哪种效果好? 解决方案: 关于AWQ(Adaptive Weight Quantization)和GPTQ(Generative Pre-trained Transformer Quantization)这两种量化方法的…...
Github 2025-05-17 Rust开源项目日报 Top10
根据Github Trendings的统计,今日(2025-05-17统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10Dart项目1RustDesk: 用Rust编写的开源远程桌面软件 创建周期:1218 天开发语言:Rust, Dart协议类型:GNU Affero General Public Li…...
借助 CodeBuddy 打造我的图标预览平台 —— IconWiz 开发实录
我正在参加CodeBuddy「首席试玩官」内容创作大赛,本文所使用的 CodeBuddy 免费下载链接:腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴 想做一款自己的图标预览平台 这段时间我在做前端 UI 设计时,常常需要到处找图标素材,复…...
KL散度 (Kullback-Leibler Divergence)
KL散度,也称为相对熵 (Relative Entropy),是信息论中一个核心概念,用于衡量两个概率分布之间的差异。给定两个概率分布 P ( x ) P(x) P(x) 和 Q ( x ) Q(x) Q(x)(对于离散随机变量)或 p ( x ) p(x) p(x) 和 q ( x …...
【Linux网络】NAT和代理服务
NAT 之前我们讨论了,IPv4协议中,IP地址数量不充足的问题。 原始报文途径路由器WAN口时,对报文中的源IP进行替换的过程,叫做NAT。 NAT技术当前解决IP地址不够用的主要手段,是路由器的一个重要功能: NAT能…...
DeepSeek赋能电商,智能客服机器人破解大型活动人力困境
1. DeepSeek 与电商客服结合的背景 1.1 电商行业客服需求特点 电商行业具有独特的客服需求特点,这些特点决定了智能客服机器人在该行业的必要性和重要性。 高并发性:电商平台的用户数量庞大,尤其是在促销活动期间,用户咨询量会…...
Unity序列化字段、单例模式(Singleton Pattern)
一、序列化字段 在Unity中,序列化字段是一个非常重要的概念,主要用于在Unity编辑器中显示和编辑类的成员变量,或者在运行时将对象的状态保存到文件或网络中。 1.Unity序列化字段的作用 在编辑器中显示和编辑字段:默认情况下&…...
一个可拖拉实现列表排序的WPF开源控件
从零学习构建一个完整的系统 推荐一个可通过拖拉,来实现列表元素的排序的WPF控件。 项目简介 gong-wpf-dragdrop是一个开源的.NET项目,用于在WPF应用程序中实现拖放功能,可以让开发人员快速、简单的实现拖放的操作功能。 可以在同一控件内…...
hadoop.proxyuser.代理用户.授信域 用来干什么的
在Hadoop的core-site.xml文件中存在三个可选配置,如下 <property><name>hadoop.proxyuser.root.hosts</name><value>*</value> </property> <property><name>hadoop.proxyuser.root.groups</name><value…...