天天看点

LINUX C++语法疑问记录

What does OpenCV’s cvWaitKey( ) function do? - Stack Overflow

Plain simply, cvWaitKey() sleeps for X miliseconds, waiting for any key to be pressed.

int cvWaitKey(int X);

If a key is pressed, this function returns the ASCII code of key. Or returns -1 if no keys were pressed during that time.

VideoCapture()

cv::VideoCapture::VideoCapture	(	const String & 	filename,
int 	apiPreference = CAP_ANY 
)		
explicit
Python:
<VideoCapture object>	=	cv.VideoCapture(		)
<VideoCapture object>	=	cv.VideoCapture(	filename[, apiPreference]	)
<VideoCapture object>	=	cv.VideoCapture(	index[, apiPreference]	)
Opens a video file or a capturing device or an IP video stream for video capturing with API Preference.

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Parameters
filename	it can be:
name of video file (eg. video.avi)
or image sequence (eg. img_%02d.jpg, which will read samples like img_00.jpg, img_01.jpg, img_02.jpg, ...)
or URL of video stream (eg. protocol://host:port/script_name?script_params|auth)
or GStreamer pipeline string in gst-launch tool format in case if GStreamer is used as backend Note that each video stream or IP camera feed has its own URL scheme. Please refer to the documentation of source stream to know the right URL.
           
cv::VideoCapture::VideoCapture	(	int 	index,
int 	apiPreference = CAP_ANY 
)		
explicit
Python:
<VideoCapture object>	=	cv.VideoCapture(		)
<VideoCapture object>	=	cv.VideoCapture(	filename[, apiPreference]	)
<VideoCapture object>	=	cv.VideoCapture(	index[, apiPreference]	)
Opens a camera for video capturing.

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Parameters
index	id of the video capturing device to open. To open default camera using default backend just pass 0. (to backward compatibility usage of camera_id + domain_offset (CAP_*) is valid when apiPreference is CAP_ANY)
apiPreference	preferred Capture API backends to use. Can be used to enforce a specific reader implementation if multiple are available: e.g. cv::CAP_DSHOW or cv::CAP_MSMF or cv::CAP_V4L.
           

opencv octave

KeyPoint::angle
In OpenCV docs was mentioned that angle is computed orientation of the keypoint (-1 if not applicable). I can not imagine that what it is about. So Can anyone say me what it means or bring a small example.

KeyPoint::octave
In OpenCV docs was mentioned that octave is octave (pyramid layer) from which the keypoint has been extracted. I can not imagine that what it is about. So Can anyone say me what it means or bring a small example.
           

CMake 关闭警告的方法

在CMakeLists.txt中添加add_definitions(-w)

在绘制直线时,特别是一系列连续的点时,要特别注意 绘线方式GL_LINES 和GL_LINE_STRIP

1、GL_LINES :每一对顶点被解释为一条直线

  2、GL_LINE_STRIP: 一系列的连续直线
           

在glBegin()和glEnd()之间可调用的函数

函数 函数意义

glVertex*() 设置顶点坐标

glColor*() 设置当前颜色

glIndex*() 设置当前颜色表

glNormal*() 设置法向坐标

glCoord*() 产生坐标

glCallList(),glCallLists() 执行显示列表

glTexCoord*() 设置纹理坐标

glEdgeFlag*() 控制边界绘制

glMaterial*() 设置材质

类型 说明

GL_POINTS 单个顶点集

GL_LINES 多组双顶点线段

GL_POLYGON 单个简单填充凸多边形

GL_TRAINGLES 多组独立填充三角形

GL_QUADS 多组独立填充四边形

GL_LINE_STRIP 不闭合折线

GL_LINE_LOOP 闭合折线

GL_TRAINGLE_STRIP 线型连续填充三角形串

GL_TRAINGLE_FAN 扇形连续填充三角形串

GL_QUAD_STRIP 连续填充四边形串

线程的同步(unique_lock的使用)

unique_lock中的unique表示独占所有权。

unique_lock独占的是mutex对象,就是对mutex锁的独占。

用法:

(1)新建一个unique_lock 对象

(2)给对象传入一个std::mutex 对象作为参数;

std::mutex mymutex;

unique_lock lock(mymutex);

因此加锁时新建一个对象lock

unique_lock lock(mymutex);

而这个对象生命周期结束后自动解锁。

C++ Vector转Set与Set转Vector

#include<set>
#include<vector>
#include<iostream>
using namespace std;


int main()
{
    vector<int> vec;
    vec = { 1, 2, 3, 4, 8, 9, 3, 2, 1, 0, 4, 8 };
    set<int> st(vec.begin(), vec.end());
    vec.assign(st.begin(), st.end());

    vector<int>::iterator it;
    for (it = vec.begin(); it != vec.end(); it++)
        cout << *it<<endl;
    
    return 0;
}
           

这个例子是将vector里面的重复元素去掉并排序,先将vector转成set 然后set转成vector

运行结果

0 1 2 3 4 8 9

ORB_SLAM2 一直初始化无法建图

使用orb_slam2跑自己数据时,一直初始化无法建图。需要改两个bug

第一个bug
将src文件夹下的Initializer.cc 892行

if(cosParallax<0.99998){
	vbGood[vMatches12[i].first]=true;
}
改为
if(cosParallax<0.99998){
	vbGood[vMatches12[i].first]=true;
	nGood++;
}


第二个bug
ORBmatcher.cc文件第478行
int bin = round(rot*factor);
改为
int bin = round(rot/(360.0f*factor));

           

(1)size_t, ssize_t和int

size_t是一些C/C++标准在stddef.h中定义的。这个类型足以用来表示对象的大小。size_t的真实类型与操作系统有关。

在32位架构中被普遍定义为:

typedef unsigned int size_t;

而在64位架构中被定义为:

typedef unsigned long size_t;

size_t在32位架构上是4字节,在64位架构上是8字节,在不同架构上进行编译时需要注意这个问题。而int在不同架构下都是4字节,与size_t不同;且int为带符号数,size_t为无符号数。

(2)ssize_t

ssize_t是有符号整型,在32位机器上等同与int,在64位机器上等同与long int.

(3)size_t和ssize_t作用

size_t一般用来表示一种计数,比如有多少东西被拷贝等。例如:sizeof操作符的结果类型是size_t,该类型保证能容纳实现所建立的最大对象的字节大小。 它的意义大致是“适于计量内存中可容纳的数据项目个数的无符号整数类型”。所以,它在数组下标和内存管理函数之类的地方广泛使用。

而ssize_t这个数据类型用来表示可以被执行读写操作的数据块的大小.它和size_t类似,但必需是signed.意即:它表示的是signed size_t类型的。

在ORB_SLAM2中使用自己的视频

%YAML:1.0
 
#--------------------------------------------------------------------------------------------
# Camera Parameters. Adjust them!
#--------------------------------------------------------------------------------------------
 
# Camera calibration and distortion parameters (OpenCV) 
Camera.fx: 500.0
Camera.fy: 500.0
Camera.cx: 320.0
Camera.cy: 240.0
 
Camera.k1: 0
Camera.k2: 0
Camera.p1: 0
Camera.p2: 0
Camera.k3: 0
 
# Camera frames per second 
Camera.fps: 30.0
 
# Color order of the images (0: BGR, 1: RGB. It is ignored if images are grayscale)
Camera.RGB: 0
 
#--------------------------------------------------------------------------------------------
# ORB Parameters
#--------------------------------------------------------------------------------------------
 
# ORB Extractor: Number of features per image
ORBextractor.nFeatures: 1000
 
# ORB Extractor: Scale factor between levels in the scale pyramid     
ORBextractor.scaleFactor: 1.2
 
# ORB Extractor: Number of levels in the scale pyramid    
ORBextractor.nLevels: 8
 
# ORB Extractor: Fast threshold
# Image is divided in a grid. At each cell FAST are extracted imposing a minimum response.
# Firstly we impose iniThFAST. If no corners are detected we impose a lower value minThFAST
# You can lower these values if your images have low contrast            
ORBextractor.iniThFAST: 10
ORBextractor.minThFAST: 5
 
#--------------------------------------------------------------------------------------------
# Viewer Parameters
#--------------------------------------------------------------------------------------------
Viewer.KeyFrameSize: 0.05
Viewer.KeyFrameLineWidth: 1
Viewer.GraphLineWidth: 0.9
Viewer.PointSize: 2
Viewer.CameraSize: 0.08
Viewer.CameraLineWidth: 3
Viewer.ViewpointX: 0
Viewer.ViewpointY: -0.7
Viewer.ViewpointZ: -1.8
Viewer.ViewpointF: 500

           
#include <opencv2/opencv.hpp>
#include "System.h"
#include <string>
#include <chrono>   // for time stamp
#include <iostream>
using namespace std;
// 参数文件与字典文件
// 如果你系统上的路径不同,请修改它
string parameterFile = "./myvideo.yaml";
string vocFile = "./Vocabulary/ORBvoc.txt";
// 视频文件
string videoFile = "./myvideo.mp4";
int main(int argc, char **argv) {
 // 声明 ORB-SLAM2 系统
    ORB_SLAM2::System SLAM(vocFile, parameterFile, ORB_SLAM2::System::MONOCULAR, true);
 // 获取视频图像
  cv::VideoCapture cap(videoFile);    // change to 0 if you want to use USB camera.
  // 记录系统时间
  auto start = chrono::system_clock::now();

while (1) {
        cv::Mat frame;
        cap >> frame;   // 读取相机数据

        if ( frame.data == nullptr )
            continue;
        // rescale because image is too large
        cv::Mat frame_resized;
        cv::resize(frame, frame_resized, cv::Size(640,360));
        auto now = chrono::system_clock::now();
        auto timestamp = chrono::duration_cast<chrono::milliseconds>(now - start);
        SLAM.TrackMonocular(frame_resized, double(timestamp.count())/1000.0);
        cv::waitKey(30);
    }
    return 0;

}

           
#生成调用myvideo.mp4 可执行文件
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR})
add_executable(myvideo myvideo.cpp)
target_link_libraries(myvideo ${PROJECT_NAME})

           

CLion使用技巧

Ctrl + 向左箭头 回退
Ctrl + 向右箭头 前进
ALT + 1 显隐工程栏
Ctrl + / 添加或删除注释
Ctrl + Alt + L 格式化代码
Alt + F7 Find Usages
Ctrl + R 替换
Ctrl + B 在定义和申明之间跳转
Ctrl + Shift + Backspace 回到最后编辑的地方

Ctrl + N 查找类
Ctrl + O 选取需要重写的方法
Ctrl + F12 快速查看类成员
Ctrl + Q 快速查看文档
Ctrl + P 提示参数信息
Ctrl + H 查看继承树
Ctrl + E 查看最近浏览的文件
Ctrl + Alt + B 查看接口、抽象类的实现类

Ctrl + F 搜索当前文件 注:按Esc,搜索框就会消失
Ctrl + Shift + F 搜索整个工程或指定目录 注:连续按两次Esc,搜索框就会消失
Ctrl + Shift + N 找文件
Ctrl + F7 找到某个类、变量、函数等在文中被使用到的的地方
Shift + Shift 全局搜索
Ctrl + Alt + 7 查看类、对象、变量使用的地方

Ctrl + Alt + -/+ 展开折叠当前函数、类
Ctrl + Shift + -/+ 展开折叠所有函数、类

Shift + F6 重新命名变量
Alt + insert 添加自动代码生成信息(插入set*()/get*()/构造器、equals、hashcode等)
Ctrl + Shift + 空格 提示信息(new后直接键入构造器、构造器内提供构造信息)

           

emplace_back() 和 push_back 的区别

vector中push_back对象时,会调用对象的拷贝构造函数。
而且在vector空间不足时,继续push_back,vector会将之前的所有对象都拷贝构造到一块更大的空间里。
也就是说对象如果较大,那么最好用vector保存指针以减少调用拷贝构造 造成的消耗,
如果vector存指针,那么也就拷贝指针而已,消耗非常小。


c++开发中我们会经常用到插入操作对stl的各种容器进行操作,比如vector,map,set等。
在引入右值引用,转移构造函数,转移复制运算符之前,通常使用push_back()向容器中加入一个右值元素(临时对象)时,
首先会调用构造函数构造这个临时对象,然后需要调用拷贝构造函数将这个临时对象放入容器中。
原来的临时变量释放。这样造成的问题就是临时变量申请资源的浪费。 
引入了右值引用,转移构造函数后,push_back()右值时就会调用构造函数和转移构造函数,
如果可以在插入的时候直接构造,就只需要构造一次即可。这就是c++11 新加的emplace_back。
emplace_back函数原型:
template <class... Args>
  void emplace_back (Args&&... args);
在容器尾部添加一个元素,这个元素原地构造,不需要触发拷贝构造和转移构造。
而且调用形式更加简洁,直接根据参数初始化临时对象的成员。
           

Counting bits set, in parallel

unsigned int v; // count bits set in this (32-bit value)
unsigned int c; // store the total here
static const int S[] = {1, 2, 4, 8, 16}; // Magic Binary Numbers
static const int B[] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF};

c = v - ((v >> 1) & B[0]);
c = ((c >> S[1]) & B[1]) + (c & B[1]);
c = ((c >> S[2]) + c) & B[2];
c = ((c >> S[3]) + c) & B[3];
c = ((c >> S[4]) + c) & B[4];
The B array, expressed as binary, is:
B[0] = 0x55555555 = 01010101 01010101 01010101 01010101
B[1] = 0x33333333 = 00110011 00110011 00110011 00110011
B[2] = 0x0F0F0F0F = 00001111 00001111 00001111 00001111
B[3] = 0x00FF00FF = 00000000 11111111 00000000 11111111
B[4] = 0x0000FFFF = 00000000 00000000 11111111 11111111
We can adjust the method for larger integer sizes by continuing with the patterns for the Binary Magic Numbers, B and S. If there are k bits, then we need the arrays S and B to be ceil(lg(k)) elements long, and we must compute the same number of expressions for c as S or B are long. For a 32-bit v, 16 operations are used.
The best method for counting bits in a 32-bit integer v is the following:

v = v - ((v >> 1) & 0x55555555);                    // reuse input as temporary
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);     // temp
c = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count
The best bit counting method takes only 12 operations, which is the same as the lookup-table method, but avoids the memory and potential cache misses of a table. It is a hybrid between the purely parallel method above and the earlier methods using multiplies (in the section on counting bits with 64-bit instructions), though it doesn't use 64-bit instructions. The counts of bits set in the bytes is done in parallel, and the sum total of the bits set in the bytes is computed by multiplying by 0x1010101 and shifting right 24 bits.

A generalization of the best bit counting method to integers of bit-widths upto 128 (parameterized by type T) is this:

v = v - ((v >> 1) & (T)~(T)0/3);                           // temp
v = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3);      // temp
v = (v + (v >> 4)) & (T)~(T)0/255*15;                      // temp
c = (T)(v * ((T)~(T)0/255)) >> (sizeof(T) - 1) * CHAR_BIT; // count
See Ian Ashdown's nice newsgroup post for more information on counting the number of bits set (also known as sideways addition). The best bit counting method was brought to my attention on October 5, 2005 by Andrew Shapira; he found it in pages 187-188 of Software Optimization Guide for AMD Athlon™ 64 and Opteron™ Processors. Charlie Gordon suggested a way to shave off one operation from the purely parallel version on December 14, 2005, and Don Clugston trimmed three more from it on December 30, 2005. I made a typo with Don's suggestion that Eric Cole spotted on January 8, 2006. Eric later suggested the arbitrary bit-width generalization to the best method on November 17, 2006. On April 5, 2007, Al Williams observed that I had a line of dead code at the top of the first method.
           

why homography matrix svd smallest eigenvalue

LINUX C++语法疑问记录

why Decompose the fundamental matrix twice

第一次得到一个初步基础矩阵,但是不能保证他的最小奇异值为0,所以第二次分解是将最小奇异值设置为0,相乘后重新获得一个好的基础矩阵。