OpenCV中的矩阵操作

news2025/4/16 17:01:03

        OpenCV中的矩阵操作主要围绕Mat类展开,涵盖创建、访问、运算及变换等。

1. 创建矩阵

  • 零矩阵/单位矩阵‌:
    Mat zeros = Mat::zeros(3, 3, CV_32F); // 3x3浮点零矩阵
    Mat eye = Mat::eye(3, 3, CV_32F);      // 3x3单位矩阵
  • 自定义初始化‌:
    Mat A = (Mat_<float>(3,3) << 1,2,3,4,5,6,7,8,9);

2. 访问与修改元素

  • 使用at方法‌(注意数据类型):
    float elem = A.at<float>(0,0); // 访问(0,0)元素
    A.at<float>(1,1) = 10;         // 修改(1,1)元素
  • 多通道矩阵‌(如RGB图像):
    Vec3b pixel = img.at<Vec3b>(i,j); // 获取三通道像素值
    pixel = 255;                   // 修改蓝色通道,实际上取的pixel[0]
    pixel[0] = 255;                // 修改蓝色通道
    pixel[1] = 255;                // 修改绿色通道  
    pixel[2] = 255;                // 修改红色通道
    
    img.at<Vec3b>(14,25) [0]= 25;//B    
    img.at< Vec3b >(14,25) [1]= 25;//G    
    img.at< Vec3b >(14,25 [2]= 25;//R 
  • 使用ptr方法:
    Mat a(Size(720,1024),CV_8UC3);
    for(int i=0;i<a.rows;i++){
          for(int j=0;j<a.cols;j++){
              a.ptr(i,j)[0]=0;
              a.ptr(i,j)[1]=0;
              a.ptr(i,j)[2]=255;
          }
    }
    for(int i=0;i<a.rows;i++){
          for(int j=0;j<a.cols;j++){
              a.ptr<Vec3b>(i,j)[0]=0;
              a.ptr<Vec3b>(i,j)[1]=0;
              a.ptr<Vec3b>(i,j)[2]=255;
          }
    }
  • 迭代器访问元素:
    Mat a(Size(720,1024),CV_8UC3);
    for(auto iter=a.begin<Vec3b>();iter!=a.end<Vec3b>();iter++){
          iter[0]=255;
          iter[1]=0;
          iter[2]=0;
    }

3. 矩阵运算

  • 基本运算‌(需尺寸/类型一致):
    使用"+"和"-"符号进行矩阵加减运算。

  • cv::Mat a= Mat::eye(Size(3,2), CV_32F);
    cv::Mat b= Mat::ones(Size(3,2), CV_32F);
    cv::Mat c= a+b;
    cv::Mat d= a-b;
  • 矩阵乘法(A*B)‌:
    使用"*"号计算矩阵与标量相乘,矩阵与矩阵相乘。 A*B是以数学运算中矩阵相乘的方式实现的,即Mat矩阵A和B被当做纯粹的矩阵做乘法运算,这就要求A的列数等       于B的行数时,才能定义两个矩阵相乘。如A是m×n矩阵,B是n×p矩阵,它们的乘积AB是一个m×p矩阵。

    另外:参与点乘的两个Mat矩阵的数据类型(type)只能是 CV_32F、 CV_64FC1、 CV_32FC2、 CV_64FC2 这4种类        型中的一种。若选用其他类型,比如CV_8UC1,编译器会报错。
    #include "core/core.hpp"     
    #include "iostream"  
     
    using namespace std;   
    using namespace cv;  
     
    int main(int argc,char *argv[])    
    { 
    	Mat A=Mat::ones(2,3,CV_32FC1);
    	Mat B=Mat::ones(3,2,CV_32FC1);
    	Mat AB;
     
    	A.at<float>(0,0)=1;
    	A.at<float>(0,1)=2;
    	A.at<float>(0,2)=3;
    	A.at<float>(1,0)=4;
    	A.at<float>(1,1)=5;
    	A.at<float>(1,2)=6;
     
    	B.at<float>(0,0)=1;
    	B.at<float>(0,1)=2;
    	B.at<float>(1,0)=3;
    	B.at<float>(1,1)=4;
    	B.at<float>(2,0)=5;
    	B.at<float>(2,1)=6;
     
    	AB=A*B;
     
    	cout<<"A=\n"<<A<<endl<<endl;
    	cout<<"B=\n"<<B<<endl<<endl;
    	cout<<"AB=\n"<<AB<<endl<<endl;
     
    	system("pause");
    }
  • 矩阵dot
    Opencv中.dot操作才算得上是真正的“点乘”,A.dot(B)操作相当于数学向量运算中的点乘,也叫向量的内积、数量积。
        double dot(InputArray m) const;

    dot说明:

    1).  对两个向量执行点乘运算,就是对这两个向量对应位一一相乘之后求和的操作,点乘的结果是一个标量。   

    对于向量a和向量b:

    a和b的点积公式为:

    要求向量a和向量b的行列数相同。

    Mat矩阵的dot方法扩展了一维向量的点乘操作,把整个Mat矩阵扩展成一个行(列)向量,之后执行向量的点乘运算,仍然要求参与dot运算的两个Mat矩阵的行列数完全一致。

    2).  dot方法声明中显示返回值是double,所以A.dot(B)结果是一个double类型数据,不是Mat矩阵,不能把A.dot(B)结果赋值给Mat矩阵。

    #include "core/core.hpp"     
    #include "iostream"  
     
    using namespace std;   
    using namespace cv;  
     
    int main(int argc,char *argv[])    
    { 
    	Mat A=Mat::ones(2,3,CV_8UC1);
    	Mat B=Mat::ones(2,3,CV_8UC1);
     
    	A.at<uchar>(0,0)=1;
    	A.at<uchar>(0,1)=2;
    	A.at<uchar>(0,2)=3;
    	A.at<uchar>(1,0)=4;
    	A.at<uchar>(1,1)=5;
    	A.at<uchar>(1,2)=6;
     
    	B.at<uchar>(0,0)=1;
    	B.at<uchar>(0,1)=2;
    	B.at<uchar>(0,2)=3;
    	B.at<uchar>(1,0)=4;
    	B.at<uchar>(1,1)=5;
    	B.at<uchar>(1,2)=6;
     
    	double AB=A.dot(B);
     
    	cout<<"A=\n"<<A<<endl<<endl;
    	cout<<"B=\n"<<B<<endl<<endl;
    	cout<<"double类型的AB=\n"<<AB<<endl<<endl;
     
    	system("pause");
    }
  • 矩阵mul(元素乘法)
    Opencv中mul会计算两个Mat矩阵对应位的乘积,所以要求参与运算的矩阵A的行列和B的行列数一致。计算结果是跟A或B行列数一致的一个Mat矩阵。
        MatExpr mul(InputArray m, double scale=1) const;
    以简单的情况为例,对于2*2大小的Mat矩阵A和B:
  • 对A和B执行mul运算:

    mul说明:
    1).  mul操作不对参与运算的两个矩阵A、B有数据类型上的要求,但要求A,B类型一致,不然报错。

    2).  Mat AB=A.mul(B),若声明AB时没有定义AB的数据类型,则默认AB的数据类型跟A和B保存一致。

    3).  若AB精度不够,可能产生溢出,溢出的值被置为当前精度下的最大值。

    #include "core/core.hpp"     
    #include "iostream"  
     
    using namespace std;   
    using namespace cv;  
     
    int main(int argc,char *argv[])    
    { 
    	Mat A=Mat::ones(2,3,CV_8UC1);
    	Mat B=Mat::ones(2,3,CV_8UC1);
     
    	A.at<uchar>(0,0)=60;
    	A.at<uchar>(0,1)=2;
    	A.at<uchar>(0,2)=3;
    	A.at<uchar>(1,0)=4;
    	A.at<uchar>(1,1)=5;
    	A.at<uchar>(1,2)=6;
     
    	B.at<uchar>(0,0)=60;
    	B.at<uchar>(0,1)=2;
    	B.at<uchar>(0,2)=3;
    	B.at<uchar>(1,0)=4;
    	B.at<uchar>(1,1)=5;
    	B.at<uchar>(1,2)=6;
     
    	Mat AB=A.mul(B);
     
    	cout<<"A=\n"<<A<<endl<<endl;
    	cout<<"B=\n"<<B<<endl<<endl;
    	cout<<"AB=\n"<<AB<<endl<<endl;
     
    	system("pause");
    }
  • 矩阵转置
    矩阵转置是将矩阵的行与列顺序对调(第i行转变为第i列)形成一个新的矩阵。OpenCV通过Mat类的t()函数实现。
    / 转置
        Mat m1= Mat::eye(2,3, CV_32F);    
        Mat m1t = m1.t();
        cout<<"m1  = "<<endl<<m1<<endl<<endl;
        cout<<"m1t  = "<<endl<<m1t<<endl<<endl;
  • 矩阵求逆
    逆矩阵在某些算法中经常出现,在OpenCV中通过Mat类的inv()方法实现。
    // 求逆
    Mat meinv = me.inv();
    cout<<"me  = "<<endl<<me<<endl<<endl;
    cout<<"meinv = "<<endl<<meinv<<endl<<endl;

4. 矩阵扩展方法

  •  计算矩阵非零元素个数
    计算物体的像素或面积常需要用到计算矩阵中的非零元素个数,OpenCV中使用countNonZero()函数实现。
    // 非零元素个数
    int nonZerosNum = countNonZero(me); // me为输入矩阵或图像
    cout<<"me  = "<<endl<<me<<endl;
    cout<<"me中非零元素个数 = "<<nonZerosNum<<endl<<endl;
  • 归一化

    函数:
    void cv::normalize( InputArray src, OutputArray dst, double alpha = 1, double beta = 0, int norm_type = NORM_L2, int dtype = -1, InputArray mask = noArray() );
    
    参数:
    src (InputArray): 输入数组或图像,通常为单通道或多通道的矩阵(如 cv::Mat 类型)。这是需要被标准化的源数据。
    dst (OutputArray): 输出标准化后的数组或图像。大小和类型取决于输入和参数设置。
    alpha (double): 归一化后的最小值或缩放系数,具体含义取决于 norm_type。如果选择了 NORM_MINMAX,alpha 表示归一化后数据的最小值。如果是 NORM_L2、NORM_L1 或 NORM_INF,alpha 是缩放的目标值。
    beta (double): 归一化后的最大值,当 norm_type 为 NORM_MINMAX 时有效。这个参数只会在该类型下使用,以设置归一化后的最大值。
    norm_type (int): 归一化的类型。常见的有以下几种:
    NORM_INF: 将数组的每个元素除以绝对值的最大值。
    NORM_L1: 将数组的每个元素除以元素绝对值之和。
    NORM_L2: 将数组的每个元素除以元素平方和的平方根(欧几里得范数)。
    NORM_MINMAX: 线性缩放,使得数组的最小值和最大值分别为 alpha 和 beta。
    dtype (int): 输出数据类型。如果设置为 -1,则输出与输入类型相同。否则,可以显式指定输出类型(如 CV_32F、CV_8U 等)。
    mask (InputArray): 可选的掩码数组(通常是二值图像)。只对掩码中为非零的像素进行标准化处理。
    返回值:
    该函数没有返回值,但它会通过 dst 输出标准化后的结果。
    cv::Mat src = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);
    cv::Mat dst;
    
    // 将图像归一化到 [0, 255] 范围内
    cv::normalize(src, dst, 0, 255, cv::NORM_MINMAX);
  • 变形

    函数:
    C++: Mat Mat::reshape(int cn, int rows=0) const
    参数:

    cn: 表示通道数(channels), 如果设为0,则表示保持通道数不变,否则则变为设置的通道数。rows: 表示矩阵行数。 如果设为0,则表示保持原有的行数不变,否则则变为设置的行数。
     

    int main()
    {
        Mat data = Mat(20, 30, CV_32F);  //设置一个20行30列1通道的一个矩阵
        cout << "行数: " << data.rows << endl;
        cout << "列数: " << data.cols << endl;
        cout << "通道: " << data.channels() << endl;
        cout << endl;
        
        Mat dst = data.reshape(0, 1);//通道数不变,将矩阵序列化1行N列的行向量
        cout << "行数: " << dst.rows << endl;
        cout << "列数: " << dst.cols << endl;
        cout << "通道: " << dst.channels() << endl;
        system("pause");
        return 0;
    }
  • 计算两个矩阵之间的差异或误差
    函数:
    
    // 单数组范数
    double cv::norm(InputArray src, int normType = NORM_L2, InputArray mask = noArray());
    
    // 两数组差异范数
    double cv::norm(InputArray src1, InputArray src2, int normType = NORM_L2, InputArray mask = noArray());
    
    参数:
    src1和src2是输入的数组,可以是 cv::Mat 或 cv::Mat_<T> 类型的对象。它可以是一维或多维数组。
    normType 是一个可选参数,用于指定计算范数的类型。常见的取值为 NORM_L1、NORM_L2、NORM_INF,分别表示计算 L1 范数、L2 范数和无穷范数。默认值为 NORM_L2。
    对不同范数类型的解释:
    NORM_L1:计算 L1 范数,也称为曼哈顿范数。对于一维数组,它表示数组中所有元素的绝对值之和。对于多维数组,它表示所有元素绝对值之和的最大值。
    NORM_L2:计算 L2 范数,也称为欧几里得范数。对于一维数组,它表示数组中所有元素的平方和的平方根。对于多维数组,它表示所有元素平方和的平方根。
    NORM_INF:计算无穷范数,也称为最大绝对值范数。对于一维数组,它表示数组中绝对值最大的元素的绝对值。对于多维数组,它表示所有元素绝对值的最大值。
    mask 是一个可选的掩码数组,用于指定哪些元素应该包含在范数计算中。它必须与 src 的尺寸相同,且类型为 CV_8UC1 或 CV_8SC1。
  • 矩阵的全局最大最小值
    求输入矩阵的全局最大最小值及其位置,可使用函数:
    void minMaxLoc(InputArray src, CV_OUT double* minVal,
                               CV_OUT double* maxVal=0, CV_OUT Point* minLoc=0,
                               CV_OUT Point* maxLoc=0, InputArray mask=noArray());

    参数:
    src – 输入单通道矩阵(图像).
    minVal – 指向最小值的指针, 如果未指定则使用NULL
    maxVal – 指向最大值的指针, 如果未指定则使用NULL
    minLoc – 指向最小值位置(2维情况)的指针, 如果未指定则使用NULL
    maxLoc – 指向最大值位置(2维情况)的指针, 如果未指定则使用NULL
    mask – 可选的蒙版,用于选择待处理子区域

    // 求极值 最大、最小值及其位置
        Mat img = imread("Lena.jpg",0);
        imshow("original image",img);
    
        double minVal=0,maxVal=0;
        cv::Point minPt, maxPt;
        minMaxLoc(img,&minVal,&maxVal,&minPt,&maxPt);
        cout<<"min value  = "<<minVal<<endl;
        cout<<"max value  = "<<maxVal<<endl;
        cout<<"minPt = ("<<minPt.x<<","<<minPt.y<<")"<<endl;
        cout<<"maxPt = ("<<maxPt.x<<","<<maxPt.y<<")"<<endl;
        cout<<endl;
    
        cv::Rect rectMin(minPt.x-10,minPt.y-10,20,20);
        cv::Rect rectMax(maxPt.x-10,maxPt.y-10,20,20);
    
        cv::rectangle(img,rectMin,cv::Scalar(200),2);
        cv::rectangle(img,rectMax,cv::Scalar(255),2);
    
        imshow("image with min max location",img);
        cv::waitKey();

5. 矩阵切片与ROI

  • 获取子矩阵
    Mat roi = A(Rect(0,0,2,2));   // 左上角2x2区域
    Mat rows = A.rowRange(0,2);   // 前两行
  • 矩阵的ROI(感兴趣区域)
    在OpenCV中,矩阵的ROI(Region of Interest,感兴趣区域)指的是在原矩阵中指定的一块区域。你可以从这个区域中提取数据,或者在不影响原矩阵的情况下对这个区域进行操作。
    要设置ROI,你可以使用cv::Rect对象来定义感兴趣区域的坐标和大小,然后使用Mat::operator()来访问这个区域。

    // 定义ROI
    cv::Rect roi(x, y, width, height);  // x, y 是左上角的坐标,width 和 height 是区域的宽度和高度
     
    // 使用ROI
    cv::Mat submat = image(roi);

    一旦你有了ROI的引用(如submat),你就可以像操作普通矩阵一样操作它了。任何对submat的修改都不会影响原始的image矩阵,除非你明确地复制了这些修改。

    // 例如,将ROI区域内的所有像素值设置为0
    submat = cv::Scalar(0, 0, 0);  // 对于彩色图像,三个通道都需要设置为0

    如果你希望保留原始图像不变,同时又想在其他地方使用修改后的ROI,你可以将submat复制到一个新的矩阵。

    cv::Mat newImage = image.clone();  // 克隆原始图像以保留原始数据
    newImage(roi) = submat.clone();    // 将修改后的ROI复制到新图像的相应位置

6. Mat深拷贝

在OpenCV中,cv::Mat对象通常用于存储图像数据。当你创建一个cv::Mat对象并将其赋值给另一个cv::Mat对象时,默认情况下是浅拷贝(shallow copy),这意味着两个对象指向相同的内存地址。如果你修改了任一对象的内存内容,另一个对象的内存内容也会相应改变,这可能导致不可预期的行为或错误。
如何进行深拷贝?
方法1:使用cv::Mat::clone()
这是进行深拷贝的最直接方法。clone()方法会创建一个新的cv::Mat对象,并复制原始矩阵的数据到一个全新的内存区域。

cv::Mat original = cv::imread("path_to_image.jpg");
cv::Mat copy = original.clone();
 
// 现在,original和copy指向不同的内存区域,修改它们不会相互影响。

方法2:使用cv::Mat::copyTo()
另一个方法是使用copyTo()方法,这也可以用来创建数据的深拷贝。

cv::Mat original = cv::imread("path_to_image.jpg");
cv::Mat copy;
original.copyTo(copy);
 
// 现在,original和copy也是独立的,修改它们不会相互影响。

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

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

相关文章

OAK相机入门(一):深度测距原理

文章目录 1. 测距参数介绍2. 测距原理3. 总结 官方文档 Configuring Stereo Depth 1. 测距参数介绍 理论范围&#xff1a;0.2-35m 推荐范文&#xff1a;不低于0.5m 存储类型&#xff1a;uint16&#xff0c;0代表没有数据&#xff0c;或者测不到 2. 测距原理 通过视差进行测距…

Powershell WSL .wslconfig 实现与宿主机的网络互通

前言.wslconfig .wslconfig 用于在 WSL 2 上运行的所有已安装发行版中配置全局设置 wsl 2 网络模式介绍 Bridged (外部): 桥接模式将虚拟机的网络连接直接桥接到物理网络适配器上Mirrored (镜像): 镜像模式并不是一个标准的 Hyper-V 网络类型,但它通常指的是在网络适配器级…

Vue:Vue2和Vue3创建项目的几种常用方式以及区别

前言 Vue.js 和 Element UI 都是用 JavaScript 编写的。 1、Vue.js 是一个渐进式 JavaScript 框架。2、Element UI 是基于 Vue.js 的组件库。3、JavaScript 是这两个项目的主要编程语言。 而Element Plus是基于TypeScript开发的。 一、Vue2 1、基于vuecli工具创建 vue2 …

IRF拆除

冗余口、冗余组、备份组、虚墙、MAD检测、被控制器纳管、转换为安全策略 黑洞路由的定义: 有来无回的路由。 对设备拆除IRF操作流程。 1、关闭主框的业务口&#xff08;对设备的接口使用shutdown&#xff09;&#xff0c;关闭MAD检测口&#xff08;BFD/NQA/MAD&#xff09;&…

强化学习(赵世钰版)-学习笔记(8.值函数方法)

本章是算法与方法的第四章&#xff0c;是TD算法的拓展&#xff0c;本质上是将状态值与行为值的表征方式&#xff0c;从离散的表格形式&#xff0c;拓展到了连续的函数形式。 表格形式的优点是直观&#xff0c;便于分析&#xff0c;缺点是数据量较大或者连续性状态或者行为空间时…

STM32F4与串口屏通信

淘晶池串口屏操作指令集 那我们就来谈一谈串口屏与STM32F4嵌入式板子的通信 第一&#xff0c;串口屏传输数据给F4板子 这时&#xff0c;我们就该来谈一谈prints函数和printh函数的用法 prints att,length att:变量名称 length:长度(0为自动长度) printh hex hex:需要发送的…

车载以太网网络测试-20【传输层-DOIP协议-3】

1 摘要 本文继续对ISO 13400-2定义的节点管理报文进行介绍&#xff0c;主要对路由激活请求/响应报文以及在线检查请求/响应报文的作用、帧结构以及示例进行介绍。 上文回顾&#xff1a; 车载以太网网络测试-19【传输层-DOIP协议-2】 在进行详细介绍之前&#xff0c;还是先回顾…

`chromadb` 是什么

chromadb 是什么 chromadb 是一个开源的向量数据库,它专门用于存储、索引和查询向量数据。在处理自然语言处理(NLP)、计算机视觉等领域的任务时,通常会将文本、图像等数据转换为向量表示,而 chromadb 可以高效地管理这些向量,帮助开发者快速找到与查询向量最相似的向量数…

关于“碰一碰发视频”系统的技术开发文档框架

以下是关于“碰一碰发视频”系统的技术开发文档框架&#xff0c;涵盖核心功能、技术选型、开发流程和关键模块设计&#xff0c;帮助您快速搭建一站式解决方案 --- 随着短视频平台的兴起&#xff0c;用户的创作与分享需求日益增长。而如何让视频分享更加便捷、有趣&#xff0c…

vue3之写一个aichat---已聊天组件部分功能

渲染聊天数据 这个不必多说&#xff0c;直接从stores/chat中取出聊天列表数据渲染就好&#xff0c;因为前面添加的消息都是按照用户消息、AI助手消息这样添加的&#xff0c;效果如图 但是需要注意每条助手消息的状态&#xff0c;需要根据状态显示不同的图标或不显示图标&…

基于STC89C51的太阳自动跟踪系统的设计与实现—单片机控制步进电机实现太阳跟踪控制(仿真+程序+原理图+PCB+文档)

摘 要 随着我国经济的飞速发展&#xff0c;促使各种能源使用入不敷出&#xff0c;尤其是最主要的能源&#xff0c;煤炭石油资源不断消耗与短缺&#xff0c;因此人类寻找其他替代能源的脚步正在加快。而太阳能则具有无污染﹑可再生﹑储量大等优点&#xff0c;且分布范围广&…

第五: redis 安装 / find 查找目录

redis 安装的 两种方式&#xff1a; mac上安装redis的两种方法_如何在mac上安装redis-CSDN博客 首先可以先看一下brew的常用命令如下&#xff1a; brew search ** //查找某个软件包 brew list //列出已经安装的软件的包 brew install ** //安装某个软件包,默认安装的是…

Springboot 项目如何输出优雅的日志

我们先看效果图&#xff1a; 我个人比较喜欢这种格式的日志输出&#xff0c;对其完整&#xff1b; 这种格式其实就是默认的&#xff0c;不需要大家配置任何的 logback-spring 文件和xml中配置日志level 没有做任何多余的配置&#xff1b;

Linux——进程(5)进程地址空间

先看一个程序和现象 预期现象是&#xff0c;子进程和父进程相互独立&#xff0c;子进程的gval是100&#xff0c;101&#xff0c;102....而父进程一直都是100. 结果我们并不意外&#xff0c;只是我们发现&#xff0c;父子进程的gval的地址是一样的&#xff0c;这有点颠覆我们的认…

代码随想录_动态规划

代码随想录 动态规划 509.斐波那契数 509. 斐波那契数 斐波那契数 &#xff08;通常用 F(n) 表示&#xff09;形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始&#xff0c;后面的每一项数字都是前面两项数字的和。也就是&#xff1a; F(0) 0&#xff0c;F(1) 1 F(n…

星越L_陡坡缓降使用讲解

目录 1.陡坡缓降 1.陡坡缓降 中控屏下滑-点击陡坡缓降功能 35km/h以下时生效。35km/h-60km/h该功能暂停 60km/h以上该功能关闭

XSS跨站脚本攻击漏洞(Cross Site Scripting)

前提概要 本文章主要用于分享XSS跨站脚本攻击漏洞基础学习&#xff0c;以下是对XSS跨站脚本攻击漏洞的一些个人解析&#xff0c;请大家结合参考其他文章中的相关信息进行归纳和补充。 XSS跨站脚本攻击漏洞描述 跨站脚本攻击&#xff08;XSS&#xff09;漏洞是一种常见且危害较…

html5基于Canvas的经典打砖块游戏开发实践

基于Canvas的经典打砖块游戏开发实践 这里写目录标题 基于Canvas的经典打砖块游戏开发实践项目介绍技术栈核心功能实现1. 游戏初始化2. 游戏对象设计3. 碰撞检测系统4. 动画系统5. 用户界面设计 性能优化1. 渲染优化2. 内存管理 项目亮点技术难点突破项目总结 项目介绍 在这个…

企业信息化的“双螺旋”——IT治理和数据治理

企业信息化的“双螺旋”——IT治理和数据治理 一、核心定义二、关键差异三、内在联系四、实践挑战与融合路径五、行业案例参考六、结论数据治理(Data Governance)和IT治理(IT Governance)是现代企业数字化转型中的关键概念,二者既有紧密关联又各有侧重。以下从定义、核心内…

CCBCISCN复盘

AWDP – ccfrum 自己搭了一下环境, 复现一下这道题目, 之前比赛的时候完全没想到这个漏洞要怎么打, 修也不知道要怎么修, 就仅仅是对用户名的账号和密码进行了一下过滤, 完全没起到作用, 唉, 实在太菜 如果想要尝试复现的话可以尝试拉取这个镜像, 我打完之后就直接把这个容器给…