[Vim]用行号参与替换

一个小技巧。Vim有好处千种,”替换”只是其中一个。 除了强大的正则表达式,\=也是一个好用的工具。 比如要生成这么一个文件 This is number 1 This is number 2 This is number 3 This is number 4 This is number 5 This is number 6 This is number 7 This is number 8 This is number 9 This is number 10 方法当然有很多。用\=可以这么做: 先输入一行 This is number X 复制出另外9行 yy9p 得到 This is number […]

[OpenCV] detectMultiScale: output detection score

OpenCV provides quite decent implementation of the Viola-Jones Face detector. A quick example looks like this (OpenCV 2.4.5 tested): // File: main.cc #include using namespace cv; int main(int argc, char **argv) { CascadeClassifier cascade; const float scale_factor(1.2f); const int min_neighbors(3); if (cascade.load(“./lbpcascade_frontalface.xml”)) { for (int i = 1; i < argc; i++) { Mat img […]

Nested Array in Bash

用了Bash这么久,才知道Bash支持Array。但是却缺乏对嵌套数组,或者是多维数组的支持。自己的实验里面需要用到结构性的数据,这样看起来或者改起来会比较方便,而且因为这部分是用来处理实验结果,需要经常修改,所以不适合放到C++里面去写。 因此就有了需要Bash支持嵌套数组的需求。 最终的解决方法不是很漂亮,但是也足够我自己用了。这个想法的出发点是这样的: Bash在处理数组的时候会用到IFS这个环境变量。比如这样一段字符 Li,Age*1;Weight*2;Height*3;Friends*Sun^Wang Wang,Age*11;Weight*12;Height*13;Friends*Li^Sun 如果IFS是空格,我们就可以得到两个元素 Li,Age*1;Weight*2;Height*3;Friends*Sun^Wang Wang,Age*11;Weight*12;Height*13;Friends*Li^Sun 如果IFS是分号(;),我们可以得到另一个数组 Li,Age*1 Weight*2 Height*3 Friends*Sun^Wang Wang,Age*11 Weight*12 Height*13 Friends*Li^Sun 也就是说我们可以通过指定不同的IFS让一段字符成为不同的数组。 所以,我们可以通过对每一层使用不同的IFS来表达一个嵌套数组。比如上面那段字符,我们用不同的IFS字符,先用空格( ),再用逗号(,),之后用分号(;)…… 如此做下去就可以达到层层盘剥的效果(-_-!) 在实际使用中,我们只要保证每一层用到的IFS不会在数组内容中出现就行了。 为了能够生成那样一段字符,我们自然需要一些函数做辅助。 具体的代码放到Github上了。目前这个方法虽然有效,但是使用起来仍然不够简洁,看起来如果找不到更好的Bash下的解决方法,就得考虑换用一种20世纪的脚本语言了… Github: Nested-Array-Bash

rand函数不可重入

写C代码的时候,srand(int seed) 和 rand() 是常用的伪随机数生成函数。 这两个函数的使用方法很简单,但是一个可能被忽略的细节是,rand() 依赖一个内部的、全局的状态变量。所以 rand() 是不可重入,也是不是线程安全的 (thread-safe) 。 如果多个线程同时调用 rand() 函数,那么无论你如何使用 srand(int seed) 都无法保证结果是可以重现的。每次运行程序,各个线程中 rand() 函数生成的伪随机数序列都和上次不同。 在调试的时候,不能重现的结果会是比较棘手的障碍。 幸好,我们可以用C++11 提供的伪随机数生成器 Pseudo-random number generation (这么翻译好机械-_-!)用法很容易在网络上找到,这里有一个最简单的例子。 #include //….. { std::default_random_engine gen(0); int a_random_number = gen(); } default_random_engine维护自己的内部状态,各个线程都用同样的参数初始化default_random_engine,就可以得到一致的伪随机数序列了。

Tips 2013-02-17

如果有需要把工程从Linux下面移植一份到Windows下,却又不熟悉Visual Studio的各种配置,那么用CMake来管理工程是一个不错的选择。从Makefile改写CMakeLists.txt并不麻烦,而且CMake可以自动生成VS的工程文件,很好用。 用 floor 和 ceil 这类函数最好先对参数做显示的类型转换,否则VS会报错。 isinf 和 isnan 能不能则不用,VS没有现成好用的对应版本。 关于把一份Git工程同步到SVN的版本库里去的方法,网上讨论的很多,比如这个: http://stackoverflow.com/questions/661018/pushing-an-existing-git-repository-to-svn 但是如果你的Git的工程已经有了悠久历史,那么在rebase那一步你可能会有非常多的conflicts要处理。一个小办法是每次出现了冲突都用这一行代码: $git checkout . –theirs && git add . && git rebase –continue 当然前提是当前目录下面没有不在git管理下的其他文件。这个虽然不解决根本问题,但是会方便很多。 总是有想要重构自己实验工程的想法,看起来工程的框架还是不太好。我总觉得好的框架应该是很容易修改的,现在每次想要往工程里新加一组实验就觉得有些代码碍手碍脚。如果不想有重复代码函数粒度就太小,而且接口复杂不可读,时间一长就看不出它们都是干什么的了。否则就有大段的重复代码,十分难看。如果把实验操作部分放到Bash脚本里面,移植又是一个问题。很少看到讲这种不大的工程怎么去搭框架的问题,苦于自己技术水平不够,想想真是头疼…

比较变量地址并不可靠

最近云风大牛又在黑我C++,可是在我学会之前,我还是要坚定不移地待在这贼船上。 嘿嘿 :] “用比较地址的方法来判断两个变量(的引用)是不是同一个变量是不可靠的”,这个问题很简单,却也容易忽视。 现实的情况是这样的。在写Computer Vision实验的时候,因为程序要面临的计算量往往很大,对程序的性能的优化是十分重要的。 所以我就写出了这样的代码: void foo_func(Foo& foo) { //< 如果foo和上次传入的是同一个,就省掉一部分重复计算 static Foo *p_foo = NULL; if (p_foo != &foo) { p_foo = &foo; //< 大量计算 } //< 后续计算 } 在实验里,Foo这个类本身往往比较复杂,不可能做内容的逐一比较,同时这个类的实例在初始化之后内容就保持不变。写这个函数的时候没有觉得有什么问题,结果也是正确的。 但是,这么做显然是不可靠的。 这段代码就说明问题了: #include int main(int argc, char **argv) { using namespace std; for (int i = 0; i < 100; i++) { […]