精华内容
下载资源
问答
  •  负数反码,为其原码的符号位不变,其他位取反; 负数补码,是其反码加1。  举例8bit有符号型整数: +34 原码 = 反码 = 补码:00100010 -34 原码 = 10100010,反码 = 11011101,补码 = 11011110  不管是在32...

        正数原码、反码、补码形式一致。 

        负数反码,为其原码的符号位不变,其他位取反; 负数补码,是其反码加1。

        举例8bit有符号型整数:

    +34 原码 = 反码 = 补码:00100010
    -34  原码 = 10100010,反码 = 11011101,补码 = 11011110

         不管是在32还是在64位编译器处理下,int都是4字节32位,所以整数范围是-2147483648 ~ 2147483647,数值以补码形式存储。
    【注意】最小负数-2147483648 = -2 31 并没有原码和反码,只有补码,由 -0 的原码 1 0...0(31个0)表示 。

    因此:
    1、~i:对每一位取反运算
        为 01...1(31个1),是正数,补码即原码,即2 31-1 = 2147483647;
    2、 -i:对该数求补运算,即每位取反运算,再加1。
        取反, 10...0(31个0)-> 01...1(31个1),再加1得 10...0(31个0), 该补码表现为最小负数-2147483648,并没有原码和反码;
    3、1-i:补码形式相加,再推回原码得十进制结果。
        即-i( 10...0(31个0) )+( 0 ...1(31个0) )= 10...1(30个0),此为补码形式, 补码转原码为补码减1,再非符号位取反,即原码 1...1(32个1)= -(2 31-1) = - 2147483647
    4、 -1-i :补码形式相加,再推回原码得十进制结果。
        即-i( 10...0(31个0) )+( 1 ...1(32个1) )= 01...1(31个1),是正数形式,原码即补码,为2 31-1= 2147483647 。

    源程序如下:
    #include "stdio.h"
    
    #define INT_MIN     (-2147483647 - 1) /* minimum (signed) int value */
    
    int main()
    {
    	/*int i = -2147483648;*/	//error C4146: 一元负运算符应用于无符号类型,结果仍为无符号类型
    	int i = INT_MIN;
    	printf("%d,%d,%d,%d\r\n", ~i, -i, 1 - i, -1 - i);
    
    	return 0;
    }
    运行结果如下:









    展开全文
  • 如何 利用图像特征检测与匹配获得高质量的路标,关系到单目视觉SLAM的鲁棒性。 图像特征可分为:点特征、直线特征、边缘、轮廓 相比于其他,点特征具有对遮挡相对鲁棒,识别性好,提取速度快。点特征的检测和匹配...

    2.1 特征的检测与匹配

    SLAM系统中,是以环境中的路标点为基础的。

    单目视觉系统无法从单帧图像恢复深度。如何 利用图像特征检测与匹配获得高质量的路标,关系到单目视觉SLAM的鲁棒性。

    图像特征可分为:点特征、直线特征、边缘、轮廓

    相比于其他,点特征具有对遮挡相对鲁棒,识别性好,提取速度快。点特征的检测和匹配来实现SLAM数据关联。

    2.1.1 角点特征

    角点在保留图像重要特征时,可以有效减少信息数据量,使其信息含量很高,有效提高计算速度,有利于图像可靠匹配,有利于实时。

    Harris角点:

    • Harris角点是Harris在1988年提出的一种基于信号的点特征提取算子,前身是Moravec 算子。
    • Harris角点使用自相关矩阵 改进了Moravex方法, 避免了使用离散的方向和偏移,它在窗口内使用高斯函数加权导数,取代了简单的求和。
    • 如果自相关矩阵有2个较大的特征值就表示该店为检测到的特征点。
    • 但其对亮度和对比度变化不敏感,具有旋转不变形,不具备尺度不变形。

    Shi-Tomasi角点:

    • Shi1994年 采用不同的响应函数来提取图像角点,其方式是如果2个特征值中较小的一个大于最小阈值,则判定为角点。
    • Shi的角点判定 方法比较充分,很多情况下都比Harriss算法结果更好

    FAST(features from accelerated segment test)角点:

    • Rosten在2006年提出的一种简单快速的角点检测算法。
    • 该算法检测的角点定义为在像素点的周围邻域内有足够多的像素点与该点处于不同的区域
    • 在灰度图像中,即有足够多的像素点灰度值大于该点的灰度值或者小于该点的灰度值
    • 由于FAST算法能在短时间生成大量角点,因此广泛用于实时性较高的SLAM系统中。

    2.1.2 SIFT和SURF特征

    SIFT(scale invariant feature transform)方法:

    • SIFT是Lowe在1999年提出的一种特征点提取方法。
    • SIFT特征对图像的尺度变化、图像缩放、旋转甚至仿射变换具有不变形
    • 对光照变换和图像变形具有较强的适应性
    •  首先检测由高斯差分构建的尺度空间上的局部极值点,并将其作为候选特征点,排除不太稳定的和对比度低的,从而确定关键点,接下来 为关键点分配方向,并通过采样关键点周围图像块图像梯度的幅值和方向来建立SIFT特征描述子
    • 由于SIFT特征提取和匹配存在大量的浮点运算,时间 复杂度较高,不能保证实时性,因此在单目SLAM应用不多
    • 利用GPU加速后克服了浮点运算,因此有一些GPU-SIFT作为特征检测和匹配方法。

    SURF(speeded up robust features)方法:

    • 是对SIFT的改进,基本结构、步骤与SIFT相近
    • 速度快,且稳定性高,广泛应用

    2.1.3 BRIEF与ORB特征

    BRIEF(binary robust independent elementary features)特征:

    •  Calonder在2010年提出的可以快速计算且表达方式为二进制编码的描述子
    • 主要思路是在特征点附近随机选取若干点对,将这些点对的灰度值的大小,组合成一个长为256 的二进制串,并将这个二进制串作为该特征点的特征描述子。由于其描述子利用二进制编码,因此在特征匹配时只需计算2 个特征点描述子的Hamming 距离。经过大量实验数据测试,不匹配特征点的描述子的Hamming 距离在128 左右,匹配点对描述子的Hamming 距离则远小于128。由于BRIEF 的匹配速度远高于SURF 和SIFT,因此被很多系统采用。

    ORB(oriented brief)特征:

    • 由于BRIEF 特征不具备旋转不变性,因此很难用于旋转比较剧烈的环境。
    • 为了解决这一问题,EthanRublee在2011 年提出了ORB( oriented brief)特征,较好地解决了尺度不变性。
    • 在尺度变化不大的环境,ORB 特征在SLAM 系统中获得了大量应用 
    展开全文
  • 5.利用灰度质心计算ORB特征点方向,实现旋转不变性利用灰度质心计算ORB特征点方向,实现旋转不变性ComputeKeyPointOctTree 跳转 computeOrientationcomputeOrientation 跳转 IC_Angle补 : 灰度质心法IC_Angle 结束 ...

    均匀化之后

    • scaledPatchSize 表示当前金字塔层缩放倍数
    • nkps 表示保留的特征点数目

    将保留的特征点统一成当前金字塔层的坐标,即加上minBorderX,Y

            //PATCH_SIZE是对于底层的初始图像来说的,现在要根据当前图层的尺度缩放倍数进行缩放得到缩放后的PATCH大小 和特征点的方向计算有关
            const int scaledPatchSize = PATCH_SIZE*mvScaleFactor[level];
    
            // Add border to coordinates and scale information
            //获取剔除过程后保留下来的特征点数目
            const int nkps = keypoints.size();
            //然后开始遍历这些特征点,恢复其在当前图层图像坐标系下的坐标
            for(int i=0; i<nkps ; i++)
            {
                //对每一个保留下来的特征点,恢复到相对于当前图层“边缘扩充图像下”的坐标系的坐标
                keypoints[i].pt.x+=minBorderX;
                keypoints[i].pt.y+=minBorderY;
                //记录特征点来源的图像金字塔图层
                keypoints[i].octave=level;
                //记录计算方向的patch,缩放后对应的大小, 又被称作为特征点半径
                keypoints[i].size = scaledPatchSize;
            }
        }
    

    使用computeOrientation计算所有层的特征点的方向

        // compute orientations
        //然后计算这些特征点的方向信息,注意这里还是分层计算的
        for (int level = 0; level < nlevels; ++level)
            computeOrientation(mvImagePyramid[level],   //对应的图层的图像
                               allKeypoints[level],     //这个图层中提取并保留下来的特征点容器
                               umax);                   //以及PATCH的横坐标边界
    }
    

    ComputeKeyPointOctTree 跳转 computeOrientation

    这个函数实际只起到了遍历所有特征点的作用,在每个特征点都调用IC_Angle函数来计算特征点方向

    static void computeOrientation(const Mat& image, vector<KeyPoint>& keypoints, const vector<int>& umax)
    {
        // 遍历所有的特征点
        for (vector<KeyPoint>::iterator keypoint = keypoints.begin(),
             keypointEnd = keypoints.end(); keypoint != keypointEnd; ++keypoint)
        {
            // 调用IC_Angle 函数计算这个特征点的方向
            keypoint->angle = IC_Angle(image,           //特征点所在的图层的图像
                                       keypoint->pt,    //特征点在这张图像中的坐标
                                       umax);           //每个特征点所在图像区块的每行的边界 u_max 组成的vector
        }
    }
    

    computeOrientation 跳转 IC_Angle

    基本原理就是灰度质心法:每个特征点以几何中心P为圆心,画圆,计算出灰度质心Q,则P -> Q就是该特征点的方向.后面比较特征点时,先把方向统一,然后比较特征点描述子,这样特征点就不会因为旋转而不能匹配了

    补 : 灰度质心法

    目的:使特征点具有旋转不变性

    灰度质心:像素集中点

    原理:即使图像旋转,图像几何中心与灰度质心的连线也是随之改变的,可以通过这个方向恢复原始图像

    灰度质心法

    灰度质心法

    输入参数是:

    • image输入图像
    • pt当前特征点坐标
    • u_max是指定一行后的u轴边界坐标
    static float IC_Angle(const Mat& image, Point2f pt,  const vector<int> & u_max)
    {
    

    定义的变量center 表示特征点坐标的指针

        //图像的矩,前者是按照图像块的y坐标加权,后者是按照图像块的x坐标加权
        int m_01 = 0, m_10 = 0;
    
        //获得这个特征点所在的图像块的中心点坐标灰度值的指针center
        const uchar* center = &image.at<uchar> (cvRound(pt.y), cvRound(pt.x));
    

    遍历中心线(-R到R),求m10m01,要乘加权center表示该点灰度值

    不需要求m01,因为当前遍历的是u轴,v坐标为0

    step 是一行的字节总数,后面遍历的时候增量乘step表示像素增量

       // Treat the center line differently, v=0
        //这条v=0中心线的计算需要特殊对待
        //由于是中心行+若干行对,所以PATCH_SIZE应该是个奇数
        for (int u = -HALF_PATCH_SIZE; u <= HALF_PATCH_SIZE; ++u)
            //注意这里的center下标u可以是负的!中心水平线上的像素按x坐标(也就是u坐标)加权
            m_10 += u * center[u];
    
        // Go line by line in the circular patch  
        //这里的step1表示这个图像一行包含的字节总数。参考[https://blog.csdn.net/qianqing13579/article/details/45318279]
        int step = (int)image.step1();
    

    遍历非中心线

    v从1开始,到半径的长度

        //注意这里是以v=0中心线为对称轴,然后对称地每成对的两行之间进行遍历,这样处理加快了计算速度
        for (int v = 1; v <= HALF_PATCH_SIZE; ++v)
        {
            // Proceed over the two lines
            //本来m_01应该是一列一列地计算的,但是由于对称以及坐标x,y正负的原因,可以一次计算两行
            int v_sum = 0;
            // 获取某行像素横坐标的最大范围,注意这里的图像块是圆形的!
            int d = u_max[v];
    

    给定一个v坐标,求出最大u坐标

    在每个v下,遍历u,前面定义过u_max[v],表示给定一个v坐标,求出最大u坐标,这里赋值给了d

    遍历d相当于遍历了给定v之后的当前行

    由两个公式m_10 m_01 需要当前u或v值乘以当前像素灰度值

    val_plus相当于I(x,y),val_minus相当于I(x,-y)

    有了这两个变量,下面的程序就很好懂了

    fastAtan2为计算特征点方向的函数

            //在坐标范围内挨个像素遍历,实际是一次遍历2个
            // 假设每次处理的两个点坐标,中心线下方为(x,y),中心线上方为(x,-y) 
            // 对于某次待处理的两个点:m_10 = Σ x*I(x,y) =  x*I(x,y) + x*I(x,-y) = x*(I(x,y) + I(x,-y))
            // 对于某次待处理的两个点:m_01 = Σ y*I(x,y) =  y*I(x,y) - y*I(x,-y) = y*(I(x,y) - I(x,-y))
            for (int u = -d; u <= d; ++u)
            {
                //得到需要进行加运算和减运算的像素灰度值
                //val_plus:在中心线下方x=u时的的像素灰度值
                //val_minus:在中心线上方x=u时的像素灰度值
                int val_plus = center[u + v*step], val_minus = center[u - v*step];
                //在v(y轴)上,2行所有像素灰度值之差
                v_sum += (val_plus - val_minus);
                //u轴(也就是x轴)方向上用u坐标加权和(u坐标也有正负符号),相当于同时计算两行
                m_10 += u * (val_plus + val_minus);
            }
            //将这一行上的和按照y坐标加权
            m_01 += v * v_sum;
        }
    
        //为了加快速度还使用了fastAtan2()函数,输出为[0,360)角度,精度为0.3°
        return fastAtan2((float)m_01, (float)m_10);
    }
    

    IC_Angle 结束 返回 computeOrientation

    computeOrientation 结束 返回ComputeKeyPointOctTree

    ComputeKeyPointOctTree 结束 返回operator()

    展开全文
  • 如前所说,单目运算符是只需一个变量进行运算的符号,包括1/x、±和√。先说一下各按钮的功能:  1/x:对一个数取倒数。  ±:对一个数进行取反,即将正数变成绝对值相同的负数,反之亦然。如果是0则不变。  √:...

           接下来,就轮到单目运算符了。如前所说,单目运算符是只需一个变量进行运算的符号,包括1/x、±和√。先说一下各按钮的功能:

          1/x:对一个数取倒数。

          ±:对一个数进行取反,即将正数变成绝对值相同的负数,反之亦然。如果是0则不变。

          √:对一个数进行平方根运算。

          这些运算在Math类当中均有现成函数,因此实现起来非常简单。但需要记得做围栅栏的措施:1/x运算x不能为0,而平方根运算不能对负数开方。新建一个Operation类,代码如下:

             /**

              * 单目运算符的处理

              *

              *@param text

              *            输入文本

              *@param index

              *            序列号码

              *@return 是简单符号则处理并返回结果,否则返回空字符串

              */

             public static StringunaryOperationAction(String text, int index) {

                 double digit;

                 switch (index) {

                 case Button.NEG_SIGN:

                    isResult = true;

                    if ("0".equals(text)) {

                        return "0";

                    } else if(text.startsWith("-")) {

                        return text.substring(1,text.length());

                    } else {

                        return "-" + text;

                    }

                 case Button.SQRT:

                    isResult = true;

                    digit = Double.parseDouble(text);

                    if (digit < 0) {

                        return "开方数不能为负数";

                    }

                    return resultFormat(Math.sqrt(digit));

                 case Button.RECIPROCAL:

                    isResult = true;

                    digit = Double.parseDouble(text);

                    if (digit == 0) {

                        return "除数不能为0";

                    }

                    return resultFormat(1 / digit);

                 case Button.CE:

                    empty();

                    return "0";

                 default:

                    return "";

                 }

             }

          ±和开方与前面说的一样,得出来的是结果,当再次点击数字键时会将显示区的内容清除,重新输入数字,除了CE及C以外的按键全部失效。为了完成这个效果,我在Operation类中添加了isResult字段,以记录是否为结果,Num_Index数组记录的则是数字按钮的序号,点击的如果不是数字键、C或CE,则按钮会失效。下面的refresh()则实现了判断是否为结果的功能,并返回相应结果:

             /**

              * 结果出来后输入数字会把结果清掉

              *

              *@return 重新输入的数字

              */

             public static String refresh(String text, intindex) {

                 for (int i = 0; i <Number.NUM_INDEX.length; i++) {

                    if (index == Number.NUM_INDEX[i]) {

                        isResult = false;

                        return Button.num[index];

                    }

                    if (index == Button.C || index ==Button.CE) {

                        return "0";

                    }

                 }

                 return text;

             }

     

          最后要讲一讲输出结果的格式问题。仔细注意一下,计算器输出的结果并不是直接将计算出来的结果输出的,而是进行了一定程度的处理。我对输出的结果进行了以下处理:

          1. 输出结果和输入数字的长度不得超过15位(这是为了使显示区的内容不会挡住存储运算的M符号)。

          2. 输出的结果保留15位小数,多的进行四舍五入;如果结果满足在0<|x|<0.001或|x|>1000000000时,结果将会以科学计数法显示。

          第二条处理需要用到类DecimalFormat,规定好结果的格式后,使用format()方法即可获得所需结果的格式。主要代码如下:

          /**

              * 结果格式化,如果绝对值在0.001到1000000000之间且不等于0,保留15位小数,去掉后面多余的0,否则使用科学计数法表示

              *

              *@param res

              *            计算结果

              *@return 格式化后的结果

              */

             public static String resultFormat(double res){

                 if ((Math.abs(res) < 0.001 ||Math.abs(res) > 1000000000) && res != 0) {

                    DecimalFormat sn = newDecimalFormat("0.############E0");

                    String format = sn.format(res);

                    // 保证结果长度最多15位

                    return format.length() > 15 ?format.substring(0, format

                           .indexOf("E")

                           -format.substring(format.indexOf("E"), format.length())

                                  .length())

                           +format.substring(format.indexOf("E"), format.length())

                           : format;

                 } else {

                    DecimalFormat dec = newDecimalFormat("0.#############");

                     returndec.format(res);

                 }

             }

          单目运算符的处理也到此完成。

    展开全文
  • 基于单目摄像头的物体检测

    千次阅读 2019-11-05 20:43:30
    , 我们简称它 Multi task YOLO-3D, 因为它最终输出单目摄像头3D障碍物检测和2D图像分割所需的全部信息。   它和原始的YOLO V2有以下几种不同: 1. 实现多任务输出: (1)  物体检测 ,包括2D框(以像素...
  • 第2章 运算符与表达式[考点一] C运算符简介[考点二] 运算符的结合性和优先级(1) 在C语言的运算符中,所有的单目运算符、条件运算符、赋值运算符及其扩展运算符结合方向都是从右向左,其余运算符的结合方向是从左向右...
  • 基于单目摄像头的物体检测 - Baidu Apollo 陈光 摄像机是无人车系统中最重要的传感器之一,其廉价、帧频高、信息丰富、观测距离远,但易受环境影响、缺乏深度信息。 Apollo 2.5 和 3.0 中广泛使用的单目摄像头物体...
  • 运算

    2017-08-16 16:53:30
    1、概述 位运算概念:用于对整数类型(int,char, long 等)变量中的某一位(bit),或者若干位进行操作。 比如: 1) 判断某一位是否为1 2) 只改变其中某一位,而保持其他位...~ 按位非(取反)(单目) 左移(双目) >>
  • 逻辑运算

    2015-03-13 22:58:27
    逻辑运算运算  位运算运算分量只能是整型或字符型数据,位运算运算对象看作是由二... 其中,按位取反运算符是单目运算符,其余均为双目运算符。  位运算符的优先级从高到低,依次为~、&、^、|,
  • 单目图像深度估计 - 5. 深度篇:David Eigen的两篇研究 终于写到了目前比较主流的深度学习方法。随着大规模的数据集的出现以及硬件运算能力的提高,数据驱动的方法开始在计算机视觉、自然语言理解等领域发光发热。...
  • 相机姿态估计(二)--单目POSIT算法

    万次阅读 2016-07-26 21:53:33
    要知道,这里只是利用线性关系消去了w,但保留了原来第三行中的未知量,因此未知量的数量保持12不变;而POSIT方法中,直接为w选取了一个估计值,并删去了“---原始方程--”的第3行,这样方程中才少了4个未知量只剩下...
  • ORB-SLAM:精确多功能单目SLAM系统

    万次阅读 2017-04-21 16:58:31
    ORB-SLAM: a Versatile and Accurate Monocular SLAM System Taylor Guo, 2016年3月18日-9:00 原文发表于:IEEE Transactions on Robotics ...本文主要讲了ORB-SLAM,一个基于特征识别的单目slam系统,可以实时运行,
  • Vins-mono是香港科技大学开源的一个VIO算法,用紧耦合的方法,通过单目+IMU恢复出尺度,效果非常棒。 VINS的功能模块可包括五个部分:数据预处理、初始化、后端非线性优化、闭环检测及闭环优化。代码中主要开启了四...
  • 单目slam LoopClosing之Sim3优化

    千次阅读 2017-03-15 12:48:33
    sim3群运算S=(sR01×3t1) S=\left(\begin{array}{ccc}&sR &t\\ &0_{1×3} &1 \end{array}\right) 最小表示:[ω,ν,σ][\omega,\nu,\sigma], 其中ω∈R3,ν∈R3,σ∈R\omega\in R^3, \nu\in R^3, \sigma\in R。逆...
  • 1. 算术运算: 双目运算:(参与运算的有两个)加减乘除取余,除法... 单目运算:(参与运算的只有一个)自增自减取负,a++或++a等效于a=a+1;a--或—a等效于a=a-1,前置(先操作在取变量值) ++在前 和后置(先取...
  • 这篇文章将介绍运算,包括算术运算、逻辑运算、赋值运算、位运算及编程练习。 这系列文章入门部分将参考“尚硅谷”韩顺平老师的视频和书籍《GO高级编程》,详见参考文献,并结合作者多年的编程经验进行学习和丰富,...
  • C++之单目运算符重载

    千次阅读 2016-06-04 11:16:14
    这么一个普通变量,系统是不允许这么操作的,左值不允许是运算,但 (-c) = t; 缺编译通过了,现在这是不可以的,那么就会说将运算符重载的函数返回值类型改成const就可以了,下面就改一下: class ...
  • C++位运算

    2017-05-12 15:59:17
    运算  位运算运算分量只能是整型或字符型数据,位运算运算对象看作是由二进位组成的位... 其中,按位取反运算符是单目运算符,其余均为双目运算符。  位运算符的优先级从高到低,依次为~、&、^、|,  其中
  • c语言的位运算

    2018-10-14 16:44:25
    除了~为单目运算,其余都是双目运算。 (1)&amp; 按位与 比如二进制数1001和0110进行与操作,结果则为0000,即1&amp;1为1。1&amp;0、0&amp;1、0&amp;0都为0。 与操作通常用来讲某变量中的一些...
  • 使用位运算加速乘除法运算

    千次阅读 2014-08-02 20:34:14
    运算  位运算运算分量只能是整型或字符型数据,位运算运算... 其中,按位取反运算符是单目运算符,其余均为双目运算符。  位运算符的优先级从高到低,依次为~、&、^、|,  其中~的结合方向自右至左,且
  • ORB-SLAM2代码详解06: 单目初始化器Initializer各成员变量/函数初始化函数`Initialize()`计算基础矩阵`F`和单应矩阵`H`RANSAC算法计算基础矩阵`F`: `FindFundamental()`八点法计算`F`矩阵: `ComputeF21()`计算单应...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,632
精华内容 2,652
关键字:

单目不变运算