精华内容
下载资源
问答
  • 【Verilog】Verilog定义二维数组(2D Array)
    千次阅读
    2022-03-30 21:28:35

    目录

     

    定义的种类

    第一种

    赋值方法

    第二种

    赋值方法

    第三种

    赋值方法


     

    定义的种类

    首先看几组定义类型

    第一种

    定义一个位宽为8的 data1(reg) 和 data2(wire) 的变量。

    reg     [7:0]    data1;
    
    wire    [7:0]    data2;

    赋值方法

    如果要对其进行赋值等操作,可以用 always 块进行赋值,或者利用 assign 语句。

    第二种

    定义一个一维数组

    将内存定义为一个 reg 类型的一维数组,这个数组中的任何一个单元都可以通过一个下标去访问。这样的数组的定义方式如下:

    reg    [7:0]    data  [255:0];

    其中 [7:0] 表示一维数组中的每个元素的位宽大小,而在变量后面的 [255:0] ,表示的却不是位宽大小,它表示的是所创建的数组的深度,也就是一维数组中的元素大小,也可以称作为数组的容量大小。

    赋值方法

    直接访问数组中元素的下标即可,下面的代码表示的是将数字1赋值到一维数组中的第一个元素。

    reg    [7:0]    data  [255:0];
    
    data[0] = 1;

    第三种

    定义一个二维数组,也可以说是一种向量。

    这种定义方式比较少见,因为一般在Verilog代码不会涉及到二维数组的定义,这种定义方法和C语言很类似,它所表达的含义也是向内存取得一块行256、列256,每个位宽为8的二维数组,这种定义方法是我在做矩阵运算的时候发现的,这样定义一个二维数组就可以将矩阵中的数值映射到二维数组的每一个空间中,从另一方面来看,矩阵也可以看做成一个二维数组。

    reg    [7:0]    data  [255:0] [255:0];
    

    赋值方法

    错误方法:

    reg    [7:0]    data  [255:0] [255:0];
    
    assign data[0] = 1;

    这样赋值会报错:“参考标章阵列‘改编’是不是合法的净左值”和“连续分配的非法左侧”。

    首先,不能用 assign 对 reg 型的赋值。assign 类型针对于 wire 类型,而不是 reg 类型。要对一个reg类型进行操作,需要在一个逻辑块内的语句像always块一样。

    正确方法:

    reg [7:0] b [0:3] [0:3];
    
    initial begin
    
    // using 2D
    for (int i=0; i<=3; i++)
    for (int j=0; j<=3; j++)
    b[i][j] = i*j;
    end

    即使是Verilog标准也没有严格定义的理解什么是2d数组。这是来自标准:

    reg [7:0] mema [0:255];声明 256 个 8 位寄存器的内存内存。索引为 0 到 255。

    reg  arrayb [7:0][0:255];声明一个位寄存器线的二维数组

    w_array [7:0][5:0];声明线数组

    2d数组是"reg arrayb[7:0][0:255];因为如果范围放在名称之前 ,它是一个向量。

    使用 2d 数组通过使用 for-generate 语句来扩展同质结构,但很少见。在大多数情况下,使用一维向量数组,如通道的数据总线,存储器,多个模块实例的同质输出等。

     

    更多相关内容
  • 、列表(List)1.列表的特点列表是以方括号“[]”包围的数据集合,不同成员以“,”分隔。如 L = [1,2,3], 列表a有3个成员。列表是可变的数据类型【可进行增删改查】,列表中可以包含任何数据类型,也可以包含另...

    ac0a7ddc4059571c5137a7ed45256657.png

    一、列表(List)

    1.列表的特点

    • 列表是以方括号“[]”包围的数据集合,不同成员以“,”分隔。如 L = [1,2,3], 列表a有3个成员。
    • 列表是可变的数据类型【可进行增删改查】,列表中可以包含任何数据类型,也可以包含另一个列表。如: L = [1,2,[3,4]],列表L有3个成员,最后一个成员为一个列表。
    • 列表可以通过序号(索引)访问其中成员,成员序号从0开始,如:a[0]=1。
    • 列表没有shape,计算列表中成员(元素)的个数,成员以最外层的[ ]中的逗号“,”来分隔,计算方式是len(L)=3, L = [1,2,[3,4]] ,没有数组中的a.shape操作。
    • 空列表(0个元素的列表):L=[], 一个元素的列表:L=[1], 多个元素的列表L=[1,2,3]

    2.列表运算符

    列表对+ 和 * 的操作符与字符串操作类似 ,列表之间可以使用 + 号和 * 号进行运算。+号用于组合列表,*号用于重复列表,运算之后会生成一个新的列表,如下图所示:

    d1f417c7b7c9292a37a19548be7aa46b.png

    3.列表内置的函数和方法

    b1c8bf2481b54c7e3559070418a45e1c.png

    1dc4dc1030fc64c5c88872d0ebdc39f0.png

    列表操作补充:

    #列表操作补充--切片操作
    # 创建空列表
    a = []
    # 创建一个非空列表example
    example = [0,1,2,3,4,5,6,7,8,9]  
    #切片打印某一区间 左闭右开(包含左边开始序号的成员start,不包括结束序号的成员end)  
    print(example[4:8])  # [4, 5, 6, 7]
    #想包含最后一个  
    print(example[4:])   # [4, 5, 6, 7, 8, 9]
    #包含首个  
    print(example[:8])  # [0, 1, 2, 3, 4, 5, 6, 7]
    #所有的  
    print(example[:])  
    #第三个参数为步长,左闭右开  
    print(example[1:8:2])  # [1, 3, 5, 7] 
    #倒序输出  
    print(example[::-1])  
    #列表合并  
    a = [1,2,3]  
    b = [4,5,6]  
    print(a+b)
    #替换  
    ex = [1,2,3,4,5,6]
    ex[4:]=[9,8,7] # 从第四个元素开始将剩余元素替换  
    print(ex) #将56换为987
    
    
    # 定义包含不同数据类型的列表
    list4=[123,["das","aaa"],234]
    # in只能判断一个层次的元素
    "aaa" in list4      # False
    # 但是可以选中列表中的列表进行判断
    "aaa" in list4[1]   # True 
    # 获取列表中的某个元素
    print(list4[1][1])  # 'aaa'  
    

    二、元组(Tuple)

    1.元组的特点

    • 元组是以圆括号“()”包围的数据集合,括号()可以省略,不同成员(元素)以逗号“,”分隔,如:T=(1,2,3)。
    • 元组是不可变序列,即元组一旦创建,元组中的数据一旦确立就不能改变,不能对元组中中的元素进行增删改操作,因此元组没有增加元素append、修改元素、删除元素pop的相关方法,只能通过序号(索引)访问元组中的成员,元组中的成员的起始序号为0,如:T[0]=1, T=(1,2,3)。
    • 元组中可以包含任何数据类型,也可以包含另一个元组,如:T=(1,2,3,('a','b'))
    • 空元组(没有元素的元组):T=(),含1个元素的元组:T=(1,),注意有逗号,多个元素的元组:T=(1,2,3)
    • 任意无符号的对象,以逗号隔开,默认为元组,如下:

    d934af7521f58d71030998113d0290ab.png

    2.元组运算符

    与字符串和列表一样,元组之间可以使用+号和*号进行运算,+号用于组合元组,*号用于重复元组,运算之后会生成一个新的元组,如下图所示:

    c9ffce20c477eb93e618cc852bfa5523.png

    3.元组内置的函数

    ca462deb6fcac67e00628b8decc0df46.png

    4.元组操作补充访问元组

    访问元组
    o =('a','b','c',('d1','d2'))
    print o[0]    #a
    print o[3][0] #d1
    # 索引访问
    print(o[0:2])  #
    age=22
    name='sandra'
    print('%s is %d years old'%(name,age)) # sandra is 22 years old
    
    
    修改元组
    元组中的元素值是不允许修改的,但是我们还可以对元组进行拼接
    tup1 = (12, 34.56)
    tup2 = ('abc', 'xyz')
    # 以下修改元组元素操作是非法的。
    # tup1[0] = 100
    # 创建一个新的元组
    tup3 = tup1 + tup2
    print tup3;
    
    
    删除元组
    del tup1
    
    
    添加元组
    #通过切片方法添加
    a=(1,2,3,4,5,6)
    a=a[:2]+(10,)+a[2:] # 在元组的第2个元素后面添加一个元组(10,)
    print(a)  # (1, 2, 10, 3, 4, 5, 6)

    三、数组(Array-numpy)

    1.数组(numpy array)的特点

    准确来说Python中是没有数组类型的,只有列表(list)和元组(tuple), 数组是numpy库中所定义的,所以在使用数组之前必须下载安装numpy库。 python中的list是python的内置数据类型,list中的数据类不必相同的,而array的中的类型必须全部相同。在list中的数据类型保存的是数据的存放的地址,简单的说就是指针,并非数据,这样保存一个list就太麻烦了,例如list1=[1,2,3,'a']需要4个指针和四个数据,增加了存储和消耗cpu。numpy中封装的array有很强大的功能,里面存放的都是相同的数据类型。

    • numpy array 是以方括号“[]”包围的数据集合,不同成员以空格“ ”分隔。如 a=[1 2 3 4]
    • numpy array 的数据成员必须是相同数据类型属性,不同于列表和元组
    • numpy array 数组是可以多维的,而列表和元组是一维的,数组的每个维度之间以换行分隔开,单个维度内的数组成员也以换行分隔开,每个并列(单个)维度内的成员个数需要一致,不同维度的成员个数可以不一样。ru
    • numpy array 通过索引号(下标)来访问数组元素,数组每个维度的元素的起始索引*号为0,如:a[1][1] = 2 , a = [[0 1] ,或者以逗号分隔的整数表示元素的维数和索引,如:arr[1,1]=2

    [1 2]]

    • numpy array 有很多可以直接使用的函数
    • numpy array有形状大小shape,即维度,获取的两种方式np.shape(a) 或者 a.shape,即可得到数组的大小。

    2.数组的创建

    安装numpy库(pip或者conda)

    导入numpy库(通过import关键字导入):import numpy as np

    创建数组的几种方式:

    Numpy 用于处理数组,Numpy中的数组对象称为ndarray,我们使用array()函数创建一个Numpy的ndarray对象,我们可以将列表、元组或者任何类似数组的对象传递给array()方法,array方法会将它们转换为ndarray。

    import numpy as np# 方法一:使用列表创建numpy数组# 列表转数组# 列表中有列表时,转数组时,首先将逗号“,”全部变为空格“ ”,以最外层[]中的逗号“,”以换行分开成为数组的第一维度的不同成员(元素),其他类推
    a =np.array( [[1,2,3],[4,5,6]] )
    print(a)
    # [[1 2 3]
    [4 5 6]]# 方法二 :使用元组创建numpy数组# 元组转数组# 元组中有元组时,转数组时,首先将逗号“,”全部变为空格“ ”,以最外层[]中的逗号“,”以换行分开成为数组的第一维度的不同成员(元素)
    arr = ((1,2),(3,4))
    arr0 =np.array(arr)
    print(arr0)
    # [[1 2]
    [3 4]]

    3.数组中的维

    数组中的维是数组深度(嵌套数组)的一个级别,嵌套数组是将数组作为元素的数组,即数组中有数组。

    (1)0-D维数组0维数组,也称作标量,是指数组中只有一个元素,数组的值只有一个
    a= 61
    arr = np.array(a)
    print(a) # 61
    print(type(arr)) # <class 'numpy.ndarray'>
    print(arr.shape) # ()(2)1-D维数组 一维数组,是指元素为0-D数组的数组,也就是由多个元素值构成的数组
    a = [61,62,63]
    arr = np.array(a)
    print(arr) # [61 62 63]
    print(arr.type) # (3,)(3)2-D维数组 二维数组,它的元素为一维数组,它是一维数组的数组,通常用于表示矩阵或者二阶张量,在Numpy库中又一个专门用于矩阵运算的完整子模块,numpy.mat。
    arr = np.array([[1, 2, 3], [4, 5, 6]]) # 列表转数组,数组的第一维度元素以最外层列表元素以行分隔
    print(arr) # [[1 2 3]
    [4 5 6]](3)3-D维数组 三维数组,它的元素为二维数组,它是二维数组的数组。 # 用两个二维数组,创建一个三维数组
    arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
    print(arr) # [[[ 1 2 3]
    [ 4 5 6]]
    [[7 8 9]
    [10 11 12]]]
    print(arr.shape) # (2,2,3) # 数组每个维度的元素个数是shape的由外到内,如:第一维2个元素是:[[ 1 2 3] 和 [[7 8 9]
    [ 4 5 6]] [10 11 12]](4)如何得到数组的维数?NumPy 数组提供了 ndim 属性,该属性返回一个整数,该整数会告诉我们数组有多 少维,检查数组有多少维:
    a = np.array(42)
    b = np.array([1, 2, 3, 4, 5])
    c = np.array([[1, 2, 3], [4, 5, 6]])
    d = np.array([[[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]])
    print(a.ndim) # 0
    print(b.ndim) # 1
    print(c.ndim) # 2
    print(d.ndim) # 3(5)创建更高维的数组数组可以拥有任意数量的维,在创建数组时,可以使用 ndmin 参数定义维数。 # 创建一个有5个维度的数组,并验证它拥有5个维度:
    arr = np.array([1, 2, 3, 4], ndmin=)
    print(arr) # [[[[[1 2 3 4]]]]]
    print('number of dimensions :', arr.ndim) # number of dimensions : 5说明:在这个5维数组中,最里面的一维,也就是第5个维度,有4个元素1234,第四个维度 有1个元素作为向量[1 2 3 4],第三个维度的元素是矩阵[[1 2 3 4]],也就是元素为2维数组,第2维度有1个元素是3维数组,第一个维度有1个元素,该元素是四维数组。

    4.数组中的索引和裁切

    (1)访问数组元素
     数组索引等同于访问数组元素,我们通过引用索引号来访问数组元素,Numpy中的数组的索引以0开始,即第一个元素的索引为0.第二个元素的索引为1、
     # 一维数组
     arr = np.array([1, 2, 3, 4])
     print(arr[1]) # 2
    
    
     # 二维数组或者更高维数组
     要访问二维数组或者更高维数组中的元素,我们可以使用逗号分隔的整数表示元素的维数和索引或者用数组的每个维度的索引号。
      arr = np.array([[1,2,3,4,5], [6,7,8,9,10]])
      print(arr[1, 4])  # 10 表示第一维度中的第2个元素(即[6,7,8,9,10])的第5个元素
      或者
      print(arr[1][4]) # 10
      更高维类似
    
    
     # 使用负索引从尾开始访问数组
       arr = np.array([[1,2,3,4,5], [6,7,8,9,10]])
       print(arr[1,-1])  # 10
    
    
    (2)数组的裁切(相当于列表和元组的切片)
     Python中的裁切是指将元素从一个给定的索引带到另一个给定的索引,也就是切片的意思,以冒号“:”来传递,包含开始索引start,但是不包含结束索引end。
     我们像这样定义切片而不是索引:[start:end]。
     我们还可以定义步长,如下所示:[start:end:step]。
     如果我们不设置 start,则将其视为 0,即从索引号为0的元素开始索引。
     如果我们不设置 end,则视为该维度内数组的长度,即一直索引到该维度的最后一个元素。
     如果我们不设置start和end,则视为从索引号0的元素开始一直到最后一个元素
     如果我们不设置 step,则视为 1。
    
    
     # 从下面的数组中裁切索引 1 到索引 5 的元素
     arr = np.array([1, 2, 3, 4, 5, 6, 7])
       print(arr[1:5]) # [2 3 4 5]
       print(arr[:4])  # [1 2 3 4]
     # 设置步长剪切
     print(arr[1:5:2]) # [2 4]
     # 返回数组中相隔的元素
     print(arr[::2]) #[1,3,5,7]
    
    
     # 数组的负裁切
     使用减号运算符从末尾开始引用索引:
       arr = np.array([1, 2, 3, 4, 5, 6, 7])
       print(arr[-3:-1])  # [5 6]
    
    
     # 二维数组的裁切
     # 从第二个元素开始,对从索引 1 到索引 4(不包括)的元素进行切片
     arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
       print(arr[1, 1:4])  # [7 8 9],即 第一维度的第二个元素(即[6, 7, 8, 9, 10])的索引号从1到4(不包括4)的元素
    
    
     #从两个元素中返回索引 2:
       arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
       print(arr[0:2, 2]) # [3 8],即第一维度的第1个元素和第2个元素的各自的索引号为2的元素
    
    
     #从两个元素裁切索引 1 到索引 4(不包括),这将返回一个 2-D 数组:
       arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
       print(arr[0:2, 1:4])  # [[2 3 4] ,即维度的索引从0:2(2不包括)的元素 的各自的索引号从1到
                                        [7 8 9]]
    4(不包括4)的元素
     

    总结:列表和元组都可以转换为数组,列表是可变序列,有增加删除修改元素值的方法,元组是不可序列,列表和元组没有shape属性,它的大小是元素的个数,数组有形状shape,有shape属性,可以通过array.shape获取数组的形状大小shape,不管是列表、元组、数组的索引切片,都是左闭右开形式。我们可以通过print(type(x))来判别X是列表还是元组或者是数组。

    附加:

    # 1.两个列表转数组和数组的转置
    a = [1,2]
    print(len(a))
    b = [3,4]
    print(len([a,b])) # 2 列表元素个数,以最外层的[],中的逗号分开
    
    # 单列表转数组时,将逗号消除
    K = np.array(b)
    print(K)
    
    #显示数组的维度的两种方法: print(np.shape(h)) 或者print(h.shape)
    print(K.shape)
    print(np.shape(K))
    
    # 一维数组转置是其本身
    print(np.array(b).T) 
    
    # 列表中有列表时,转数组时,将逗号消除,每个列表以换行分开
    c = np.array([a,b])
    print(c)
    """
    [[1 2]
    [3 4]]
    
    
    """
    # 二维数组转置行和列交换
    d = c.T
    """
    [[1 3]
    [2 4]]
    """
    print(d)
    
    
    # 2.单个列表转数组
    e = [[ 0,  1,  2,  3,  4],
           [ 5,  6,  7,  8,  9],
           [10, 11, 12, 13, 14],
           [15, 16, 17, 18, 19]]
    print(type(e)) # <class 'list'>
    f = np.array([[ 0,  1,  2,  3,  4],
           [ 5,  6,  7,  8,  9],
           [10, 11, 12, 13, 14],
           [15, 16, 17, 18, 19]])
    print(type(f))  # <class 'numpy.ndarray'>
    print(f)
    """
    [[ 0  1  2  3  4]
    [ 5  6  7  8  9]
    [10 11 12 13 14]
    [15 16 17 18 19]]
    
    
    """
    # 数组的转置 行变成列 列变成行
    print(f.T)
    """
    [[ 0  5 10 15]
    [ 1  6 11 16]
    [ 2  7 12 17]
    [ 3  8 13 18]
    [ 4  9 14 19]]
    """
    
    # 3. 列表转数组的拼接
    g = [[10,20]]
    h = [[1,0],[2,0],[3,0],[4,0]]
    score = np.array(g)
    boundingbbox = np.array(h)
    print(score)
    print(boundingbbox)
    print(np.shape(score))
    print(np.shape(boundingbbox))
    print("n")
    
    M = score.T
    N = boundingbbox.T
    print(np.shape(M))
    print(np.shape(N))
    print(M)
    print(N)
    # np.concatenate() 数组拼接
    # 进行列堆叠的时候要保证两个数组的行维度元素个数相同
    # 进行行堆叠的时候要保证两个数组的列维度元素个数相同
    rectangles = np.concatenate((N,M), axis=1)
    print(rectangles)

    f7a0956e0c8be7afe79ed798e3cd9c21.png

    更多有关python、深度学习和计算机编程和电脑知识的精彩内容,可以关注微信公众号:码农的后花园

    d13f0790dafeefffd878d914ff3afbdb.png
    展开全文
  • :什么是卷积 ...假设g(i)是一维的函数,而且代表的样本数为G = [1,2,3,4,5,6,7,8,9] 假设C(k)是一维的卷积操作数, 操作数为C=[-1,0,1] 则输出结果f(x)可以表示为 F=[1,2,2,2,2,2,...

    一:什么是卷积

    离散卷积的数学公式可以表示为如下形式:

    f(x) =  - 其中C(k)代表卷积操作数,g(i)代表样本数据, f(x)代表输出结果。

    举例如下:

    假设g(i)是一个一维的函数,而且代表的样本数为G = [1,2,3,4,5,6,7,8,9]

    假设C(k)是一个一维的卷积操作数, 操作数为C=[-1,0,1]

    则输出结果f(x)可以表示为 F=[1,2,2,2,2,2,2,2,1]  //边界数据未处理

     

    以上只是一维的情况下,当对一幅二维数字图像加以卷积时,其数学意义可以解释如下:

    源图像是作为输入源数据,处理以后要的图像是卷积输出结果,卷积操作数作为Filter

    在XY两个方向上对源图像的每个像素点实施卷积操作。如图所示:

     

    粉红色的方格每次在X/Y前进一个像素方格,就会产生一个新的输出像素,图中深蓝色的代

    表要输出的像素方格,走完全部的像素方格,就得到了所有输出像素。

     

    图中,粉红色的矩阵表示卷积操作数矩阵,黑色表示源图像– 每个方格代表一个像素点。

     

    二:卷积在数字图像处理中应用

    一副数字图像可以看作一个二维空间的离散函数可以表示为f(x, y), 假设有对于二维卷积操

    作函数C(u, v) ,则会产生输出图像g(x, y) = f(x, y) *C(u,v), 利用卷积可以实现对图像模糊处理,边缘检测,产生轧花效果的图像。

     

    一个简单的数字图像卷积处理流程可以如下:

    1.      读取源图像像素

    2.      应用卷积操作数矩阵产生目标图像

    3.      对目标图像进行归一化处理

    4.      处理边界像素

    使用模板处理图像相关概念:     

          模板:矩阵方块,其数学含义是一种卷积运算。
          卷积运算:可看作是加权求和的过程,使用到的图像区域中的每个像素分别于卷积核(权矩阵)的每个元素对应相
                    乘,所有乘积之和作为区域中心像素的新值。
          卷积核:卷积时使用到的权用一个矩阵表示,该矩阵与使用的图像区域大小相同,其行、列都是奇数,
                  是一个权矩阵。
          卷积示例:
                  3 * 3 的像素区域R与卷积核G的卷积运算:
                  R5(中心像素)=R1G1 + R2G2 + R3G3 + R4G4 + R5G5 + R6G6 + R7G7 + R8G8 + R9G9
                

    四使用模板处理图像的问题:
           边界问题:当处理图像边界像素时,卷积核与图像使用区域不能匹配,卷积核的中心与边界像素点对应,
                     卷积运算将出现问题。
           处理办法:
                  A. 忽略边界像素,即处理后的图像将丢掉这些像素。
                  B. 保留原边界像素,即copy边界像素到处理后的图像。

    五.常用模板:


     

    六其他

     

    -----------------------------------------------------------------------------------------------------------

     以下用$符号表示从负无穷大到正无穷大的积分。   
        
      一维卷积:   
      y(t)=g(k)*x(k)=$g(k)x(t-k)   
      先把函数x(k)相对于原点反折,然后向右移动距离t,然后两个函数相乘再积分,就得到了在t处的输出。对每个t值重复上述过程,就得到了输出曲线。   
        
      二维卷积:   
      h(x,y)=f(u,v)*g(u,v)=$$f(u,v)g(x-u,y-v)   
      先将g(u,v)绕其原点旋转180度,然后平移其原点,u轴上像上平移x,   v轴上像上平移y。然后两个函数相乘积分,得到一个点处的输出。   

    在图像中卷积是什么意思呢,就是图像就是图像f(x),模板是g(x),然后将模版g(x)在模版中移动,每到一个位置,就把f(x)与g(x)的定义域相交的元素进行乘积并且求和,得出新的图像一点,就是被卷积后的图像.模版又称为卷积核.卷积核做一个矩阵的形状。由于大多数模板都是对称的,所以模板不旋转。 

     

    二维图像卷积运算

    import numpy as np
    from scipy import signal
    from scipy import misc
    import matplotlib.pyplot as plt
    face=misc.face(gray=True) #创建一个灰度图像
    scharr=np.array([[-3-3j,0-10j,+3-3j],
            [-10+0j,0+0j,+10+0j],
             [-3+3j,0+10j,+3+3j]]) #设置一个特殊的卷积和
    grad=signal.convolve2d(face,scharr,boundary='symm',mode='same') #把图像的face数组和设计好的卷积和作二维卷积运算,设计边界处理方式为symm
    fig,(ax1,ax2)=plt.subplots(1,2,figsize=(10,6)) #建立1行2列的图fig
    ax1.imshow(face,cmap='gray') #显示原始的图
    <matplotlib.image.AxesImage object at 0x00000000078FC198>
     ax1.set_axis_off() #不显示坐标轴
     ax2.imshow(np.absolute(grad),cmap='gray') #显示卷积后的图
    <matplotlib.image.AxesImage object at 0x00000000078FCE48>
     ax2.set_axis_off() #不显示坐标轴
     fig.show() #显示绘制好的画布

     

    转载于:https://www.cnblogs.com/yanghelin/p/8025820.html

    展开全文
  • 称作2D投影空间。齐次矢量 x ~ \widetilde x x 可以通过除以最后个元素 w ~ \widetilde w w 转换为非齐次矢量 x x x ,即 x ~ = ( x ~ , y ~ , w ~ ) = w ~ ( x , y , 1 ) = w ~ x ˉ \widetilde x = (\widetilde ...

    前言

    本博客为主要学习《视觉SLAM十四讲》第3讲、《机器人学的状态估计》第6章三位几何学基础、《计算机视觉-算法和应用》第2章2.1几何基元变换等SLAM内容的总结与整理。
    主要包括:
    1、点、向量、坐标系、直线、平面等几何学基础
    2、旋转矩阵、角轴、欧拉角、四元数等表示坐标系旋转的方法,罗德里格斯公式的证明,四元数左乘右乘、导数的推导
    3、2D、3D空间的欧式、相似、仿射、射影变换性质


    1、几何学基础

    1.1 点

    2D点,如图像中的像素坐标,可以用一对数值表示: x = ( x , y ) ∈ R 2 x =(x,y) \in \mathbf R^2 x=(x,y)R2
    也可以用齐次坐标表示:
    x ~ = ( x ~ , y ~ , w ~ ) ∈ P 2 \widetilde x = (\widetilde x,\widetilde y,\widetilde w) \in \mathbf P^2 x =(x ,y ,w )P2

    其中仅在尺度上不同的矢量被视为等同的。 P 2 = R 3 − ( 0 , 0 , 0 ) \mathbf P^2=\mathbf R^3-(0,0,0) P2=R3(0,0,0)称作2D投影空间。齐次矢量 x ~ \widetilde x x 可以通过除以最后一个元素 w ~ \widetilde w w 转换为非齐次矢量 x x x,即 x ~ = ( x ~ , y ~ , w ~ ) = w ~ ( x , y , 1 ) = w ~ x ˉ \widetilde x = (\widetilde x,\widetilde y,\widetilde w)=\widetilde w(x,y,1)=\widetilde w \bar x x =(x ,y ,w )=w (x,y,1)=w xˉ x ˉ \bar x xˉ成为增广矢量。

    3D点,也可以写成非齐次坐标 x = ( x , y , z ) ∈ R 3 x =(x,y,z) \in \mathbf R^3 x=(x,y,z)R3或齐次坐标 x ~ = ( x ~ , y ~ , z ~ , w ~ ) = w ~ ( x , y , z , 1 ) ∈ P 3 \widetilde x = (\widetilde x,\widetilde y,\widetilde z,\widetilde w) =\widetilde w(x,y,z,1)\in \mathbf P^3 x =(x ,y ,z ,w )=w (x,y,z,1)P3

    1.2 向量与坐标系

    向量是线性空间中的一个元素,可以想象成从原点指向某处的一个箭头。只有当指定三维空间的坐标系时,才存在向量在此坐标系下的坐标。例如确定了三维空间中坐标系 ( e 1 , e 2 , e 3 ) (e_1,e_2,e_3) (e1,e2,e3),向量在这组基下的坐标为:

    a = [ e 1 , e 2 , e 3 ] [ a 1 a 2 a 3 ] = a 1 e 1 + a 2 e 2 + a 3 e 3 a=[e_1,e_2,e_3]\left[ \begin{matrix} a_1 \\a_2\\a_3 \end{matrix} \right]=a_1e_1+a_2e_2+a_3e_3 a=[e1,e2,e3]a1a2a3=a1e1+a2e2+a3e3

    坐标系通常由3个正交的坐标系组成。右手坐标系即给定x轴和y轴时,z轴的方向可以通过右手法则由 x × y x\times y x×y定义。

    向量内积:
    a ⋅ b = a T b = ∑ i = 1 3 a i b i = ∣ a ∣ ∣ b ∣ c o s &lt; a , b &gt; a \cdot b = a^Tb=\sum_{i=1}^{3}a_ib_i=|a||b|cos&lt;a,b&gt; ab=aTb=i=13aibi=abcos<a,b>

    向量外积
    a × b = ∥ i j k a 1 a 2 a 3 b 1 b 2 b 3 ∥ = [ a 2 b 3 − a 3 b 2 a 3 b 1 − a 1 b 3 a 1 b 2 − a 2 b 1 ] = [ 0 − a 3 a 2 a 3 0 − a 1 − a 2 a 1 0 ] b ≜ a ∧ b a \times b=\left\| \begin{matrix} i&amp;j&amp;k \\a_1&amp;a_2&amp;a_3\\b_1&amp;b_2&amp;b_3 \end{matrix} \right\|=\left[ \begin{matrix} a_2b_3-a_3b_2 \\a_3b_1-a_1b_3\\a_1b_2-a_2b_1 \end{matrix} \right]=\left[ \begin{matrix} 0&amp;-a_3&amp;a_2 \\a_3&amp;0&amp;-a_1\\-a_2&amp;a_1&amp;0 \end{matrix} \right]b \triangleq a^\land b a×b=ia1b1ja2b2ka3b3=a2b3a3b2a3b1a1b3a1b2a2b1=0a3a2a30a1a2a10bab

    引入^符号,将a写成一个反对称矩阵,将向量的外积转变为向量与矩阵的乘法。外积只对向量存在定义。

    在三维几何中,向量a和向量b的外积结果是垂直于a和b向量构成平面的法向量,大小为向量a和向量b构成的平行四边形的面积。

    1.3 2D直线

    2D直线也可以用齐次坐标表达 l ~ = ( a , b , c ) \widetilde l=(a,b,c) l =(a,b,c)。对应的直线方程为:
    x ˉ l ~ = a x + b y + c = 0 \bar x \widetilde l=ax+by+c=0 xˉl =ax+by+c=0

    也可以规范化直线方程,使得
    l = ( n ^ x , n ^ y , d ) = ( n ^ , d ) , ∣ ∣ n ^ ∣ ∣ = 1 l=(\hat n_x,\hat n_y,d)=(\hat n,d),||\hat n||=1 l=(n^x,n^y,d)=(n^,d)n^=1

    此时 n ^ \hat n n^是垂直于直线的法向量,d是其到原点的距离。但是这样有个例外,就是无穷远处的直线 l ~ = ( 0 , 0 , 1 ) \widetilde l=(0,0,1) l =(0,0,1),它包含了所有无穷远处的点。

    使用齐次坐标系,可以计算两条直线的角点:
    x ~ = l ~ 1 × l ~ 2 \widetilde x=\widetilde l_1 \times \widetilde l_2 x =l 1×l 2

    计算两点的直线:
    l ~ = x ~ 1 × x ~ 2 \widetilde l = \widetilde x_1 \times \widetilde x_2 l =x 1×x 2

    点到直线的距离
    1)对于点 ( x 0 , y 0 ) (x_0,y_0) (x0,y0),到直线 a x + b y + c = 0 ax+by+c=0 ax+by+c=0的距离d可以如下计算:
    d = ∣ a x 0 + b y 0 + c a 2 + b 2 ∣ d=|\frac{ax_0+by_0+c}{\sqrt{a^2+b^2}}| d=a2+b2 ax0+by0+c

    2)对于点A、B、C,求点A到直线BC的距离还可以这样算:
    d = ∣ A B × B C ∣ ∣ B C ∣ d=\frac{|AB \times BC|}{|BC|} d=BCAB×BC

    1.4 3D平面

    3D平面也可以表达为齐次坐标 m ^ = ( a , b , c , d ) \hat m=(a,b,c,d) m^=(a,b,c,d),对应的平面方程为:
    x ˉ ⋅ m ^ = a x + b y + c z + d = 0 \bar x \cdot \hat m=ax +by+cz+d=0 xˉm^=ax+by+cz+d=0

    也可以规范化平面方程,使得
    l = ( n ^ x , n ^ y , n ^ z , d ) = ( n ^ , d ) , ∣ ∣ n ^ ∣ ∣ = 1 l=(\hat n_x,\hat n_y,\hat n_z,d)=(\hat n,d),||\hat n||=1 l=(n^x,n^y,n^z,d)=(n^,d)n^=1

    此时 n ^ \hat n n^是垂直于平面的法向量,d是其到原点的距离。同样有个例外,就是无穷远处的平面 l ~ = ( 0 , 0 , 0 , 1 ) \widetilde l=(0,0,0,1) l =(0,0,0,1),它包含了所有无穷远处的点。

    点到平面的距离
    1)对于点 ( x 0 , y 0 ) (x_0,y_0) (x0,y0),到平面 a x + b y + c z + d = 0 ax+by+cz+d=0 ax+by+cz+d=0的距离d可以如下计算:
    d = ∣ a x 0 + b y 0 + c z 0 + d a 2 + b 2 + c 2 ∣ d=|\frac{ax_0+by_0+cz_0+d}{\sqrt{a^2+b^2+c^2}}| d=a2+b2+c2 ax0+by0+cz0+d

    2)对于点A、B、C、D,求点A到平面BCD的距离还可以这样算:
    d = ∣ ( B C × B D ) ⋅ A B ∣ ∣ B C × B D ∣ d=\frac{|(BC \times BD)\cdot AB|}{|BC \times BD|} d=BC×BD(BC×BD)AB

    1.5 3D直线

    3D的直线表达可以用直线上的两个点 ( p , q ) (p,q) (p,q),直线上的其他点可以表示为这两个点的线性组合:
    r = ( 1 − λ ) p + λ q , r ~ = ( 1 − λ ) p ~ + λ q ~ r=(1-\lambda)p+\lambda q,\widetilde r=(1-\lambda)\widetilde p+\lambda \widetilde q r=(1λ)p+λqr =(1λ)p +λq

    一种特殊情况是当第二个点位于无穷远时,即 q ~ = ( d ^ x , d ^ y , d ^ z , 0 ) = ( d ^ , 0 ) \widetilde q=(\hat d_x,\hat d_y,\hat d_z,0)=(\hat d,0) q =(d^x,d^y,d^z,0)=(d^,0)。这里 d ^ \hat d d^即为直线的方向。可以讲非齐次坐标的3D直线方程重写为:
    r = p + λ q ^ r=p+\lambda \hat q r=p+λq^


    2、旋转表示方法

    2.1 旋转矩阵与欧式变换

    假设某个单位正交基 ( e 1 , e 2 , e 3 ) (e_1,e_2,e_3) (e1,e2,e3)经过一次旋转变成了 ( e 1 ′ , e 2 ′ , e 3 ′ ) (e&#x27;_1,e&#x27;_2,e&#x27;_3) (e1,e2,e3),对于同一个向量a,它在两个坐标系下的坐标为 [ a 1 , a 2 , a 3 ] T [a_1,a_2,a_3]^T [a1,a2,a3]T [ a 1 ′ , a 2 ′ , a 3 ′ ] T [a&#x27;_1,a&#x27;_2,a&#x27;_3]^T [a1,a2,a3]T,有:
    [ e 1 , e 2 , e 3 ] [ a 1 a 2 a 3 ] = [ e 1 ′ , e 2 ′ , e 3 ′ ] [ a 1 ′ a 2 ′ a 3 ′ ] [e_1,e_2,e_3]\left[ \begin{matrix} a_1 \\a_2\\a_3 \end{matrix} \right]=[e&#x27;_1,e&#x27;_2,e&#x27;_3]\left[ \begin{matrix} a&#x27;_1 \\a&#x27;_2\\a&#x27;_3 \end{matrix} \right] [e1,e2,e3]a1a2a3=[e1,e2,e3]a1a2a3

    [ a 1 a 2 a 3 ] = [ e 1 T e 1 ′ e 1 T e 2 ′ e 1 T e 3 ′ e 2 T e 1 ′ e 2 T e 2 ′ e 2 T e 3 ′ e 3 T e 1 ′ e 3 T e 2 ′ e 3 T e 3 ′ ] [ a 1 ′ a 2 ′ a 3 ′ ] ≜ R a ′ \left[ \begin{matrix} a_1 \\a_2\\a_3 \end{matrix} \right]=\left[ \begin{matrix}e_1^Te&#x27;_1 &amp; e_1^Te&#x27;_2&amp;e_1^Te&#x27;_3\\e_2^Te&#x27;_1 &amp; e_2^Te&#x27;_2&amp;e_2^Te&#x27;_3\\e_3^Te&#x27;_1 &amp; e_3^Te&#x27;_2&amp;e_3^Te&#x27;_3\end{matrix} \right] \left[ \begin{matrix} a&#x27;_1 \\a&#x27;_2\\a&#x27;_3 \end{matrix} \right] \triangleq Ra&#x27; a1a2a3=e1Te1e2Te1e3Te1e1Te2e2Te2e3Te2e1Te3e2Te3e3Te3a1a2a3Ra

    旋转矩阵R为行列式为1的正交矩阵,其集合定义如下:
    S O ( n ) = { R ∈ R n × n ∣ R R T = I , d e t ( R ) = 1 } SO(n)=\{R∈R^{n\times n}|RR^T=I,det(R)=1\} SO(n)={RRn×nRRT=I,det(R)=1}

    SO(n)为特殊正交群(Special Orthogonal Group)。

    欧拉旋转定理:刚体在三维空间里的一般运动可以分解为刚体上方某一点的平移,和绕经过此点的旋转轴的转动。

    欧式变换可以使用旋转矩阵R和平移向量t完整地描述:
    a ′ = R a + t a&#x27;=Ra+t a=Ra+t

    引入齐次坐标,重写变换矩阵为:
    [ a ′ 1 ] = [ R T 0 T 1 ] [ a 1 ] ≜ T [ a 1 ] \left[ \begin{matrix} a&#x27; \\1 \end{matrix} \right] =\left[ \begin{matrix} R&amp;T\\0^T&amp;1 \end{matrix} \right]\left[ \begin{matrix} a \\1 \end{matrix} \right] \triangleq T\left[ \begin{matrix} a \\1 \end{matrix} \right] [a1]=[R0TT1][a1]T[a1]

    变换矩阵T又被称为特殊欧式群(Special Euclidean Group):
    S E ( 3 ) = { T = [ R t 0 T 1 ] ∈ R 4 × 4 ∣ R ∈ S O ( 3 ) , t ∈ R 3 } SE(3)=\{T=\left[ \begin{matrix} R&amp;t\\0^T&amp;1 \end{matrix} \right]\in R^{4\times 4}|R\in SO(3),t \in R^3\} SE(3)={T=[R0Tt1]R4×4RSO(3),tR3}

    变换矩阵的逆为: [ R T − R T t 0 T 1 ] \left[ \begin{matrix} R^T&amp;-R^Tt\\0^T&amp;1 \end{matrix} \right] [RT0TRTt1]

    习惯上我们采用旋转矩阵 R 12 R_{12} R12或者 R 2 1 R^1_2 R21表示从坐标系2到坐标系1的旋转矩阵:
    a 1 = R 12 a 2 a_1=R_{12}a_2 a1=R12a2


    对SLAM来说,我们会用到相机坐标系和世界坐标系。

    T w c T_{wc} Twc表示相机坐标系到世界坐标系的变换,常用来表示相机的位姿,因为更加直观:其平移部分是相机原点在世界坐标系下的坐标:
    p w = T w c p c = T w c 0 = t w c p_w=T_{wc} p_c=T_{wc} 0=t_{wc} pw=Twcpc=Twc0=twc

    T c w T_{cw} Tcw表示世界坐标系到相机坐标系的变换,在SLAM输出的结果中更加常用。

    假设世界坐标系到相机坐标系的变换Rt,相机中心在世界坐标系中的位置:

    R p w + t = p c = 0 ⇒ p w = − R T t Rp_w+t=p_c=0\Rightarrow p_w=-R^Tt Rpw+t=pc=0pw=RTt

    相机朝向(Z轴)在世界坐标系下的方向为:
    r c = Z c − O c a m c , Z c = ( 0 , 0 , 1 ) T , O c a m c = ( 0 , 0 , 0 ) T r^c=Z^c-O^c_{cam},Z^c=(0,0,1)^T,O^c_{cam}=(0,0,0)^T rc=ZcOcamc,Zc=(0,0,1)T,Ocamc=(0,0,0)T

    r w = ( R T Z c − R T t ) − ( R T O c a m c − R T t ) = R T ( 0 0 1 ) r^w=(R^TZ^c-R^Tt)-(R^TO^c_{cam}-R^Tt)=R^T \left( \begin{matrix} 0\\0\\1 \end{matrix} \right) rw=(RTZcRTt)(RTOcamcRTt)=RT001

    即旋转矩阵的第三行。


    2.2 旋转向量

    任意旋转可以用一个旋转轴和一个旋转角表示。定义旋转轴为单位向量 n = [ a 1 , a 2 , a 3 ] T n=[a_1,a_2,a_3]^T n=[a1,a2,a3]T,满足:
    n T n = a 1 2 + a 2 2 + a 3 2 = 1 n^Tn=a^2_1+a^2_2+a^2_3=1 nTn=a12+a22+a32=1

    定义旋转角为 θ \theta θ,得到三维的旋转向量 θ n \theta n θn(或角轴Angle-Axis)来描述旋转。

    从旋转向量到旋转矩阵的转换有罗德里格斯公式
    R = c o s θ I + ( 1 − c o s θ ) n n T + s i n θ n ∧ R=cos\theta I+(1-cos\theta)nn^T+sin \theta n^{\land} R=cosθI+(1cosθ)nnT+sinθn


    罗德里格斯公式的证明:
    假设初始向量 v v v 绕旋转轴 k k k(单位向量) 旋转 θ \theta θ 角得到 v r o t v_{rot} vrot
    在这里插入图片描述
    对v进行向量分解: v = v ⊥ + v ∥ v = v_{\perp} +v_{\parallel} v=v+v,其中 v ∥ = ( v ⋅ k ) k v_{\parallel} = (v\cdot k)k v=(vk)k

    由旋转过程平行向量不变性得: v r o t ∥ = v ∥ v_{rot\parallel}=v_{\parallel} vrot=v

    v r o t ⊥ = c o s θ v ⊥ + ( s i n θ ∣ v ⊥ ∣ ) k × v ⊥ ∣ v ⊥ ∣ = c o s θ v ⊥ + s i n θ k × v v_{rot\perp}=cos\theta v_{\perp} + (sin\theta|v_{\perp}|) k\times \frac{v_{\perp}}{|v_{\perp}|}=cos\theta v_{\perp} + sin\theta k\times v vrot=cosθv+(sinθv)k×vv=cosθv+sinθk×v

    因此

    v r o t = v r o t ∥ + v r o t ⊥ = v ∥ + c o s θ v ⊥ + s i n θ k × v v_{rot}=v_{rot\parallel}+v_{rot\perp}=v_{\parallel}+cos\theta v_{\perp} + sin\theta k\times v vrot=vrot+vrot=v+cosθv+sinθk×v

    = c o s θ v + ( 1 − c o s θ ) ( v ⋅ k ) k + s i n θ k × v =cos\theta v+(1-cos\theta)(v\cdot k)k+ sin\theta k\times v =cosθv+(1cosθ)(vk)k+sinθk×v

    其中 ( v ⋅ k ) k = k ( v ⋅ k ) = k ( k T v ) = k k T v (v\cdot k)k=k(v\cdot k)=k(k^Tv)=kk^Tv (vk)k=k(vk)=k(kTv)=kkTv
    所以 v r o t = c o s θ v + ( 1 − c o s θ ) k k T v + s i n θ k ∧ v = R t v_{rot}=cos\theta v+(1-cos\theta)kk^Tv+ sin\theta k^{\land} v=Rt vrot=cosθv+(1cosθ)kkTv+sinθkv=Rt

    R = c o s θ I + ( 1 − c o s θ ) k k T + s i n θ k ∧ R=cos\theta I +(1-cos\theta)kk^T+ sin\theta k^{\land} R=cosθI+(1cosθ)kkT+sinθk

    如果用叉乘来表示 v ⊥ v_{\perp} v,有: v ⊥ = − k × ( k × v ) v_{\perp}=-k \times(k \times v) v=k×(k×v)

    v r o t = v r o t ∥ + v r o t ⊥ = v ∥ + c o s θ v ⊥ + s i n θ k × v v_{rot}=v_{rot\parallel}+v_{rot\perp}=v_{\parallel}+cos\theta v_{\perp} + sin\theta k\times v vrot=vrot+vrot=v+cosθv+sinθk×v

    = v + ( 1 − c o s θ ) k × ( k × v ) + s i n θ k × v = v+(1-cos\theta) k \times(k \times v)+sin\theta k\times v =v+(1cosθ)k×(k×v)+sinθk×v

    = ( I + ( 1 − c o s θ ) k ∧ k ∧ + s i n θ k ∧ ) v = (I+(1-cos \theta)k^{\land}k^{\land}+sin\theta k^{\land})v =(I+(1cosθ)kk+sinθk)v

    罗德里格斯公式也可以写成:

    R = I + ( 1 − c o s θ ) k ∧ k ∧ + s i n θ k ∧ R=I +(1-cos\theta)k^{\land}k^{\land} +sin\theta k^{\land} R=I+(1cosθ)kk+sinθk


    同时可以得到旋转矩阵到旋转向量的变换:
    两边取迹:

    t r ( R ) = c o s θ t r ( I ) + ( 1 − c o s θ ) t r ( n n T ) + s i n θ t r ( n ∧ ) = 3 c o s θ + 1 − c o s θ = 1 + 2 c o s θ tr(R)=cos\theta tr(I)+(1-cos\theta)tr(nn^T)+sin \theta tr(n^{\land})\\ =3cos\theta+1-cos\theta=1+2cos\theta tr(R)=cosθtr(I)+(1cosθ)tr(nnT)+sinθtr(n)=3cosθ+1cosθ=1+2cosθ

    因此:

    θ = a r c c o s ( t r ( R ) − 1 2 ) \theta=arccos(\frac{tr(R)-1}{2}) θ=arccos(2tr(R)1)

    对于转轴 n n n,由于旋转轴上的向量在旋转后不变,有:
    R n = n Rn=n Rn=n

    因此也可以说,转轴是旋转矩阵的特征值1所对应的特征向量。

    2.3 欧拉角

    欧拉角(Euler Angles),将旋转分解为三个方向上的转动。分解方式有多种,同时根据绕固定轴还是绕旋转后的轴旋转也会有不一样的定义方式。
    比如按Z-Y-X顺序转动得到yaw(偏航角)-pitch(俯仰角)-roll(滚转角),用 [ r , p , y ] T [r,p,y]^T [r,p,y]T表示

    欧拉角的缺点是会遇到万向锁问题:在俯仰角为±90°时,第一次旋转与第三次旋转将使用同一个轴,使得系统丢失一个自由度。这被成为奇异性问题。因此欧拉角不适于插值和迭代,往往用于人机交互中。

    理论可以证明,对于只有三个参数的表示形式,则必然会存在奇异点。所以没有完美的旋转表示形式。

    2.4 四元数

    四元数的相关知识推荐看《Quaternion kinematics for the error-state Kalman filter》,这里只对重要的性质做简单介绍。

    四元数具有一个实部和三个虚部,常用一个标量和一个向量来表示:
    q = q 0 + q 1 i + q 2 j + q 3 k = [ s , v ] T , s = q 0 ∈ R , v = [ q 1 , q 2 , q 3 ] T ∈ R 3 q=q_0+q_1i+q_2j+q_3k=[s,v]^T,s=q_0\in R,v=[q_1,q_2,q_3]^T\in R^3 q=q0+q1i+q2j+q3k=[s,v]Ts=q0Rv=[q1,q2,q3]TR3

    四元数的性质

    这里主要讨论四元数的左右乘和求导。

    四元数的乘法有:
    p ⊗ q = [ s p s q − v p T v q s p v q + s q v p + v p × v q ] = [ p ] L q = [ q ] R p p\otimes q=\left[ \begin{matrix} s_ps_q-v^T_pv_q\\s_pv_q+s_qv_p+v_p \times v_q \end{matrix} \right]=[p]_Lq=[q]_Rp pq=[spsqvpTvqspvq+sqvp+vp×vq]=[p]Lq=[q]Rp

    其中:
    [ p ] L = [ s p − v p T v p s p I + v p ∧ ] = s p I + [ 0 − v p T v p v p ∧ ] , [ p ] R = [ s q − v q T v q s q I − v q ∧ ] = s q I + [ 0 − v q T v q − v q ∧ ] [p]_L=\left[ \begin{matrix} s_p&amp;-v_p^T\\v_p&amp;s_pI+v_p^{\land} \end{matrix} \right]=s_pI+\left[ \begin{matrix} 0&amp;-v_p^T\\v_p&amp;v_p^{\land} \end{matrix} \right],[p]_R=\left[ \begin{matrix} s_q&amp;-v_q^T\\v_q&amp;s_qI-v_q^{\land} \end{matrix} \right]=s_qI+\left[ \begin{matrix} 0&amp;-v_q^T\\v_q&amp;-v_q^{\land} \end{matrix} \right] [p]L=[spvpvpTspI+vp]=spI+[0vpvpTvp][p]R=[sqvqvqTsqIvq]=sqI+[0vqvqTvq]

    注意如果写成虚部在前实部在后的四元数形式,左乘和右乘矩阵的符号有所变化。

    同时有性质:
    [ p ] L [ q ] R = [ q ] R [ p ] L [p]_L[q]_R=[q]_R[p]_L [p]L[q]R=[q]R[p]L

    单位四元数满足: q T q = 1 q^Tq=1 qTq=1

    四元数与旋转

    假设某旋转是绕着单位向量 n = [ n x , n y , n z ] n=[n_x,n_y,n_z] n=[nx,ny,nz]进行角度为 θ \theta θ的旋转,那么四元数可表示为:
    q = [ c o s θ 2 , n x s i n θ 2 , n y s i n θ 2 , n z s i n θ 2 ] T q=[cos\frac{\theta}{2},n_xsin\frac{\theta}{2},n_ysin\frac{\theta}{2},n_zsin\frac{\theta}{2}]^T q=[cos2θ,nxsin2θ,nysin2θ,nzsin2θ]T

    反之:
    θ = 2 a r c c o s q 0 , n = [ q 1 , q 2 , q 3 ] T / s i n θ 2 \theta = 2arccos q_0,n=[q_1,q_2,q_3]^T/sin\frac{\theta}{2} θ=2arccosq0n=[q1,q2,q3]T/sin2θ

    在四元数中,任意的旋转都可以由两个相反的四元数表示。假设空间三维点 p = [ x , y , z ] T ∈ R 3 p=[x,y,z]^T\in R^3 p=[x,y,z]TR3经过轴角 n θ n\theta nθ变为 p ′ p&#x27; p。首先将三维空间点用虚四元数表示:
    p = [ 0 , x , y , z ] T = [ 0 , v ] T p=[0,x,y,z]^T=[0,v]^T p=[0,x,y,z]T=[0,v]T

    用四元数表示旋转:
    q = [ c o s θ 2 , n s i n θ 2 ] , p ′ = q p q − 1 q=[cos\frac{\theta}{2},nsin\frac{\theta}{2}],p&#x27;=qpq^{-1} q=[cos2θ,nsin2θ]p=qpq1

    结果仍为纯虚四元数,虚部的三个分量表示旋转后的3D点坐标。

    四元数的导数

    首先需要注意的是,对于用任何方式表示旋转时,对一个旋转再进行旋转有左乘和右乘两种形式,分别代表不同的意义。

    首先定义四元数的导数有:

    q ˙ ≜ lim ⁡ Δ t → 0 q ( t + Δ t ) − q ( t ) Δ t = lim ⁡ Δ t → 0 q ⊗ Δ q L − q Δ t = lim ⁡ Δ t → 0 Δ q G ⊗ q − q Δ t \dot q\triangleq \lim_{\Delta t \to0}\frac{q(t+\Delta t )-q(t)}{\Delta t }=\lim_{\Delta t \to0}\frac{q\otimes \Delta q_L-q}{\Delta t }=\lim_{\Delta t \to0}\frac{ \Delta q_G\otimes q-q}{\Delta t } q˙Δt0limΔtq(t+Δt)q(t)=Δt0limΔtqΔqLq=Δt0limΔtΔqGqq

    其中 Δ q L \Delta q_L ΔqL表示局部坐标系中的角度扰动,而 Δ q G \Delta q_G ΔqG表示全局(世界)坐标系中的角度扰动。我们实际测量的角速度往往是在物体坐标系下的角速度 w w w(例如VIO中通过IMU陀螺仪获得),故常采用四元数右乘形式。

    测量的角速度可以定义为:

    w L ( t ) ≜ d ϕ L ( t ) d t ≜ lim ⁡ Δ t → 0 Δ ϕ L Δ t w_L(t)\triangleq \frac{d\phi_L(t)}{dt}\triangleq \lim_{\Delta t \to0}\frac{\Delta \phi_L}{\Delta t } wL(t)dtdϕL(t)Δt0limΔtΔϕL

    那么有:

    q ˙ ≜ lim ⁡ Δ t → 0 q ⊗ Δ q L − q Δ t = lim ⁡ Δ t → 0 q ⊗ ( [ 1 Δ ϕ L 2 ] − [ 1 0 ] ) Δ t \dot q \triangleq \lim_{\Delta t \to0}\frac{q\otimes \Delta q_L-q}{\Delta t } = \lim_{\Delta t \to0}\frac{q\otimes (\left[ \begin{matrix} {1}\\ \frac{\Delta \phi_L}{2}\end{matrix} \right]-\left[ \begin{matrix} 1\\ 0\end{matrix} \right])}{\Delta t } q˙Δt0limΔtqΔqLq=Δt0limΔtq([12ΔϕL][10])

    = lim ⁡ Δ t → 0 q ⊗ [ 0 Δ ϕ L 2 ] Δ t = 1 2 q ⊗ [ 0 w L ] =\lim_{\Delta t \to0}\frac{q\otimes \left[ \begin{matrix} {0}\\ \frac{\Delta \phi_L}{2}\end{matrix} \right]}{\Delta t } =\frac{1}{2}q \otimes \left[ \begin{matrix} {0}\\ w_L\end{matrix} \right] =Δt0limΔtq[02ΔϕL]=21q[0wL]

    因此有:

    q ˙ = 1 2 q ⊗ w L = 1 2 Ω ( w L ) q , Ω ( w ) ≜ [ w ] R = [ 0 − w T w − w ∧ ] \dot q=\frac{1}{2}q \otimes w_L=\frac{1}{2} \Omega(w_L)q,\Omega(w) \triangleq [w]_R=\left[ \begin{matrix} 0&amp;-w^T\\w&amp;-w^{\land} \end{matrix} \right] q˙=21qwL=21Ω(wL)qΩ(w)[w]R=[0wwTw]

    如果是左乘形式,即将角速度转换到世界坐标系下,有:

    q ˙ = 1 2 w G ⊗ q \dot q=\frac{1}{2}w_G \otimes q q˙=21wGq

    3、坐标变换性质

    3.1 2D坐标变换

    在这里插入图片描述

    变换矩阵自由度保持图标
    平移 [ I ∣ t ] 2 × 3 [I\vert t]_{2\times3} [It]2×32方向正方形
    欧式 [ R ∣ t ] 2 × 3 [R\vert t]_{2\times3} [Rt]2×33长度旋转的正方形
    相似 [ s R ∣ t ] 2 × 3 [sR\vert t]_{2\times3} [sRt]2×34夹角旋转缩放的正方形
    仿射 [ A ] 2 × 3 [A]_{2\times3} [A]2×36平行性平行四边形
    投影 [ H ~ ] 3 × 3 [\widetilde H]_{3\times3} [H ]3×38直线性四边形

    其中 R = [ c o s θ s i n θ − s i n θ c o s θ ] R=\left[ \begin{matrix} cos\theta &amp; sin\theta \\ -sin\theta &amp;cos\theta \end{matrix} \right] R=[cosθsinθsinθcosθ]

    3.2 3D坐标变换

    变换名称矩阵形式自由度不变性之
    平移变换 [ I t 0 T 1 ] \left[ \begin{matrix}I &amp; t \\0^T &amp;1 \end{matrix} \right] [I0Tt1]3方向
    欧式变换 [ R t 0 T 1 ] \left[ \begin{matrix}R &amp; t \\0^T &amp;1 \end{matrix} \right] [R0Tt1]6长度、体积
    相似变换 [ s R t 0 T 1 ] \left[ \begin{matrix}sR &amp; t \\0^T &amp;1 \end{matrix} \right] [sR0Tt1]7夹角
    仿射变换 [ A t 0 T 1 ] \left[ \begin{matrix}A &amp; t \\0^T &amp;1 \end{matrix} \right] [A0Tt1]12平行性、体积比
    射影变换 [ A t a T v ] \left[ \begin{matrix}A &amp; t \\a^T &amp;v \end{matrix} \right] [AaTtv]15接触平面的相交和相切

    从世界坐标系到相机照片的变换是一个射影变换,如果相机焦距无穷远则为仿射变换。

    展开全文
  • 本文代码实现基本按照《数据结构》课本目录顺序,外加大量的复杂算法实现,篇文章足够。能换你个收藏了吧?
  • 超硬核!数据结构学霸笔记,考试面试吹牛就靠它

    万次阅读 多人点赞 2021-03-26 11:11:21
    1、内部无指向自己的指针才可以第一行先不起名字。 2、内部不能定义自己的,如果能的话那空间不就无限了么。很简单的逻辑 指针我不习惯,还是写Date *比较顺眼 3、有同学没注意:访问结构体里的东西怎么访问? Date...
  • C语言题库()

    千次阅读 多人点赞 2020-12-11 21:05:30
    第一章数据类型与表达式 一.知识点 1.C语言的特点:①语言简洁、紧凑,使用方便、...⑵一个函数包括函数的首部(即函数的第一行)和函数体(即花括号部分); ⑶函数体一般包括声明部分和执行部分; ⑷一个...
  • 数组中某些数字是重复的,但不知道有几个数字是重复的,也不知道个数字重复几次。请找出数组中任意个重复的数字。 Input: {2, 3, 1, 0, 2, 5} Output: 2 解题思路 要求时间复杂度 O(N),空间复杂度 O(1)。因此...
  • 原文:A Comprehensive Survey of Graph Embedding: Problems, Techniques and Applications (arxiv 1709.07604) ...、引言 图自然存在于各种各样的现实世界场景中,例如,社交媒体网络中的社交图/扩散...
  • 结构化数据:也称作行数据,是由二维表结构来逻辑表达和实现的数据,严格地遵循数据格式与长度规范,主要通过关系型数据库进行存储和管理。指具有固定格式或有限长度的数据,如数据库,元数据等。    非结构化数据...
  • 本文解析来源: ... 原英文链接: ... ...Transformer由论文《Attention is All You Need》提出,现在是谷歌云TPU推荐的参考模型。论文相关的Tensorflow的代码可以从GitHub获取,其作为Tensor2Tensor包的部分。哈佛.
  • 图解Transformer(完整版)

    万次阅读 多人点赞 2019-01-17 23:45:25
    审校:百度NLP、龙心尘 ...编者按:前段时间谷歌推出的BERT模型在11项NLP任务中夺得SOTA结果,引爆了整个NLP界。而BERT取得成功的个关键因素是Transformer的强大作用。谷歌的Transformer模型...
  • 第4章 串、数组和广义 下标从1开始 、填空题 1. 零个字符的串 称为空串; 由个或多个空格组成的串 称为空白串。 2. 设S=“A;/document/Mary.doc”,则strlen(s)= 20 , “/”的字符定位的位置为 3 。 3. ...
  • 目录 标准区间 一般区间 数值实验 实验 实验 总结 下节预告 matlab代码 在数值分析中,尤其是有限元刚度矩阵、质量矩阵等的计算中,必然要求如下定积分: \[ I=\int_a...
  • 数据结构课上笔记9

    千次阅读 多人点赞 2018-11-07 21:22:05
    数组:按一定格式排列起来的具有相同类型的数据元素的集合。   二维数组:若维数组中的数据元素又是维数组结构,则称为二维数组。  ...二维数组两种顺序存储方式:以序为主序 (低下标...
  • 聚类算法综述()

    万次阅读 2018-12-09 09:55:49
    对于二维点的集合,层次聚类也可以使用嵌套图表示。层次聚类的关键操作是计算两个簇之间的邻近度,并且正是簇的邻近性定义区分了我们将讨论的各种凝聚层次技术。簇的邻近性通常用特定的簇类型定义。通常的方法有MIN...
  • 玩转 matlab 之一维 gauss 数值积分公式及matlab源代码

    千次阅读 多人点赞 2019-05-10 22:06:21
    文章目录标准区间一般区间数值实验实验实验总结下节预告matlab代码 在数值分析中,尤其是有限元刚度矩阵、质量矩阵等的计算中,必然要求如下定积分: I=∫abf(x)dx I=\int_a^b f(x)dx I=∫ab​f(x)dx学好...
  • 概念:内存中只有一道程序,该道程序独占整个用户区(次只有个进程可以执行) 特点:无外部碎片,可以采用覆盖技术,有内部碎片,内存利用率极低。 2.固定分配管理 概念:固定分区分配是最简单的种多道程序...
  • 《机器学习实战》学习笔记():k-近邻算法

    千次阅读 多人点赞 2019-08-19 22:36:02
    k-近邻算法(kNN),它的工作原理是:存在个样本数据集合,也称作训练样本集,并且样本集中个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。输入没有标签的新数据后,将新数据的个特征与...
  • Leetcode链表题目总结

    千次阅读 2020-07-28 10:34:06
    给定个链表,两两交换其中相邻的节点,并返回交换后的链表。 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。 示例: 给定 1->2->3->4, 你应该返回 2->1->4->3. 本题需要两两...
  • 、前述 一直以来都想用很简介或者很普通的方式聊下各个算法的前龙后脉,让更多的人都能看懂算法的过程。查看了网上很多博客,不是写的太笼统就是抄来抄去,根本没有阅读的欲望,很是让人浪费时间,也学不到真正...
  • 称作行数据,一般特点是:数据以行为单位,一行数据表示一个实体的信息,每一行数据的属性是相同的。 比如: id name gender phone address 1 ....
  • 计算机级选择题知识点之数据库

    千次阅读 2021-08-17 07:47:53
    写在前面:计算机级选择题涉及数据结构与算法、程序设计基础、数据库设计基础、软件工程基础、计算机系统五大类以及所选科目类所涉及的知识。本文主要包括数据库设计基础部分。 第章:绪论 数据(data) 数据是...
  • 在树形结构中,数据元素之间有明显的层次关系,并且每一层中的数据元素可能和下层的多个元素(子结点)相关,但只能和上层的个元素(父结点)相关; 在图结构中,结点之间的关系是任意的,可以说...
  • 神经网络——最易懂最清晰的篇文章

    万次阅读 多人点赞 2018-08-24 15:43:20
    神经网络是一门重要的机器学习技术。它是目前最为火热的研究方向--深度学习的基础。学习神经网络不仅可以让你掌握一门强大的机器学习方法... 神经网络是种模拟人脑的神经网络以期能够实现类人工智能的机器学习技...
  • 中文题目:基于二维卷积的知识图谱嵌入表示学习 论文作者: Tim Dettmers, Pasquale Minervini, Pontus Stenetorp, Sebastian Riedel 论文出处: The Thirty-Second AAAI Conference on Artificial ...
  • 结构化数据、半结构化数据和非结构化数据分析、...结构化数据也称作行数据,是由二维表结构来逻辑表达和实现的数据,严格地遵循数据格式与长度规范,主要通过关系型数据库进行存储和管理。与结构化数据相对的是不适
  • 大数据生态圈如何入门?

    万次阅读 2022-03-21 15:56:43
    大数据技术已经被应用到各各业,涉及人们生活的方方面面。大数据技术大大提高了数据存储和计算能力,从而为企业快速决策提供了数据支撑,能够助力企业改进业务流程、控制成本、提高产品质量,应用大数据技术为企业...
  • 【Java从入门到天黑|04】JavaSE入门之数组

    千次阅读 多人点赞 2021-05-25 00:03:40
    关于数组我们可以把它看作是个类型的所有数据的个集合,并用个数组下标来区分或指定每一个数,例如个足球队通常会有几十个人,但是我们来认识他们的时候首先会把他们看作是某某对的成 员,然后再利用他们的...
  • 其实接触KF已经很久了,听过对应的课程,也跟过参考数进行推导,但总有种感觉,始终在门外,没有醍醐灌顶,融会贯通的感觉,所以还是写篇博客,毕竟通过强行让自己输出一下,也会帮助理解和记忆。 、什么是...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,702
精华内容 5,480
关键字:

二维表的每一行称作