OpenCV 笔记(2):图像的属性以及像素相关的操作

news2024/11/18 22:37:53

Part11.  图像的属性

11.1 Mat 的主要属性

在前文中,我们大致了解了 Mat 的基本结构以及它的创建与赋值。接下来我们通过一个例子,来看看 Mat 所包含的常用属性。

先创建一个 3*4 的四通道的矩阵,并打印出其相关的属性,稍后会详细解释每个属性的含义。

Mat srcImage(3, 4, CV_16UC4, Scalar_<uchar>(1, 2, 3, 4));

cout << srcImage << endl;

cout << "dims:" << srcImage.dims << endl;
cout << "rows:" << srcImage.rows << endl;
cout << "cols:" << srcImage.cols << endl;
cout << "channels:" << srcImage.channels() << endl;
cout << "type:" << srcImage.type() << endl;
cout << "depth:" << srcImage.depth() << endl;
cout << "elemSize:" << srcImage.elemSize() << endl;
cout << "elemSize1:" << srcImage.elemSize1() << endl;
cout << "step:" << srcImage.step << endl;
cout << "step[0]:" << srcImage.step[0] << endl;
cout << "step[1]:" << srcImage.step[1] << endl;
cout << "step1[0]:" << srcImage.step1(0) << endl;
cout << "step1[1]:" << srcImage.step1(1) << endl;

输出结果:

[1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4;
 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4;
 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
dims:2
rows:3
cols:4
channels:4
type:26
depth:2
elemSize:8
elemSize1:2
step:32
step[0]:32
step[1]:8
step1[0]:16
step1[1]:4

在上述例子中我们打印了 Mat 的很多属性,它们主要包括:

  • rows: 表示图像的高度。

  • cols:表示图像的宽度。

  • dims:表示矩阵的维度。

  • data:表示 Mat 对象中的指针(uchar 类型的指针),指向内存中存放矩阵数据的一块内存 (uchar* data)。

  • channels:表示通道数量;例如常见的 RGB、HSV 彩色图像,则 channels=3;若为灰度图,则 channels=1。

  • depth:表示图像的深度,它用来度量每一个像素中每一个通道的精度,它本身与通道数无关,它的数值越大表示精度越高。

数据类型depth 的值数据类型取值范围对应 C++ 的类型
CV_8U08 位无符号类型0—255uchar,  unsigned char
CV_8S18 位有符号类型-128—127char
CV_16U216 位无符号类型0—65535ushort, unsigned short, unsigned short int
CV_16S316 位有符号类型-32768—32767short, short int
CV_32S432 位整数数据类型-2147483648—2147483647int, long
CV_32F532 位浮点数类型±(1.18e-38……3.40e38)float
CV_64F632 位双精度类型±(2.23e-308……1.79e308)double
  • type:表示矩阵的数据类型,它包含矩阵中元素的类型以及通道数信息。

数据类型1234
CV_8UCV_8UC1CV_8UC2CV_8UC3CV_8UC4
CV_8SCV_8SC1CV_8SC2CV_8SC3CV_8SC4
CV_16UCV_16UC1CV_16UC2CV_16UC3CV_16UC4
CV_16SCV_16SC1CV_16SC2CV_16SC3CV_16SC4
CV_32SCV_32SC1CV_32SC2CV_32SC3CV_32SC4
CV_32FCV_32FC1CV_32FC2CV_32FC3CV_32FC4
CV_64FCV_64FC1CV_64FC2CV_64FC3CV_64FC4
  • elemSize:表示矩阵中每一个元素的数据大小,它与通道数相关,单位是字节。 举几个例子: 如果 Mat 中的数据类型是 CV_8UC1 或 CV_8SC1,那么 elemSize=1(1 * 8 / 8 = 1 bytes); 如果 Mat 中的数据类型是 CV_8UC3 或 CV_8SC3,那么 elemSize=3(3 * 8 / 8 = 3 bytes); 如果 Mat 中的数据类型是 CV_16UC3 或 CV_16SC3,那么 elemSize=6(3 * 16 / 8 = 6 bytes); 如果 Mat 中的数据类型是 CV_32SC3 或 CV_32FC3,那么 elemSize=12(3 * 32 / 8 = 12 bytes);

  • elemSize1:表示矩阵中每一个元素单个通道的数据大小,单位是字节。满足:

  • step: 字面意思是“步长”,实际上它描述了矩阵的形状。 step[] 为一个数组,矩阵有几维,step[] 数组就有几个元素。以一个三维矩阵为例,step[0] 表示一个平面的字节总数,step[1] 表示一行元素的字节总数,step[2] 表示每一个元素的字节总数。

在 OpenCV 的官方文档中,关于解释 step 时曾提到矩阵数据元素

的地址

对于我们常用的二维数组,上述公式可化简为:

这里的 step[0] 表示一行元素的字节总数,step[1] 表示每一个元素的字节总数。

b0ec7e951bab533cd242f5163b09871c.jpeg
mat.png
  • step1:  step1 也是一个数组。step1 不再以字节为单位,而是以 elemSize1 为单位,满足:

Part22. 图像的像素操作

22.1 像素的类型

我们最常用的图像是二维数组,灰度图像(CV_8UC1)会存放 C++ 的 uchar 类型,RGB 彩色图像一般会存放 Vec3b 类型。

其中,单通道数据存放格式:061bed490799cb6ea99a30e4dfa20705.jpeg

三通道数据存放格式:cf92ff6d908931eaf945c6f308bb2f13.jpeg

对于彩色图像而言,在 OpenCV 中通道的顺序是 B、G、R,这跟我们通常所说的 RGB 三原色正好相反。

当然,灰度图像也不一定都是 CV_8UC1 类型,也可能是 CV_16SC1、CV_32FC1 等,它们会存放 C++ 的 short、float 等基本类型。类似地,彩色图像也可能是 CV_16SC3、CV_32FC3 等,那它们是怎么存放的呢?

OpenCV 定义了一系列的 Vec 类,它是一个一维的向量,代表像素的类型

typedef Vec<uchar, 2> Vec2b;
typedef Vec<uchar, 3> Vec3b;
typedef Vec<uchar, 4> Vec4b;

typedef Vec<short, 2> Vec2s;
typedef Vec<short, 3> Vec3s;
typedef Vec<short, 4> Vec4s;

typedef Vec<ushort, 2> Vec2w;
typedef Vec<ushort, 3> Vec3w;
typedef Vec<ushort, 4> Vec4w;

typedef Vec<int, 2> Vec2i;
typedef Vec<int, 3> Vec3i;
typedef Vec<int, 4> Vec4i;
typedef Vec<int, 6> Vec6i;
typedef Vec<int, 8> Vec8i;

typedef Vec<float, 2> Vec2f;
typedef Vec<float, 3> Vec3f;
typedef Vec<float, 4> Vec4f;
typedef Vec<float, 6> Vec6f;

typedef Vec<double, 2> Vec2d;
typedef Vec<double, 3> Vec3d;
typedef Vec<double, 4> Vec4d;
typedef Vec<double, 6> Vec6d;

其中 b、s、w、i、f、d 分别表示如下的含义:


数据类型
bunsigned char
sshort int
wunsigned short
iint
ffloat
ddouble

Vec 类又被称为固定向量类,在编译时就知道向量的大小。类似 Vec 这样的类还有:Matx、Point、Size、Rect

我们用一张表,总结一下矩阵中的数据类型和像素的类型的对应关系:

数据类型C1C2C3C4C6
CV_8UucharVec2bVec3bVec4b
CV_8ScharVec<char, 2>Vec<char, 3>Vec<char, 4>
CV_16UushortVec2wVec3wVec4w
CV_16SshortVec2sVec3sVec4s
CV_32SintVec2iVec3iVec4i
CV_32FfloatVec2fVec3fVec4fVec6f
CV_64FdoubleVec2dVec3dVec4dVec6d

基于上述表格我们可以回答刚才的问题,CV_16SC3 类型的图像存放的是 Vec3s 类型,CV_32FC3 类型的图像存放的是 Vec3f 类型。

32.2 像素点的读取

Mat 的 at() 函数实现了对矩阵中的某个像素的读写操作

下面的代码展示了 at() 函数对灰度图像像素的读写:

Scalar value = grayImage.at<uchar>(y, x);
Scalar.at<uchar>(y, x) = 128;

三通道彩色的图像的读取:

Vec3b value = image.at<Vec3b>(y, x);

uchar blue = value.val[0];
uchar green = value.val[1];
uchar red = value.val[2];

三通道彩色图像的赋值:

image.at<Vec3b>(y,x)[0]=128;
image.at<Vec3b>(y,x)[1]=128;
image.at<Vec3b>(y,x)[2]=128;

下面的例子结合像素的类型,展示了将加载的图像转换成灰度图像,以及对灰度图像进行取反的操作。

Mat srcImage = imread("/Users/tony/beautiful.jpg");
if (srcImage.empty())
{
    cout << "could not load image ..." << endl;
    return -1;
}
imshow("src", srcImage);

Mat grayImage;
cvtColor(srcImage, grayImage, COLOR_BGR2GRAY); // 灰度处理
imshow("gray",grayImage);

int height = grayImage.rows;
int width  = grayImage.cols;

for (int row=0; row<height; row++)
{
    for (int col=0; col<width; col++)
    {
        int gray = grayImage.at<uchar>(row, col);
        grayImage.at<uchar>(row, col) = 255- gray;
    }
}

imshow("invert", grayImage);
1925bc3571edae4d8e4ecd159d5d671c.jpeg
像素点操作.png

简单提一下,上述例子中 cvtColor() 函数的作用是将图像从一个颜色空间转换到另一个颜色空间。例如,可以将图像从 BGR 色彩空间转换成灰度色彩空间,或者从 BGR 色彩空间转换成 HSV 色彩空间等等。

42.3 图像的遍历

2.3.1 基于数组遍历

前面 2.2 介绍过 at() 函数可以对某个像素进行读写操作,并用例子展示了对单通道进行遍历。

对于三通道的彩色图像可以这样遍历。

for(int i=0;i<srcImage.rows;i++){
    for(int j=0;j<srcImage.cols;j++){
        srcImage.at<Vec3b>(i,j)[0]=...  //B通道
        srcImage.at<Vec3b>(i,j)[1]=...  //G通道
        srcImage.at<Vec3b>(i,j)[2]=...  //R通道
    }
}

2.3.2 基于指针遍历

Mat 类提供了更高效的 ptr() 函数,它可以得到图像任意行首地址

下面的代码,它返回第 i+1 行的首地址,也就是指向第 i+1 行第一个元素的指针。

uchar* data = srcImage.ptr<uchar>(i);

at() 函数跟 ptr() 函数在使用上有一定的区别:

at<类型>(i,j) 

ptr<类型>(i)

当然,使用 ptr()  函数访问某个像素也是可以的,采用如下的方式:

mat.ptr<type>(row)[col]

它返回的是 <> 中的模板类型指针,指向的是第 row+1 行 col+1 列的元素。

对于单通道图像的遍历:

for(int i=0;i<srcImage.rows;i++){
    uchar* data=srcImage.ptr<uchar>(i);
    for(int j=0;j<srcImage.cols;j++){
        data[j]=...
    }
}

对于三通道图像的遍历:

for(int i=0;i<srcImage.rows;i++){
    Vec3b* data=srcImage.ptr<Vec3b>(i);
    for(int j=0;j<srcImage.cols;j++){
        data[j][0]=...  //B通道
        data[j][1]=...  //G通道
        data[j][2]=...  //R通道
    }
}

2.3.3 基于迭代器遍历

C++ STL 对每个集合类都定义了对应的迭代器类,OpenCV 也提供了 cv::Mat 的迭代器类,并且与 C++ STL 中的标准迭代器兼容。

对于单通道图像的遍历:

Mat_<uchar>::iterator begin = srcImage.begin<uchar>();
Mat_<uchar>::iterator end = srcImage.end<uchar>();

for (auto it = begin; it != end; it++)
{
    *it = ...
}

迭代器 Mat_ 是 Mat 的模版子类,它重载了 operator() 让我们可以更方便的取图像上的点。类似的迭代器还有 Matlterator_。

对于三通道图像的遍历:

Mat_<cv::Vec3b>::iterator begin = srcImage.begin<cv::Vec3b>();
Mat_<cv::Vec3b>::iterator end = srcImage.end<cv::Vec3b>();

for (auto it = begin; it != end; it++)
{
    (*it)[0] = ... //B通道
    (*it)[1] = ... //G通道
    (*it)[2] = ... //R通道
}

使用迭代器遍历图像会便捷一些,但是效率没有使用指针的效率高。

52.3.4 基于 LUT 遍历

LUT (LOOK -UP-TABLE) 意为查找表。

在数据结构中,查找表是由同一类型的 数据元素 构成的集合,它是一种以查找为“核心”,同时包括其他运算的非常灵活的数据结构。

在图像处理中,经常会通过事先建立一张查找表对图像进行映射。

例如,将灰度图由某个区间映射到另一个区间,或者将单通道映射到三通道。它们都是以像素灰度值作为索引,以灰度值映射后的数值作为表中的内容,通过索引号与映射后的输出值建立联系。

一般灰度图像会有 0-255 个灰度值,有时我们不需要这么精确的灰度级,例如黑白图像。下面我们来展示如何建立一个 LUT,将 64 到 196 之间的灰度值变成 0,其余变成 1。

Mat lut(1, 256, CV_8U);
for (int i = 0; i < 256; i++)
{
    if (i > 64 and i < 196)
    {
        lut.at<uchar>(i) = 0;
    }
    else
    {
        lut.at<uchar>(i) = i;
    }
}

从上述代码可以看出,通过改变图像中像素的灰度值,LUT 可以降低灰度级提高运算速度。

LUT 只适用于 CV_8U 类型的图像。

当然,查找表并不一定都是单通道的。

  • 如果输入图像为单通道,那么查找表为单通道

  • 如果输入图像为三通道,那么查找表可以为单通道或者三通道

使用 LUT 进行遍历,采用的是颜色空间缩减的方式:把 unsigned char 类型的值除以一个 int 类型的值,得到仍然是一个 char 类型的数值。

我们采用如下的公式:

其中,Q 表示量化级别,当 Q= 10 时则灰度值 1-10 用灰度值 1 表示,灰度值 11-20 用灰度值 11 表示,以此类推。256 个灰度值的灰度图像可以用 26 个数值表示,那么彩色的图像就可以用 26 * 26 * 26 个数值表示,比原先小了很多。

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>

using namespace std;
using namespace cv;

#define QUAN_VAL1          10
#define QUAN_VAL2          20
#define QUAN_VAL3          100

void createLookupTable(Mat& table, uchar quanVal)
{
    table.create(1,256,CV_8UC1);

    uchar *p = table.data;
    for(int i = 0; i < 256; ++i)
    {
        p[i] = quanVal*(i/quanVal); // 颜色缩减运算
    }
}

int main()
{
    Mat srcImage = imread("/Users/tony/beautiful.jpg");
    if (srcImage.empty())
    {
        cout << "could not load image ..." << endl;
        return -1;
    }
    imshow("src", srcImage); // 原图

    Mat table,dst1,dst2,dst3;
    createLookupTable(table, QUAN_VAL1);
    LUT(srcImage, table, dst1);

    createLookupTable(table, QUAN_VAL2);
    LUT(srcImage, table, dst2);

    createLookupTable(table, QUAN_VAL3);
    LUT(srcImage, table, dst3);

    imshow("dst1", dst1); // Q=10
    imshow("dst2", dst2); // Q=20
    imshow("dst3", dst3); // Q=100
    waitKey(0);

    return 0;
}
90c433dda869d33d1fa5fa71fde7ce70.jpeg
lut.png

上述例子在创建查找表时,遍历了矩阵的每一个像素以及运用颜色空间缩减的运算公式。并且分别展示了原图、Q=10、Q=20、Q=100 的图片。可以看到当 Q = 100 时,图像压缩得比较厉害丢失了很多信息。

Part33. 图像像素值的统计

63.1 均值与标准差

均值和标准差是统计学的概念。

均值的公式:

标准差公式:

在图像处理中,它们能帮助我们了解图像通道中像素值的分布情况。均值表示图像整体的亮暗程度,图像的均值越大则表示图像越亮。标准差表示图像中明暗变化的对比程度,标准差越大表示图像中明暗变化越明显。

在图像分析的时候,我们通过图像像素值的统计,可以对图像的有效信息作出判断。当标准差很小时,图像所携带的有效信息会很少,便于我们判断这是否是我们所需要的图像。说一个题外话,曾经我看到过一段很震惊的代码,某同事写的判断传送带上手机是否亮屏。当时的代码可能是为了偷懒,只通过判断图像的均值,当均值超过某个阈值时就认为手机是亮屏的。后来我接手后,当即做了大量的修改。

下面举个例子,通过 meanStdDev() 函数获取图像的均值和标准差,以及每个通道的均值和标准差。

Mat srcImage = imread("/Users/tony/beautiful.jpg");
if (srcImage.empty())
{
    cout << "could not load image ..." << endl;
    return -1;
}
imshow("src", srcImage);

Mat mean, stddev;
meanStdDev(srcImage, mean, stddev);
std::cout << "mean:" << std::endl << mean << std::endl;
std::cout << "stddev:" << std::endl<< stddev << std::endl;
printf("blue channel mean:%.2f, stddev: %.2f \n", mean.at<double>(0, 0), stddev.at<double>(0, 0));
printf("green channel mean:%.2f, stddev: %.2f \n", mean.at<double>(1, 0), stddev.at<double>(1, 0));
printf("red channel mean:%.2f, stddev: %.2f \n", mean.at<double>(2, 0), stddev.at<double>(2, 0));

输出结果:

mean:
[91.28189117330051;
 104.7030620995939;
 118.9715339648672]
stddev:
[77.24017058254671;
 79.5424883584348;
 83.89088339080149]
blue channel mean:91.28, stddev: 77.24 
green channel mean:104.70, stddev: 79.54 
red channel mean:118.97, stddev: 83.89

Part44. 总结

本文过一个简单的例子,介绍了 Mat 经常使用的属性和方法。后续还介绍了像素的类型和多种图像遍历的方式、像素值的统计。

在几种图像遍历方式中,除了 LUT 遍历外,其他的几种方式它们的效率从高到低依次为:指针 > 迭代器 > 数组。在实际生产环境中,我们经常会用指针遍历的方式

本文介绍的内容是对前面一篇文章内容的补充,它们都是 OpenCV 最基础的内容,接下来的文章会经常使用这些内容。本文还引申出了 LUT 以及图像像素值的统计, 特别是均值和标准差它们在图像预处理中经常用到。

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

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

相关文章

数据库索引种类

文章目录 索引的优缺点优点缺点 聚簇索引特点优点缺点 非聚簇索引特点优点缺点使用场景&#xff1a; 在MyISAM与InnoDB中的使用 索引的优缺点 索引概述 MySQL官方将索引定义为帮助MySQL高效获取数据的数据结构。索引的本质是一种排好序的快速查找数据结构&#xff0c;用于满足…

YOLOv5/v7/v8改进实验(五)之使用timm更换YOLOv5模型主干网络Backbone篇

&#x1f680;&#x1f680; 前言 &#x1f680;&#x1f680; timm 库实现了最新的几乎所有的具有影响力的视觉模型&#xff0c;它不仅提供了模型的权重&#xff0c;还提供了一个很棒的分布式训练和评估的代码框架&#xff0c;方便后人开发。更难能可贵的是它还在不断地更新迭…

(H5轮播)vue一个轮播里显示多个内容/一屏展示两个半内容

效果图 : html: <div class"content"><van-swipeclass"my-swipe com-long-swipe-indicator":autoplay"2500"indicator-color"#00C4FF"><van-swipe-itemclass"flex-row-wrap"v-for"(items, index) in M…

Kubernetes 进阶

Kubernetes 进阶  Service 控制器  Ingress 对象(对外暴露应用)  管理应用程序配置  K8s 数据卷与持久数据卷  再谈有状态应用部署:StatefulSet控制器  K8s 安全访问控制  K8s 部署利器Helm初探 Service 控制器 • Service存在的意义 • Pod与…

更改Kali Linux系统语言以及安装zenmap

目录 更改Kali Linux系统语言 安装 Zenmap 更改Kali Linux系统语言以及安装zenmap 在使用kali的过程中&#xff0c;会遇到许多问题&#xff0c;其中一个就是看不懂英语&#xff0c;下面是如何更换语言的步骤。 更改Kali Linux系统语言 首先&#xff0c;打开kali&#xff0…

学信息系统项目管理师第4版系列32_信息技术发展

1. 大型信息系统 1.1. 大型信息系统是指以信息技术和通信技术为支撑&#xff0c;规模庞大&#xff0c;分布广阔&#xff0c;采用多级 网络结构&#xff0c;跨越多个安全域&#xff1b;处理海量的&#xff0c;复杂且形式多样的数据&#xff0c;提供多种类型应用 的大系统 1.1.…

python安装、输入输出、注释、中文编码、编码规范等基础语法

一、概述 1、简介 Python的创始人为吉多范罗苏姆&#xff08;Guido van Rossum&#xff09;。1989年的圣诞节期间&#xff0c;Guido开始写Python语言的编译器。Python这个名字&#xff0c;来自Guido所挚爱的电视剧Monty Python’s Flying Circus。他希望这个新的叫做Python的…

30 Python的matplotlib模块

概述 在上一节&#xff0c;我们介绍了Python的pandas模块&#xff0c;包括&#xff1a;Series、DataFrame、数据读取和写入等内容。在这一节&#xff0c;我们将介绍Python的matplotlib模块。matplotlib模块是一个Python的2D绘图库&#xff0c;可以实现各种类型的图形绘制&#…

【试题021】C语言算术运算符例题

1.题目&#xff1a;表达式4.8-1/25%3的值是 &#xff1f; 2.代码解析&#xff1a; //表达式4.8-1/25%3的值是?printf("%d\n", (4 - 1 / 2 5 % 3));//分析&#xff1a;多个运算符看优先级高低次序//根据口诀可知&#xff1a; /和%都排第三&#xff0c;和-排第四//所…

AutoSAR入门:应用背景及简介

1、应用背景 在我们现在的汽车行业里面&#xff0c;汽车电子的发展过程中&#xff0c;我们发现有一些新的趋势汽车电子系统的复杂性不断增长。 我们现在可以看到车辆有越来越多的功能&#xff0c;那么这些功能呢&#xff0c;也在往这个控制器上进行集中&#xff0c;比如说我们现…

修炼k8s+flink+hdfs+dlink(六:学习k8s)

一&#xff1a;增&#xff08;创建&#xff09;。 直接进行创建。 kubectl run nginx --imagenginx使用yaml清单方式进行创建。 二&#xff1a;删除。 kubectl delete pods/nginx 三&#xff1a;修改。 kubectl exec -it my-nginx – /bin/bash 四&#xff1a;查看。 …

【Leetcode每日一题 1726】「组合|哈希表」同积元组

2023.10.19 本题重点&#xff1a; 1.题目的理解&#xff0c;如何转化成一种组合问题 2.哈希表的使用 题目介绍&#xff1a; 给你一个由 不同 正整数组成的数组 nums &#xff0c;请你返回满足 a * b c * d 的元组 (a, b, c, d) 的数量。其中 a、b、c 和 d 都是 nums 中的元…

11. 机器学习 - 评价指标2

文章目录 混淆矩阵F-scoreAUC-ROC 更多内容&#xff1a; 茶桁的AI秘籍 Hi, 你好。我是茶桁。 上一节课&#xff0c;咱们讲到了评测指标&#xff0c;并且在文章的最后提到了一个矩阵&#xff0c;我们就从这里开始。 混淆矩阵 在我们实际的工作中&#xff0c;会有一个矩阵&am…

【计算机网络笔记】OSI参考模型基本概念

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

分布式存储 vs. 全闪集中式存储:金融数据仓库场景下的性能对比

作者&#xff1a;深耕行业的 SmartX 金融团队 张德敏 近年来随着金融行业的高速发展&#xff0c;经营决策者及监管机构对信息时效性的要求越来越高&#xff0c;科技部门面临诸多挑战。例如&#xff0c;不少金融机构使用数仓业务系统&#xff0c;为公司高层提供日常经营报表&am…

阿里云服务器x86计算架构ECS规格大全

阿里云企业级服务器基于X86架构的实例规格&#xff0c;每一个vCPU都对应一个处理器核心的超线程&#xff0c;基于ARM架构的实例规格&#xff0c;每一个vCPU都对应一个处理器的物理核心&#xff0c;具有性能稳定且资源独享的特点。阿里云服务器网aliyunfuwuqi.com分享阿里云企业…

InitializeComponent报错(提示不存在)

我是c#新手。为了解决这个问题&#xff0c;需要按照以下步骤进行。、 WPF应用(.NET Framework) 解决问题 首先&#xff0c;确保项目的类型为WPF应用(.NET Framework)&#xff1b; 然后&#xff0c;代码的位置应正确处于项目的MainWindow.xaml.cs&#xff1b; 最后&#xff0c…

Deno 快速入门

目录 1、简介 2、安装Deno MacOS下安装 Windows下安装 Linux 下安装 3、创建并运行TypeScript程序 4、内置Web API和Deno命名空间 5、运行时安全 6、导入JavaScript模块 7、远程模块和Deno标准库 8、使用deno.json配置您的项目 9、Node.js API和npm包 10、配置IDE…

宏(预编译)详解

目录 一、程序的编译环境 二、运行环境 三、预编译详解 3.1预定义符号 3.2.1 #define 定义标识符 3.2.2 #define 定义宏 3.2.3#define替换规则 3.2.4 #和## 2)##的作用&#xff1a; 3.2.5宏和函数的对比 3.2.6宏的命名约定和#undef指令 一、命名约定&#xff1a; …

CCC数字钥匙设计【NFC】--通过NFC进行车主配对Phase3

1、车主配对流程介绍 车主配对可以通过车内NFC进行&#xff0c;若支持UWB测距&#xff0c;也可以通过蓝牙/UWB进行。通过NFC进行车主配对总共有5个Phase。本文档主要对Phase3进行介绍。 1) Phase0&#xff1a;准备阶段&#xff1b; 2) Phase1&#xff1a;启动流程&#xff1…