2014年12月31日星期三

2014年小结

在2014年的最后一天分几个部分小结一下本年的情况.

a. 业余活动

刚刚看了阅读DNA对我在豆瓣上的记录统计:
我在2014年共读过58本书,五星好书11本,11月最勤快读了20本,平均:6.28天读一本书.
大概是这个数吧,有时候忘记统计了,有时候想起来的时候一个月把前几个月读过的书都在豆瓣上加上,其实11月没有读20本.平均:6.28天读一本书,大概一个星期读一本书,速度不快不慢.刚刚好,刚刚发现其实在2012年,我也是读了58本书.除了专业的书,2014年我个人比较推荐的五星好书为<房噬>和<费雪论创富>.看来如果即使今年工作很忙的阶段,每个星期读一本书还是可以保证的,把每周零散的看书的时间集成在一起大概有3个小时.

看了46部电影,其中五星电影4部,9月最消遣看了9部,平均:7.91天看一部电影.大部分在家看的,到电影院大概10几次吧,平均每个月一次.只有四部我评为5星<星际穿越><布达佩斯大饭店><纸牌屋 第二季>.加上没有记录的美剧,平均起来的时间,大概也就是每个星期看一部电影看一集美剧,大概每周不到3小时.

读书看片大概是我比较重要的业余消遣,读书其实很多时候读的还是工作上的专业书.大概每周花6个小时来读书看片.加上每周2个小时左右的运动.这个8个小时就是我平时最重要的业余消遣活动.

对了,2014年博客写的也不多,加上这篇才12篇,每月一篇,都是一些技术上的简单记录.希望2015年能有更多的时间来写博客.

b. 旅游

真正的旅游就是2014年春天到西班牙的Teneriffa呆了一个星期吧,满满的美好记忆.其他都是很多很多的德国境内的短途旅游,大多数都是去不同的城市工差办事.

c. 工作

简单提一下2014工作的情况吧:
一个已经做了3年的项目2014年有一个比较大的突破,终于做出了一个可以使用,用户满意的前端版本,从9月底开始了用户使用测试,进行的不断的迭代和纠错,现在用户有了一个相对不错的稳定的硬件平台和相对应的软件.后端程序还是有很多东西需要进一步开发,2014年开发后端程序的时候走了不少弯路,经历了许多方向性错误,经过不停的修正,经历了一个无比痛苦的过程,现在终于走上的正轨,希望在2015年初有一个稳定的后端版本可以推出.个人目标为2015年中可以彻底结束这个项目.

二月底成立了一家新公司.2014年7月艰难地开始一个筹划很久的项目,这个项目年底得到一个小的投资,正式开始.有可能2015年2月前可以得到一个比较大的投资.

2014年可以说是艰苦积累的一年,2015年项目上了轨道,应该会更忙,有可能会经常出差,希望一切顺利吧.

d. 生活

总体上都还行吧,老婆6月底毕业,年底请岳母来德国玩了3个月,生活中的一些新的计划也在有条不紊的进行.

2014年12月23日星期二

关于CLR的runtime的一个小记录

如果在.NET项目中使用Common Language Runtime Support (/clr)编译C++项目,如下图所示,如果使用VS2012会默认使用,.NET framework 4.5:



如果我们使用引用这个通过CLR编译的dll,查看它的属性,也会发现,如下图所示的,这个dll的Runtime Version是v4.0319。



如果我们的项目使用的不是.NET framework 4.5,使用上面所述的CLR编译的项目中的namespace就会出现下面的报错:
Error 492 The type or namespace name 'XXX' could not be found (are you missing a using directive or an assembly reference?)
最简单的解决的方法就是修改我们项目的Target Framework,将其改为4.5就可以了。

2014年9月11日星期四

使用QNetworkAccessManager下载文件的一个问题

今天发现一个问题,使用Qt的QNetworkAccessManager进行下载,将其放入一个QPushButton的clicked()的slots,但是无法正确执行下载文件,想了半天,还是没有搞明白,最后在stackoverflow在找到这个问题的解决方法,才明白,因为QNetworkAccessManager是非同步的,它需要一个event loop去开始下载,而我们执行clicked()这个slots,它会给一个control back给event loop,但是QNetworkAccessManager以及被销毁了,没有时间去做QNetworkAccessManager的下载文件。

解决方法:如果加入一个QMessageBox,这样就会启动另一个event loop在这个slot里面,这样QNetworkAccessManager就会有机会完成下载文件这个工作。

链接:
http://stackoverflow.com/questions/7870017/how-can-i-download-file-from-the-internet-in-qt

2014年9月8日星期一

OpenCV放大或者缩小图像的速度

使用OpenCV放大或者缩小图像,我们比较熟悉的是下面的function:
cv::resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR )¶
http://docs.opencv.org/modules/imgproc/doc/geometric_transformations.html
关于它的Interpolation method(插值方法),其中:

INTER_NEAREST 最近邻插值,是最快的method并且创建blocky images并选择1个pixel去替代几个pixels,这样做得到图像的结果效果比较差。
INTER_AREA 也是一个快速计算方法,它取几个pixels的平均值,所以它比较适合缩小图像,而不是放大图像。
INTER_LINEAR 使用双线性的插值去改变图像尺寸,组成几个pixels在一起(在很多情况下是比较好的选择,但是计算速度比较慢)。
INTER_CUBIC 使用的是双三次的插值,但是计算机量比较大,所以运行速度慢,而且有时候结果看起来比较好,有时候比较差。

非常简单地,不完全正确地说,在速度上:
INTER_NEAREST > INTER_AREA > INTER_LINEAR > INTER_CUBIC
但是放大或者缩小图像后的效果上一般而言INTER_LINEAR是相对最好的。

其实,也可以使用Opencv的cv::pyrUp(使用Gaussian 金字塔分解对输入图像向上采样)和cv::pyrDown(使用 Gaussian金字塔分解对输入图像向下采样),关于使用这两个function去放大或者缩小图像,具体信息可查阅下面链接:
http://docs.opencv.org/doc/tutorials/imgproc/pyramids/pyramids.html
但是cv::pyrUp和cv::pyrDown的运算速度其实也并不高。

2014年9月7日星期日

libVLC进行memory stream延迟问题

最近我使用libVLC进行在server端进行memory stream,出现了一个问题,client端得到的视频有7秒的延迟。类似以下帖子提到的问题:
http://stackoverflow.com/questions/19604815/main-input-error-and-delays-when-libvlc-stream-images-in-memory

为了找到错误我打开以下的参数:
"--verbose=2", // Be much more verbose then normal for debugging purpose
这样可以得到更多的debug信息。
我得到这样的信息:main warning: late buffer for mux input

经过查阅发现,正确的解决方法就是,在transcode里设置venc=x264{preset=ultrafast,tune=zerolatency}这样的参数:

sprintf(smem_options_transcode,"#transcode{venc=x264{preset=ultrafast,tune=zerolatency},acodec=none}:rtp{mux=ts,dst=127.0.0.1,port=5004}");

这样延迟可以控制在3秒以内,当然了,可以使用其他的方法进一步减少延迟,譬如在client端减少caching的数值等等。

解决方法参考:
https://forum.videolan.org/viewtopic.php?f=4&t=95364

2014年8月19日星期二

Qt Webkit 加入新的plugin路径

在Qt中使用QWebView播放flash文档(swf格式),需要加入NPSWF32.dll这个plugin,如果使用plugin要使用下面代码,去允许使用plugin:

QWebSettings *settings = QWebSettings::globalSettings();

settings->setAttribute (QWebSettings::PluginsEnabled, true);

但是如果还是无法显示flash文档,其实原因是Qt无法找到正确的plugin路径,需要使用类似以下代码,告诉Qt正确的含有NPSWF32.dll的plugin路径:

QString path  = QDir::currentPath() + "/webplugins";

qputenv("QTWEBKIT_PLUGIN_PATH", path.toLocal8Bit());

2014年8月12日星期二

设置GigEVision相机使用固定IP

如果使用Stemmer Imaging的CVB软件,可以在Camera的Properties里面设定:
在GigEVisionTransportLayer里面:
GevCurrentIPAddress            169.254.1.10
GevCurrentSubnetMask        255.255.0.0
GevPersistentDefaultGateway    0.0.0.0
GevIPConfiguration PersistenIP
在UserSets里面,将上面的设置储存,下次启动相机的时候上面的设置将会被使用:
User Set Default Selector    UserSet1
set User Save-->Execute
如果要加快计算机接上GigEVision相机后找到相机的速度
也可以将计算机的Lan Adapter设成固定的IP
譬如说:
IP address: 169.254.200.9
Subnetzmake: 255.255.0.0
Standardgateway: 放空


关于自动专用IP寻址的介绍:
我们上面使用的是Automatic Private IP Addressing (from 169.254.0.0 - 169.254.255.255) 它们的subnet mask value 是 255.255.0.0。其实是Windows 计算机自动专用IP寻址(APIPA)是DHCP故障转移机制。自动专用IP 寻址(APIPA) 协议,就是, 当无DHCP 服务器时,通过APIPA, DHCP 客户端可自动配置IP 地址和子网掩码。

The Internet Assigned Numbers Authority (IANA) has reserved 169.254.0.0 through169.254.255.255 for Automatic Private IP Addressing. As a result, Automatic Private IP Addressing provides an address that is guaranteed not to conflict with routable addresses.



关于使用私有IP的介绍:
http://zh.wikipedia.org/wiki/%E4%B8%93%E7%94%A8%E7%BD%91%E7%BB%9C
在互联网的地址架构中,专用网络是指遵守RFC 1918和RFC 4193规范,使用私有IP地址空间的网络。私有IP无法直接连接互联网,需要公网IP转发。与公网IP相比,私有IP是免费的,也节省了IP地址资源,适合在局域网使用。私有IP地址在internet中不会被分配。

private-IPv4-addr

2014年8月5日星期二

使用MP4Box对MP4视频文件加入Chapters


今天我尝试着使用FFmpeg对MP4视频文件加入Chapters(片段,段落,章节),这样可以在播放视频的时候直接跳到不同的片段,使用FFmpeg经过多次尝试均不成功,经过一番搜索,发现MP4Box这个免费工具,它可以非常轻松的完成我的需要。
先下载并安装MP4Box: http://www.videohelp.com/tools/mp4box ,我使用的是MP4BOX_GPAC.Framework.Setup-0.5.0这个版本。
然后写一个关于例如下面所示的的Chapter设置文档,保存成txt格式。
CHAPTER1=00:00:00.000
CHAPTER1NAME=Chapter 001
CHAPTER2=00:01:10.222
CHAPTER2NAME=Chapter 002
CHAPTER3=00:02:00.70
CHAPTER3NAME=Chapter 003
最后使用以下命令行,使用VLC打开生成的test.mp4文件,就可以发现文档中包含了3个片段。
MP4Box -add my_video.mp4 -chap chapters_file.txt test.mp4

2014年6月25日星期三

重新写一个精简的核心库

最近的带的项目陷入了软件开发的危机,原因是陷入自家写的库造成的泥沼越来越深。

最近几年带的大的软件项目都是使用自家写的库,工具库utils,开发库commDev,核心库core,api库,可视化库viz等等。当然了使用自家的库开发软件有时候非常有效率,但是自家开发库的升级以及维护绝对是一个大问题,维护超过5万行程序本身就是一个大问题,而且这几年来因为项目压力,常常直接将很多东西放入核心库core里,导致核心库臃肿不堪,而且关于库的使用的实例程序以及接口或者api更本做不到时常更新,有很多文档已经四五年了,更本无法使用,所以导致最最大的痛苦是教新人使用我们的库。更为恐怖的是核心库对其他外部库的依赖越来越多,从OpenCV,Boost到现在的至少10个以上的第三方库,但是核心库更本也没有根据外部库进行更新,至今核心库还在使用OpenCV2.0。更为痛苦的是自家写的库还是使用VS2008进行编译,因为实在太大,以至于没有人有勇气进行修整,并使用最新的编译器进行编译。


现在实在受不了了,我终于决定重写核心库,并且放弃工具库utils,开发库commDev,api库,可视化库viz。新的核心库只有两个依赖OpenCV和Qt这两个第三方库的巨无霸。放弃的工具库utils,开发库commDev,api库,可视化库viz,全部使用Qt代替。新的核心库就叫CoreLite,只依赖于最新的Qt5.3和OpenCV2.49,保持绝对的精简,而且可以根据Qt和OpenCV的升级进行编译,而且使用VS2012进行开发和编译,希望能做到根据OpenCV更新的频率进入版本更新。

  • 新的库CoreLite的第一个tag就是CoreLite290,使用和OpenCV一样的文档结构。
    \build\include
    \build\x86 (\build\x86\vc11\bin, \build\x86\vc11\lib)
    \sources\modules\
  • 新的库使用Qt的QThread。
  • 控制Class的总数,只包括Qt或OpenCV无法提供的一些特性,例如Producer-Comsumer-Data Sink结构。
  • 带几个实例。
  • 保证库的可读性,使用Qt的api的写作标准。
  • 最大程度保证库的可维护性,其实就是要保持精简。

目前想到的就是这些了,以后在重新的过程中,如果还有什么想法,我希望能写下来记录一下,期望可以用一个星期将新的核心库改写完成。

2014年6月14日星期六

VS 2008编译的程序部署的一个问题解决

最近遇到一个问题,在一台机器上使用VS 2008编译的程序无法在其他机器上运行,马上想到了以前提到过的关于Side-by-Side问题, 但是安装了Microsoft Visual C++ 2008 SP1 Redistributable Package (x86)后程序还是无法运行,而且没有什么错误信息。然后使用Windows里的Computer Management里的Event Viewer的Windows Logs发现这个程序无法运行的原因在于其调用的一个动态链接库DLL。然后我查看了一下这个DLL的Manifest,原来多了一个Microshoft.VC90.DebugCRT的依赖,如下图所示。如果我们在机器上没有安装VS 2008当然就会没有Microshoft.VC90.DebugCRT的依赖需要的msvcm90d.dll,msvcp90d.dll,msvcr90d.dll,所以程序就无法运行了。

manifest_vs2008_debug
解决的方法就是使用在release模式下编译,或者如下图所示,修改C++ Project的Property里的Linker-->Debugging选项页,将Generate Debug Info修改成No,将Debuggable Assembly改成No Debuggable attribute emitted,原来如下图a所示,修改后如下图b所示:

debuggable_assembly_debug_modedebuggable_assembly_release_mode

现在再编译一次,查看一下新生成的DLL的Manifest可以发现Microshoft.VC90.DebugCRT的依赖已经没有了,现在程序应该可以在其他机器上运行了。

manifest_vs2008_release

2014年1月27日星期一

Emgu CV使用1

最近开始使用Emgu CV,也就是在.NET可以使用的OpenCV,Emgu CV是一个.Net的wrapper。使用从C++转到C#中写OpenCV代码,开始时候还真的很不习惯,以下将简单整理一下最近的一些笔记。

如何将Grayimage转换到Matrix<float>,注意rows cols和height width的关系

Image<Gray, float> img = new Image<Gray, float>("c:\\test_image.jpg");
int rows = img.Height;
int cols = img.Width;
Matrix<float> tmp_matrix= new Matrix<float>(rows, cols);
CvInvoke.cvConvert(img, tmp_matrix);
       

如何显示图

//The name of the window
String win1 = "Test Window";
//Create the window using the specific name
CvInvoke.cvNamedWindow(win1);
Image<Bgr, Byte> img = new Image<Bgr, Byte>("c:\\test_image.jpg");
CvInvoke.cvShowImage(win1, img.Ptr);
//Wait for the key pressing event
CvInvoke.cvWaitKey(1);
//Destory the window
CvInvoke.cvDestroyWindow(win1);
           

如何画一个正方形在图上

Rectangle box = new Rectangle(121, 57, 75, 97);
Image<Bgr, Byte> img = new Image<Bgr, Byte>("c:\\test_image.jpg");
img.Draw(box, new Bgr(Color.DarkOrange), 2);

如何计算一个积分图integral image,在C++中我们可以使用integral(frame, imageIntegral, CV_32F),在C#中可以这样做:

Image<Gray, double> cvImageIntegral = null;
cvImageIntegral = frame.Integral();

如何计算标准差,标准差就是方差的算术平方根,反映组内个体间的离散程度,标准差与期望值之比为标准离差率。

Matrix<float> mat = ... // your input matrix
MCvScalar average = new MCvScalar();
MCvScalar std = new MCvSaclar();
CvInvoke.cvAvgSdv(mat, ref average, ref std, IntPtr.Zero);

2014年1月8日星期三

优化网卡用于machine vision

以下设定最好是使用Intel network chipset的网卡,并确保使用最新的驱动

我们要做的就是optimize bandwidth,improve efficiency

在Win7下选择Local Area Connection → 鼠标右键,点选Properties → 点击Configure → 选择Advanced Tab

1. set interrupt moderation rate to extreme

2. set maximize jumbo packets

3. maximize number of receive buffers

4. disable power saving on the network card