OpenCV4 学习指导1 —— Mat:最基本的图像容器

news2024/11/18 5:47:17

Mat: CV基本的数据结构

    • 1、认识数字图像
    • 2、CV的发展历程
    • 3、Mat的基本结构
      • 3.1、Mat—浅拷贝
      • 3.2、Mat—深拷贝
    • 4、颜色的表示方法
    • 5、创建Mat对象方法集合
      • 5.1、Mat类的常用成员函数
      • 5.2、Mat类的成员函数举例
    • 6、Mat的输出样式
    • 7、Point 数据存储结构
    • 8、参考资源

1、认识数字图像

我们有多种方法从现实世界中获取数字图像:数码相机、扫描仪、 计算机断层成像和磁共振成像等等。在任何情况下,我们(人类)看到的都是图像。然而,当我们把它转换到数字设备时,记录的是图像中每个点的数值(也就称为数字图像)。

在这里插入图片描述
例如,在上面的图像中,可以看到,汽车的镜子只不过是一个包含所有像素点的强度值矩阵。我们获取和存储像素值的方式可能会根据我们的需要而有所不同,但是最终计算机世界中的所有图像可能会被简化为数字矩阵和其他描述矩阵本身的信息。OpenCV 是一个计算机视觉库,其主要目的是处理和操作这些信息。因此,首先需要熟悉的是 OpenCV 如何存储和处理图像。

2、CV的发展历程

OpenCV 从2001年就开始了,最开始的 CV 库是围绕 C 接口构建的。为了在内存中存储图像,使用了一种称为 IplImage 的 C 结构,这将在大多数旧的教程和教育材料中看到。这样做的问题在于包含了 C 语言的所有缺点,其中最大的问题是需要手动内存管理。它建立在用户负责内存分配和释放的假设之上。虽然这对于较小的程序来说不是问题,但是一旦你的代码基数增长了,处理所有这些问题就会变得更加困难,而不是专注于实现你的开发目标。

幸运的是,C + + 出现了,并且引入了类的概念,通过自动内存管理,使用户更加容易使用。好消息是 C + + 与 C 完全兼容,所以不会产生兼容性问题。因此,OpenCV 2.0 引入新的 C + + 接口,它提供了一种新的方式,这意味着你不需要摆弄内存管理,使你的代码简洁(更少的编写,实现更多)。C + + 接口的主要缺点是,目前许多嵌入式开发系统只支持 C。因此,除非你的目标是嵌入式平台,否则使用旧方法毫无意义(除非你是一个受虐狂程序员,并且自找麻烦)。

关于 Mat,您需要了解的第一件事是,您不再需要手动分配它的内存,并在不需要时尽快释放它。虽然这样做仍然是可能的,但大多数 OpenCV 函数将自动分配其输出数据。如果您传递一个已经存在的 Mat 对象(它已经为矩阵分配了所需的空间) ,这将是一个很好的奖励,它将被重用。换句话说,我们在任何时候只使用执行任务所需的内存。

3、Mat的基本结构

Mat 是一个包含两个数据部分的类:矩阵头(matrix header,包含矩阵大小、存储方法、存储矩阵的地址等信息)和指向矩阵的指针(pointer),矩阵包含像素值。矩阵头部的大小是固定的,但矩阵本身的大小可能会因图像大小而异。

OpenCV 是一个图像处理库。它包含了大量的图像处理功能。为了解决计算方面的挑战,大多数情况下您最终将使用库的多个函数。因此,将图像传递给函数是一种常见的操作。我们不应该忘记,我们正在谈论的是图像处理算法,这往往是相当沉重的计算量。通过制作大型图像的副本,会进一步降低程序的速度。

为了解决这个问题,OpenCV 使用了一个引用计数系统。基本思想:每个 Mat 对象都有自己的头,但是一个矩阵可以在两个 Mat 对象之间通过让它们的【矩阵指针】指向相同的地址来共享。此外,复制操作符只复制大矩阵的矩阵头和指针,而不复制图像数据本身。

3.1、Mat—浅拷贝

Mat A, C;                          // 仅仅创建矩阵头(matrix header)
A = imread(argv[1], IMREAD_COLOR); // 分配内存,存储图像数据
Mat B(A);                          // 使用复制构造器(copy constructor)
C = A;                             // 赋值操作符(Assignment operator)

上述所有对象(B,C)都指向同一个数据矩阵,对其中任何一个进行修改都会影响其它所有对象。实际上,不同的对象只是为相同的底层数据提供了不同的访问方法。然而,他们的头部部分(header)是不同的。

真正有趣的部分是,您可以创建只引用完整数据的一部分的矩阵头(matrix header)。例如,要在图像中创建感兴趣区域(ROI) ,只需创建一个带有新边界的新矩阵头,具体如下:

Mat D (A, Rect(10, 10, 100, 100) ); // using a rectangle
Mat E = A(Range::all(), Range(1,3)); // using row and column boundaries

值得注意的是:

  1. 如果修改A的像素,那么D和E都会被影响。
  2. 这个有个问题?如果矩阵本身属于多个 Mat 对象,当它不再需要的时候,谁来负责清理它?答案是:最后一个使用它的对象。这是通过使用引用计数机制(reference count systerm)来处理的。每当拷贝一次 Mat 对象的头,矩阵的计数器就会加 1。每当清理矩阵头时,计数器就会减 1。当计数器达到零时,矩阵被释放。
  3. 浅复制可以降低内存的消耗,如果需要频繁修改像素值,则会带来不小的隐患。

3.2、Mat—深拷贝

如果不希望原始图像被修改,可以使用深拷贝的方法,代码片段如下:

Mat F = A.clone();
Mat G;
A.copyTo(G);

使用上述方式,修改F和G的数据,不会影响到A指向的图像数据,有几点需要注意:

  1. OpenCV 函数的输出图像分配是自动的(除非特别指定);
  2. 使用 OpenCV 的 C++ 接口,不用特别关注内存的管理;
  3. 赋值操作和复制构造函数仅仅拷贝矩阵头;
  4. Mat 深度拷贝可以使用 cv::Mat::clone() and cv::Mat::copyTo()

4、颜色的表示方法

关于如何存储像素值的:我们可以选择颜色空间(color space)和所使用的数据类型(data type)。颜色空间是指如何组合颜色组件来编码给定的颜色。最简单的是灰度图,可以使用的颜色是黑色和白色,这些元素的组合使我们能够创造出许多灰色的阴影。

对于创建更多丰富多彩的图像,我们有更多的方法可供选择。我们通常把它分解成3~4个基本组成部分,使用这些组合来创建其它的颜色。最流行的是 RGB 颜色空间,主要是因为这也是我们的眼睛建立颜色的方式。它的基本颜色是红色,绿色和蓝色。为了编写颜色的透明度代码,有时会添加第四个元素 alpha (A)。

然而,还有许多其他的颜色系统(RGB,HSV/HLS,YCrCb,Lab),每一个都有自己的优势:

  • RGB 是最常见的,因为我们的眼睛使用类似的东西。但请记住,OpenCV 标准显示系统组成的颜色使用 BGR 颜色空间(红色和蓝色通道交换的位置)。
  • HSV 和 HLS 将颜色分解为它们的色相(hue)、饱和度(suaturation)和值/亮度(value/luminance)等三个部分,这是我们描述颜色的一种更自然的方式。例如,可以忽略最后一个组件,使算法对输入图像的光照条件不太敏感。
  • 流行的 JPEG 图像格式使用 YCrCb。
  • CIE L * a * b * 是一个感知上均匀的颜色空间,如果您需要测量给定颜色到另一种颜色的距离,它会派上用场。

每个构建组件都有自己的有效域。这将导致所使用的数据类型。如何存储组件定义了我们对其有效域的控制。最小的数据类型可能是 char,这意味着一个字节或8位,可以是无符号的(因此可以存储从0到255的值)或有符号的(值从 -127到 + 127)。虽然这个宽度,在三个组件(如 RGB)的情况下,已经给出了1600万种可能的颜色来表示,我们可以通过使用每个组件的 float (4字节 = 32位)或 double (8字节 = 64位)数据类型来获得更好的控制。然而,请记住,增加组件的大小也会增加内存的占用。

5、创建Mat对象方法集合

虽然 Mat 作为一个图像容器工作得非常好,但它也是一个通用的矩阵类。因此,可以创建和操作多维矩阵。借助【Mat 类】的成员函数,我们可以通过多种方式创建 【Mat 对象】,创建方法如下:

5.1、Mat类的常用成员函数

  • Mat (int rows, int cols, int type)

    CV::Mat 第一个重载成员函数,用于创建新的矩阵。
    参数解析

    1. rows:2D 数组的行数;
    2. cols:2D 数组的列数;
    3. type:数组类型,比如CV_64FC4,表示每个元素占用64bit(4byte),元素的数据类型为Float,4个通道;

    官方API
    这里是引用

  • Mat (Size size, int type)

    函数功能:重载函数,便于创建矩阵。
    参数解析:

    1. size:2D 数组的大小,Size(cols,rows)。在Size() 构造器中,rowscols是反的顺序;
    2. type:参考上述的介绍,此处略;

    官方API
    在这里插入图片描述

5.2、Mat类的成员函数举例

  • cv::Mat::Mat Constructor(构造器)

    Mat M(2,3, CV_8UC3, Scalar(0,0,255));
    cout << "M = " << endl << " " << M << endl << endl;
    M = 
     [  0,   0, 255,   0,   0, 255,   0,   0, 255;
    	0,   0, 255,   0,   0, 255,   0,   0, 255]
    
    1. 2,3:指定Mat矩阵的行(2)和列(3);
    2. CV_8UC3:指定存储数据的类型,每一个矩阵点的通道数,结构如下CV_[The number of bits per item][Signed or Unsigned][Type Prefix]C[The channel number]
    3. 具体解释:【8】表示存储一个数据的需要8位的长度(一个字节byte),【U】表示无符号类型,【C】表示字符型(char),【3】表示通道数量;
    4. Scalar(0,0,255):指定创建矩阵的初始化值。
  • C/C++ 数组 和 Mat 构造器初始化

    Mat类的重载成员函数,不同的地方在于参数的设定,

    1. ndims:矩阵的维度
    2. size:整数类型的多维数组
    3. type:与上面的定义是一样的
    4. 官方重载函数如下图所示:在这里插入图片描述

    示例:

    int sz[3] = {2,3,5};
    Mat L(3,sz, CV_8UC(1), Scalar::all(0));
    std::cout << "L.DIMS = " << " " << L.dims << std::endl;
    std::cout << "L.SIZE = " << " " << L.size << std::endl;
    
    // 输出如下
    L.DIMS =  3
    L.SIZE =  2 x 3 x 5
    

  • cv::Mat::create

    这里是引用
    该方法的使用规则:

    1. 如果当前数组形状和类型与新的匹配,则立即返回。否则,通过调用 Mat: : release 解除对前面数据的引用;
    2. 初始化新的矩阵头(header);
    3. 为新的数据分配空间,空间大小为: t o t a l ( ) ∗ e l e m S i z e ( ) total()*elemSize() total()elemSize(),单位是字节(byte);
    4. 分配与数据关联的新引用计数器,并将其设置为1 ;

    补充内容:

    1. memory size = image.total() x image.elemSize();
    2. image.total() = image.width x image.height;
    3. image.elemSize:一个像素值占的字节数大小,比如16SC3,其它大小为3xsizeof(short)
    // create function
    M.create(4,4, CV_8UC(2));
    cout << "N = "<< endl << " "  << M << endl << endl;
    std::cout << "M = " << std::endl << " " << &(M.data) << std::endl << std::endl;
    N = 
     [  0,   0,   0,   0,   0,   0,   0,   0;
        0,   0,   0,   0,   0,   0,   0,   0;
      216, 224,  38,   2,   0,   0,   0,   0;
       32, 225,  38,   2,   0,   0,   0,   0]
    
    M = 
     0x7ffd731496f0
    
  • Matlab 风格的初始化

    Mat E = Mat::eye(4, 4, CV_64F);
    cout << "E = " << endl << " " << E << endl << endl;
    Mat O = Mat::ones(2, 2, CV_32F);
    cout << "O = " << endl << " " << O << endl << endl;
    Mat Z = Mat::zeros(3,3, CV_8UC1);
    cout << "Z = " << endl << " " << Z << endl << endl;
    
    // 输出内容如下
    E = 
     [1, 0, 0, 0;
      0, 1, 0, 0;
      0, 0, 1, 0;
      0, 0, 0, 1]
    
    O = 
     [1, 1;
      1, 1]
    
    Z = 
     [  0,   0,   0;
        0,   0,   0;
        0,   0,   0]
    
  • 使用 Mat_ 和 短列表初始化 Mat

    Mat C = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
    cout << "C = " << endl << " " << C << endl << endl;
    
    C = (Mat_<double>({0, -1, 0, -1, 5, -1, 0, -1, 0})).reshape(3);
    cout << "C = " << endl << " " << C << endl << endl;
    
    // 输出内容
    C = 
     [0, -1, 0;
     -1, 5, -1;
      0, -1, 0]
    
    C = 
     [0, -1, 0;
     -1, 5, -1;
      0, -1, 0]
    
  • cv::Mat::clone or cv::Mat::copyTo
    在已有Mat 数据 C 的基础上,创建新的Mat

    // 取C的第2行,创建新的Mat
    MatRowClone = C.row(1).clone();
    cout << "RowClone = " << endl << " " << RowClone << endl << endl;
    
    // 输出内容
    RowClone = [-1, 5, -1]
    
  • 随机值初始化矩阵

    Mat R = Mat(3, 2, CV_8UC3);
    randu(R, Scalar::all(0), Scalar::all(255));
    
    // 输出内容
    R (default) = 
    	[ 91,   2,  79, 179,  52, 205;
    	 236,   8, 181, 239,  26, 248;
     	 207, 218,  45, 183, 158, 101]
    

6、Mat的输出样式

 从输出的结构可以看出,默认的风格(C++)与C是很像的,Python和Numpy是非常类似的。

  • Default

    cout << "R (default) = " << endl <<        R           << endl << endl;
    
    // 输出内容
    R (default) = 
    	[ 91,   2,  79, 179,  52, 205;
    	 236,   8, 181, 239,  26, 248;
    	 207, 218,  45, 183, 158, 101]
    
  • Python

    cout << "R (python)  = " << endl << format(R, Formatter::FMT_PYTHON) << endl << endl;
    
    // 输出内容
    R (python)  = 
    	[[[ 91,   2,  79], [179,  52, 205]],
    	 [[236,   8, 181], [239,  26, 248]],
    	 [[207, 218,  45], [183, 158, 101]]]
    
  • CSV

    cout << "R (csv)     = " << endl << format(R, Formatter::FMT_CSV   ) << endl << endl;
    
    // 输出内容
    R (csv)     = 
     	91,   2,  79, 179,  52, 205
       236,   8, 181, 239,  26, 248
       207, 218,  45, 183, 158, 101
    
  • Numpy

    cout << "R (numpy)   = " << endl << format(R, Formatter::FMT_NUMPY ) << endl << endl;
    
    // 输出内容
    R (numpy)   = 
    	array([[[ 91,   2,  79], [179,  52, 205]],
      		   [[236,   8, 181], [239,  26, 248]],
     	 	   [[207, 218,  45], [183, 158, 101]]], dtype='uint8')
    
  • C

    cout << "R (numpy)   = " << endl << format(R, Formatter::FMT_NUMPY ) << endl << endl;
     	
    // 输出内容
    R (c)       = 
       { 91,   2,  79, 179,  52, 205,
        236,   8, 181, 239,  26, 248,
        207, 218,  45, 183, 158, 101}
    

7、Point 数据存储结构

  • Point 的类型
    在这里插入图片描述

  • 示例解析

    // 2D Point
    Point2f P(5, 1);
    cout << "Point (2D) = " << P << endl << endl;
    
    // 3D Point
    Point3f P3f(2, 6, 7);
    cout << "Point (3D) = " << P3f << endl << endl;
    
    // vector
    vector<float> v;
    v.push_back( (float)CV_PI);   v.push_back(2);    v.push_back(3.01f);
    cout << "Vector of floats via Mat = " << Mat(v) << endl << endl;
    
    // push 2d points
    vector<Point2f> vPoints(20);
    for (size_t i = 0; i < vPoints.size(); ++i)
        vPoints[i] = Point2f((float)(i * 5), (float)(i % 7));
    cout << "A vector of 2D Points = " << vPoints << endl << endl;
    
    // 输出内容
    Point (2D) = [5, 1]
    
    Point (3D) = [2, 6, 7]
    
    Vector of floats via Mat = [3.1415927;
     									2;
    								 3.01]
    
    A vector of 2D Points = [0, 0;
    						 5, 1;
    					 	10, 2;
    					 	15, 3;
    					 	20, 4;
    					 	25, 5;
    					 	30, 6;
    					 	35, 0;
    					 	40, 1;
    					 	45, 2;
    					 	50, 3;
    					 	55, 4;
    					 	60, 5;
    					 	65, 6;
    					 	70, 0;
    					 	75, 1;
    					 	80, 2;
    					 	85, 3;
    					 	90, 4;
    					 	95, 5]
    

8、参考资源

  • 官方示例代码文件
  • 官方教程:Mat - The Basic Image Container

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

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

相关文章

Yolov8改进---注意力机制:Polarized Self-Attention,效果秒杀CBAM、SE

1. Polarized Self-Attention 论文:https://export.arxiv.org/pdf/2107.00782.pdf Polarized self-attention是一种改进的自注意力机制,旨在提高自注意力模型的效率和准确性。传统的自注意力机制通常需要计算所有位置对所有位置的注意力,这会导致计算复杂度的增加和模型的训…

君子签:助力高校毕业、就业协议电子签,打通就业最后一公里

据介绍&#xff0c;2023届全国普通高校毕业生规模预计达1158万人&#xff0c;同比增加82万人。毕业季即将来临&#xff0c;全国各大高校毕业、就业材料签署压力大&#xff0c;盖章需求激增&#xff0c;如何快捷、高效地处理各类毕业、就业材料签署问题呢&#xff1f; 在教育部…

间隔损失函数

度量损失&#xff1a; Contrastive Loss 核心含义&#xff1a;同类的样本要更近&#xff0c;不同类的样本要更远 正样本不用管&#xff0c;把负样本分开就行&#xff0c;最小化损失函数就是最大化决策边界和负样本的距离 Triplet Loss Triplet Loss是一种用于训练深度学习中…

7-2 哈利·波特的考试

哈利波特要考试了&#xff0c;他需要你的帮助。这门课学的是用魔咒将一种动物变成另一种动物的本事。例如将猫变成老鼠的魔咒是haha&#xff0c;将老鼠变成鱼的魔咒是hehe等等。反方向变化的魔咒就是简单地将原来的魔咒倒过来念&#xff0c;例如ahah可以将老鼠变成猫。另外&…

git的学习2

文章目录 一、Git 创建仓库二、Git 基本操作1总结 一、Git 创建仓库 git init Git 使用 git init 命令来初始化一个 Git 仓库&#xff0c;Git 的很多命令都需要在 Git 的仓库中运行&#xff0c;所以 git init 是使用 Git 的第一个命令。 在执行完成 git init 命令后&#xf…

Opencascad开发(C#)-建模-反向片体(SheetBody)的法向矢量

文章目录 1、前言2、在UG NX中构建一个片体3、在UG NX中查看片体的法向矢量4、采用UFun函数来实现法向反向5、代码实现6、测试效果1、前言 在UG NX中,一张曲面获取其所属的片体(SheetBody)对象,其在构建时有默认的法向矢量,有时处于功能的需求,比如加工时工件的材料去除方…

根据IP获取地理位置信息 — Golang

根据IP获取地理位置信息 — Golang 1 介绍1.1 ip2region1.2 geoip2-golang1.3 总结 2 使用2.1 ip2region2.2 geoip2-golang 1 介绍 1 ip2region 2 geoip2-golang 1.1 ip2region ip2region 是一个离线IP地址定位库和IP定位数据管理框架&#xff0c;10微秒级别的查询效率&…

ipad密码忘了怎么解锁?教你40秒轻松移除!

无论是手机还是平板&#xff0c;相信大部分都会去给它们设上密码&#xff0c;来保证自己的隐私安全。同理&#xff0c;无论是苹果设备还是安卓设备&#xff0c;一旦设了锁屏密码&#xff0c;就会遇到密码忘记的情况&#xff0c;多次输入错误密码还会导致设备被停用。 近日&…

上海亚商投顾:沪指放量上涨创年内新高 中字头个股掀涨停潮

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 市场情绪 沪指今日高开高走&#xff0c;盘中一度涨近2%&#xff0c;站上3400点关口&#xff0c;深成指、创业板指走势较弱。…

openssl一套证书-配置文件和证书签发

dn-param 和 extend 配置文件 CA的dn-param 和 extend CA的dn-param 和 extend CI-csr.cnf 的内容如下&#xff1a; #openssl x509 extfile params extensions extend # This prevent the user to be prompted for values prompt nodistinguished_name dn-param [dn-param…

【C++】-对于自定义类型的输入输出运算符重载

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树 ❤️‍&#x1fa79;作者宣言&#xff1a;认真写好每一篇博客 &#x1f4a8;作者gitee:gitee &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 文章目录 前言一、案例引入二、<<的重载三、>>的…

智慧城市3d可视化管理大屏系统有效提高服务质量和效率

随着新一代信息技术飞速融入传统产业&#xff0c;农业数字化、网络化、智能化逐步成为农业现代化发展的基石。实现农业生产环境的智能感知、智能预警、智能决策、智能分析等功能&#xff0c;为农业生产提供精准化保障、高质量运营水平、智能化决策支撑。 3D可视化智慧管理 1&am…

在docker上安装运行Python文件

目录 一、在docker中安装python 1.1 输入镜像拉取命令 1.2 查看镜像 1.3 运行 1.4 查看是否成功 1.5 查看python版本 二、运行py文件 2.1准备运行所需文件 2.2 准备文件夹 2.3 大概是这幅模样 2.4 打包上传到服务器上 2.5 构建镜像示例 2.6 查看镜像 2.7 优化镜像的…

微星GT77HX-13VI2023原厂Windows11重建F3一键恢复

MSI微星系列原厂预装正版系统恢复镜像有原机所有驱动&#xff0c;主题&#xff0c;Logo 安装后自动重建f3 msirestore功能 系统带所有驱动以及msi center小红龙 恢复至出厂状态 文件地址https://pan.baidu.com/s/1snKOsH3OMl3GZLqeAf-GLA?pwd8888 其他型号: 微星 GE76-12代…

lua | 数组与迭代器的使用

目录 一、数组 一维数组 多维数组 二、迭代器 泛型for迭代器 无状态的迭代器 多状态的迭代器 本文章为笔者学习分享 学习网站&#xff1a;Lua 基本语法 | 菜鸟教程 一、数组 数组&#xff1a;相同数据类型的元素按一定顺序排列的集合&#xff0c;可以是一维数组和多维数…

就业Android倒数第二,IOS稳居倒数第一

在如今的互联网大环境下&#xff0c;相信有很多人都在为找工作而感到焦虑&#xff0c;每一投上十几份简历&#xff0c;收到的面试通知也就那么一两家&#xff0c;而且收到面试通知的都是一些小企业&#xff0c;工资低就不是很想去&#xff0c;工资高的岗位看了一下要求感觉自己…

解决uniapp在js文件中使用国际化报错问题

uniapp js 中如何使用国际化&#xff1f; 文章目录 uniapp js 中如何使用国际化&#xff1f;main.js 配置遇到问题解决方案Demo方式一&#xff1a;异步加载模块Promise 写法await写法 方式二&#xff1a;局部引入方式三&#xff1a;按需导入 main.js 配置 main.js 引入并初始化…

Python——pyqt5的计算器(源码+打包)

目录 一、效果图 二、源码 三、如何打包 四、如何减小打包程序大小&#xff08;方法1&#xff09; 五、如何减小打包程序大小&#xff08;方法2&#xff09; 学习视频 一、效果图 只是单纯的练手&#xff0c;然后再学习一下如何打包 二、源码 calculator_UI.zip - 蓝奏云…

论文阅读《Centralized Feature Pyramid for Object Detection》

论文地址&#xff1a;https://arxiv.org/pdf/2210.02093.pdf 源码地址&#xff1a;https://github.com/QY1994-0919/CFPNet 概述 特征金字塔模块在众多计算机视觉任务中都有优异的性能表现。针对现有的方法过渡关注于层间的特征交互而忽略了层内的特征交互的问题&#xff0c;本…

药物分子虚拟筛选规则

药物分子虚拟筛选规则 Lipinski Rule RO5是辉瑞公司资深药物化学家Christopher A. Lipinski在1997年提出&#xff0c;虽然随时代发展虽然其适用范围逐渐变窄&#xff0c;但仍然非常有参考意义。其主要内容如下&#xff1a; 分子量(Mw)小于500&#xff1b;氢键供体(HBD)数目小…