邻接矩阵在图像数据储存中的应用
最编程
2024-02-20 21:27:53
...
#ifndef _GRAPH_H_
#define _GRAPH_H_
#include<iostream>
using namespace std;
#define VERTEX_DEFAULT_SIZE 10
template<typename Type>
class Graph{
public:
bool isEmpty()const{
return curVertices == 0;
}
bool isFull()const{
if(curVertices >= maxVertices || curEdges >= curVertices*(curVertices-1)/2)
return true; //图满有2种情况:(1)、当前顶点数超过了最大顶点数,存放顶点的空间已满
return false; //(2)、当前顶点数并没有满,但是当前顶点所能达到的边数已满
}
int getCurVertex()const{
return curVertices;
}
int getCurEdge()const{
return curEdges;
}
public:
virtual bool insertVertex(const Type &v) = 0; //插入顶点
virtual bool insertEdge(const Type &v1, const Type &v2) = 0; //插入边
virtual bool removeVertex(const Type &v) = 0; //删除顶点
virtual bool removeEdge(const Type &v1, const Type &v2) = 0; //删除边
virtual int getFirstNeighbor(const Type &v) = 0; //得到第一个相邻顶点
virtual int getNextNeighbor(const Type &v, const Type &w) = 0; //得到下一个相邻顶点
public:
virtual int getVertexIndex(const Type &v)const = 0; //得到顶点下标
virtual void showGraph()const = 0; //显示图
protected:
int maxVertices; //最大顶点数
int curVertices; //当前顶点数
int curEdges; //当前边数
};
template<typename Type>
class GraphMtx : public Graph<Type>{ //邻接矩阵继承父类矩阵
#define maxVertices Graph<Type>::maxVertices //因为是模板,所以用父类的数据或方法都得加上作用域限定符
#define curVertices Graph<Type>::curVertices
#define curEdges Graph<Type>::curEdges
public:
GraphMtx(int vertexSize = VERTEX_DEFAULT_SIZE){ //初始化邻接矩阵
maxVertices = vertexSize > VERTEX_DEFAULT_SIZE ? vertexSize : VERTEX_DEFAULT_SIZE;
vertexList = new Type[maxVertices]; //申请顶点空间
for(int i = 0; i < maxVertices; i++){ //都初始化为0
vertexList[i] = 0;
}
edge = new int*[maxVertices]; //申请边的行
for(i = 0; i < maxVertices; i++){ //申请列空间
edge[i] = new int[maxVertices];
}
for(i = 0; i < maxVertices; i++){ //赋初值为0
for(int j = 0; j < maxVertices; j++){
edge[i][j] = 0;
}
}
curVertices = curEdges = 0; //当前顶点和当前边数
}
GraphMtx(Type (*mt)[4], int sz){ //通过已有矩阵的初始化
int e = 0; //统计边数
maxVertices = sz > VERTEX_DEFAULT_SIZE ? sz : VERTEX_DEFAULT_SIZE;
vertexList = new Type[maxVertices]; //申请顶点空间
for(int i = 0; i < maxVertices; i++){ //都初始化为0
vertexList[i] = 0;
}
edge = new int*[maxVertices]; //申请边的行
for(i = 0; i < maxVertices; i++){ //申请列空间
edge[i] = new Type[maxVertices];
}
for(i = 0; i < maxVertices; i++){ //赋初值为矩阵当中的值
for(int j = 0; j < maxVertices; j++){
edge[i][j] = mt[i][j];
if(edge[i][j] != 0){
e++; //统计列的边数
}
}
}
curVertices = sz;
curEdges = e/2;
}
~GraphMtx(){}
public:
bool insertVertex(const Type &v){
if(curVertices >= maxVertices){
return false;
}
vertexList[curVertices++] = v;
return true;
}
bool insertEdge(const Type &v1, const Type &v2){
int maxEdges = curVertices*(curVertices-1)/2;
if(curEdges >= maxEdges){
return false;
}
int v = getVertexIndex(v1);
int w = getVertexIndex(v2);
if(v==-1 || w==-1){
cout<<"edge no exit"<<endl; //要插入的顶点不存在,无法插入
return false;
}
if(edge[v][w] != 0){ //当前边已经存在,不能进行插入
return false;
}
edge[v][w] = edge[w][v] = 1; //因为是无向图,对称的,存在边赋为1;
return true;
} //删除顶点的高效方法
bool removeVertex(const Type &v){
int i = getVertexIndex(v);
if(i == -1){
return false;
}
vertexList[i] = vertexList[curVertices-1];
int edgeCount = 0;
for(int k = 0; k < curVertices; k++){
if(edge[i][k] != 0){ //统计删除该行的边数
edgeCount++;
}
}
//删除行
for(int j = 0; j < curVertices; j++){
edge[i][j] = edge[curVertices-1][j];
}
//删除列
for(j = 0; j < curVertices; j++){
edge[j][i] = edge[j][curVertices-1];
}
curVertices--;
curEdges -= edgeCount;
return true;
}
/* //删除顶点用的是数组一个一个移动的方法,效率太低。
bool removeVertex(const Type &v){
int i = getVertexIndex(v);
if(i == -1){
return false;
}
for(int k = i; k < curVertices-1; ++k){
vertexList[k] = vertexList[k+1];
}
int edgeCount = 0;
for(int j = 0; j < curVertices; ++j){
if(edge[i][j] != 0)
edgeCount++;
}
for(int k = i; k < curVertices-1; ++k)
{
for(int j = 0; j < curVertices; ++j)
{
edge[k][j] = edge[k+1][j];
}
}
for(int k = i; k < curVertices-1; ++k)
{
for(int j = 0; j < curVertices; ++j)
{
edge[j][k] = edge[j][k+1];
}
}
curVertices--;
curEdges -= edgeCount;
return true;
}
*/
bool removeEdge(const Type &v1, const Type &v2){
int v = getVertexIndex(v1);
int w = getVertexIndex(v2);
if(v==-1 || w==-1){ //判断要删除的边是否在当前顶点内
return false; //顶点不存在
}
if(edge[v][w] == 0){ //这个边根本不存在,没有必要删
return false;
}
edge[v][w] = edge[w][v] = 0; //删除这个边赋值为0,代表不存在;
curEdges--;
return true;
}
int getFirstNeighbor(const Type &v){
int i = getVertexIndex(v);
if(i == -1){
return -1;
}
for(int col = 0; col < curVertices; col++){
if(edge[i][col] != 0){
return col;
}
}
return -1;
}
int getNextNeighbor(const Type &v, const Type &w){
int i = getVertexIndex(v);
int j = getVertexIndex(w);
if(i==-1 || j==-1){
return -1;
}
for(int col = j+1; col < curVertices; col++){
if(edge[i][col] != 0){
return col;
}
}
return -1;
}
public:
void showGraph()const{
if(curVertices == 0){
cout<<"Nul Graph"<<endl;
return;
}
for(int i = 0; i < curVertices; i++){
cout<<vertexList[i]<<" ";
}
cout<<endl;
for(i = 0; i < curVertices; i++){
for(int j = 0; j < curVertices; j++){
cout<<edge[i][j]<<" ";
}
cout<<vertexList[i]<<endl;
}
}
int getVertexIndex(const Type &v)const{
for(int i = 0; i < curVertices; i++){
if(vertexList[i] == v){
return i;
}
}
return -1;
}
private:
Type *vertexList; //存放顶点的数组
int **edge; //存放顶点关系的矩阵用边表示
};
#endif
上一篇: 形象说明:邻接矩阵在数据储存中的应用展示
下一篇: 用邻接矩阵表示图形数据结构的方法
推荐阅读
-
ZH-HPLC/RS485 传输模块在光伏逆变器发电数据采集器中的应用 + 宽带电力线载波 HPLC + 站式智能汇聚终端在分布式光伏并网数据采集与编程中的应用特点
-
python 数据分析在电力行业中的应用 python 电影数据分析报告
-
网络在单细胞转录组数据分析中的应用
-
openEuler郑州用户组成立!openEuler与hyperfusion携手共建河南地区用户生态 - 开幕致辞 超融合操作系统业务总经理、openEuler委员会成员蒋振华先生为本次活动致辞。 在本次活动的致辞中,他提到,作为openEuler社区早期的成员,超融合见证了openEuler从成立到在各行业商业落地,再到跨越生态拐点的过程,感谢openEuler提供了一个全产业链共同创新的平台,共同推动创新技术的商业落地。 同时,本次活动得到了郑州市郑东新区大数据管理局、郑州中原科技城投资服务局的大力支持。 郑东新区大数据管理局曹光远 在活动致辞中表示,openEuler的应用和*应用设施的深度优化,为郑东新区数字化转型提供了安全、可靠、高性能的技术基础;郑州中原科技城招商服务局王林表示,郑东新区欢迎所有openEuler生态相关企业扎根当地,围绕openEuler社区共同发展,形成合力。 openEuler社区及运维功能介绍 openEuler技术委员会委员胡峰 openEuler技术委员会委员胡峰先生在本次活动中介绍了openEuler社区目前发展的整体情况,并重点从技术层面介绍了openEuler的运维功能。 openEuler 晚会 胡峰先生介绍智能运维工具 A-Ops 和 openEuler gala、 阿波罗 Apollo、智能漏洞管理解决方案等新功能,以及涵盖各种运维场景的精品运维组件。在*交流环节,许多用户就目前使用的 openEuler 在*交流环节,许多用户就自己在使用openEuler过程中遇到的一些问题与胡峰先生进行了进一步的交流。 软硬结合,构建多样化算力操作系统 Hyperfusion 基于 openEuler 的基础上,结合自身软硬件技术积累,推出了富讯服务器操作系统 FusionOS FusionOS. FusionOS 首席架构师张海亮 分享了 FusionOS FusionOS首席架构师张海亮分享了FusionOS的软硬件协同优势、卓越的性能和可靠性,以及FusionOS在金融、运营商、*、互联网等行业的实践案例,引起了众多用户的兴趣,分享结束后,不少参会者就FusionOS的特点向讲师提问并进行了交流。
-
深度学习原理与实践:深度学习在图像分割中的应用
-
iCloud 切换区域,中国区保留 appStore(更新)--自 2018 年 2 月 28 日起,中国区 iCloud 由云上贵州管理 苹果公司发布的公告 https://support.apple.com/zh-cn/HT208352 关键词 关键部分 受影响的 iCloud 账户:国家或地区设置为 "中国 "的 Apple ID。 iCloud 包含的服务照片、邮件、通讯录、日历、提醒事项、备忘、书签、钱包、钥匙串、云备份、云驱动器、应用程序数据 新条款和条件: 同意仅出于本协议允许的目的并在中国法律允许的范围内使用服务。 云桂洲在提供服务时应使用合理的技能并尽职尽责,但在适用法律允许的最大范围内,我们不保证或担保您通过本服务存储或访问的任何内容不会意外损坏、崩溃、丢失或根据本协议的条款被删除,如果发生此类损坏、崩溃、丢失或删除,我们不承担任何责任。您应自行负责维护您的信息和数据的适当备份。 Apple 和云上贵州有权访问您存储在服务中的所有数据,包括有权根据适用法律相互之间共享、交换和披露所有用户数据(包括内容)。 本协议的解释、效力和履行应适用*法律。对于因本协议引起的或与本协议有关的任何争议,云桂洲和您同意提交中国国际经济贸易仲裁委员会(CIETAC)根据提交仲裁时有效的法律在北京进行具有约束力的仲裁。 由云桂洲管理,用户选择: 停用; ID 到地区; 受 iCloud(由云桂洲运营)条款和条件约束 首先,我想说说我对数据安全的看法。 当我在朋友圈发布通知时,有些朋友回复说国外的操作并没有多安全,或者国外的安全只是相对于国外而言的等等。首先,我非常感谢这些朋友,这让我反思什么是数据安全。以下观点均属个人观点: 国外的月亮一定比国内圆? 这是一个根深蒂固的问题,只要有人说国外的东西比国内好,就会有人嘲笑崇洋媚外。我觉得我们在某些方面应该向国外学习,比如搜索引擎和版权问题。打开百度搜索 "数据安全",第一行肯定是广告。打开谷歌搜索 "数据安全",第一条就是 "数据安全_百度百科" .....各种版权问题大家都明白,支持正版,但不仅客户一心想找免费破解,就连作者也往往没有保护自己劳动成果或产品的想法。但从另一个层面来说,国内的发展和安全,甩国外几条街。没有说哪里好,哪里不好,辩证地去学习更好。 国外也有别有用心的数据泄露,谈何安全? 从加密解密的角度看,自古以来就没有绝对安全的加密,只有相对安全的做法。苹果的棱镜门、微软的 cpu 漏洞,各种参差不齐的被破解案例 ....是的,这的确是一个很好的论据,但凡事都不能只看一面,当年苹果面对FBI破解手机的要求,几经论证,苹果还是拒绝破解。这点拿到国内,只要上面的文件传达下去,还有企业敢说不吗?还敢说不吗? 关于这次iCloud数据迁移个人看法? 把数据迁移到贵州的云端,相当于把手机的所有数据都存储在贵州的云端服务器上。也许访问数据的速度会快很多,但我会把我的iCloud区放到美国,因为我不想数据存在云上贵州后经常接到莫名其妙的电话或短信,更不想因为乱用国外服务器而被请去喝茶。iCloud一个ID,即从中国账号转到美国区,主要用于数据存在美国服务器上。appStore一个ID,除了注册一个中国ID外,专门用来下载应用用,因为国外ID不支持酷狗和网易云等应用。麻烦的是,用了新的 appStore ID 后,当前的应用还得重新下载安装,因为旧的应用 ID 与新的应用 ID 不兼容,安装不了。最后,iCloud迁移后,国内用户使用美国服务器,估计要 "扶墙 "了。 专业步骤: 首先,进行appleID设置,这是前提条件,否则无法选择转移区域! 取消 appleID 的双重认证 取消家庭共享选项 二、窗口下载并安装 icloud 3.0 版
-
[姿势估计] 实践记录:使用 Dlib 和 mediapipe 进行人脸姿势估计 - 本文重点介绍方法 2):方法 1:基于深度学习的方法:。 基于深度学习的方法:基于深度学习的方法利用深度学习模型,如卷积神经网络(CNN)或递归神经网络(RNN),直接从人脸图像中学习姿势估计。这些方法能够学习更复杂的特征表征,并在大规模数据集上取得优异的性能。方法二:基于二维校准信息估计三维姿态信息(计算机视觉 PnP 问题)。 特征点定位:人脸姿态估计的第一步是通过特征点定位来检测和定位人脸的关键点,如眼睛、鼻子和嘴巴。这些关键点提供了人脸的局部结构信息,可用于后续的姿势估计。 旋转表示:常见的旋转表示方法包括欧拉角和旋转矩阵。欧拉角通过三个旋转角度(通常是俯仰、偏航和滚动)描述头部的旋转姿态。旋转矩阵是一个 3x3 矩阵,表示头部从一个坐标系到另一个坐标系的变换。 三维模型重建:根据特征点的定位结果,三维人脸模型可用于姿势估计。通过将人脸的二维图像映射到三维模型上,可以估算出人脸的旋转和平移信息。这就需要建立人脸的三维模型,然后通过优化方法将模型与特征点对齐,从而获得姿势估计结果。 特征点定位 特征点定位是用于检测人脸关键部位的五官基础部分,还有其他更多的特征点表示方法,大家可以参考我上一篇文章中介绍的特征点检测方案实践:人脸校正二次定位操作来解决人脸校正的问题,客户在检测关键点的代码上略有修改,坐标转换部分客户见上图 def get_face_info(image). img_copy = image.copy image.flags.writeable = False image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) results = face_detection.process(image) # 在图像上绘制人脸检测注释。 image.flags.writeable = True image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) box_info, facial = None, None if results.detections: for detection in results. for detection in results.detections: mp_drawing.Drawing.detection = 无 mp_drawing.draw_detection(image, detection) 面部 = detection.location_data.relative_keypoints 返回面部 在上述代码中,返回的数据是五官(6 个关键点的坐标),这是用 mediapipe 库实现的,下面我们可以尝试用另一个库:dlib 来实现。 使用 dlib 使用 Dlib 库在 Python 中实现人脸关键点检测的步骤如下: 确保已安装 Dlib 库,可使用以下命令: pip install dlib 导入必要的库: 加载 Dlib 的人脸检测器和关键点检测器模型: 读取图像并将其灰度化: 使用人脸检测器检测图像中的人脸: 对检测到的人脸进行遍历,并使用关键点检测器检测人脸关键点: 显示绘制了关键点的图像: 以下代码将参数 landmarks_part 添加到要返回的关键点坐标中。
-
平滑处理在眼动跟踪数据分析中的应用
-
基于 NFC 的无线电池管理 BMS - ● 主动读取内部传感器:利用 NFC 技术,BMS 能够主动读取内部传感器的数据 [... 考虑车辆外使用案例中的空闲状态场景:NFC 技术可用于处理闲置状态下的电池组读取,例如在第二次生命转移期间进行存储。 主动诊断读取:在邻近系统中部署了 BMS 的情况下,使用 NFC 技术进行主动诊断读取。 (ii) 系统结构 系统架构如图所示,在建立安全通道之前,需要对设备进行身份验证。数据链路通信层由 NDEF 记录处理,而数据存储可以是离线的,也可以是数据库中的在线存储。活动和空闲状态的诊断读数取决于设备和数据方向,需要与外部 NFC 阅读器进行通信。软件架构分为三层,包括硬件抽象层(HAL)、中间层(中间件)和应用层。HAL 处理硬件驱动组件,中间件执行设备验证,而应用层则由开发人员根据安全漏洞和格式扩展*定义。 为确保安全,系统采用了一个安全模型,为 BMS 和主动诊断读取情况格式化应用数据。安全考虑因素包括设备相互验证、使用安全通道(加密和防篡改)以及确保电池组内读数的安全。 考虑到不同的 BMS 拓扑,包括集中式、调制式、分布式和分散式,系统需要满足设备相互验证和使用安全通道的要求。对于每种拓扑结构,都必须考虑将性能开销降至最低。电池是封闭的,对其进行物理攻击不可行或成本太高。外部攻击可能也很困难。基于对称或非对称加密技术的自动验证可用于保护电池组读数。安全协议在验证阶段和会话密钥确认阶段采用双密钥加密,以抵御攻击。中间件在数据格式验证、确认和处理中发挥关键作用,确保数据传输安全。 (iii) 唤醒模型设计
-
详细介绍 CNN 卷积层的原理、结构和应用,讨论其在图像处理和计算机视觉任务中的重要性