2009年3月21日星期六

第一份工作一定要选一家好公司

同很多年轻朋友交流时,我都以自己的亲身经历劝告他们:

  第一份工作不是选一份好职业,不是选一份好薪水,而一定要选一家好公司。

  为什么?因为一家好的公司可以在各方面奠定你的职业基础。回头来看,我能有今天这样的发展空间,职业初期在微软打下的基础实在起着举足轻重的作用。

   我加入微软后,有一个亲戚对我说:如果这家公司让你去做前台,你都应该去。对于他的话,我深以为然。因为即使是做前台,只要你有心,一样可以了解到这个 公司的结构体系和管理规范。我的朋友,也是我在微软时曾经的同事吴士宏,最初进IBM时就只是一个前台人员,后来却做到微软中国区总经理,成为中国女性职 业经理人的代表之一。

  只要你有能力,不在乎工作的性质,不在乎薪水的高低,你完全可以从很低的位置开始证明自己。而去管理不规范的小公司,哪怕一开始就做副总裁,对你未来的发展也没有太大的帮助。因此,不要眼高手低,选中一家好公司,先入门再说,跨进去后未来就是你的了。

  以应聘者身份踏进微软总部的那天,我以为从此可以天天近距离接触心目中的偶像、世界首富比尔·盖茨了。当时我那股天真和傻气的劲儿,就仿佛最不懂得分清现实和幻想的那一类追星族。当人力资源部的招聘经理对我说那番话时,我还一度相当不解。

   然而上班短短几天后,我已经不存在任何幻想了。眼前的现实告诉我,在制度严谨规范的微软,如果我没有特殊的作为,可能永远也无法和比尔·盖茨说上一句 话。身处世界上最宏伟的软件帝国,我无法不生敬畏之心。就像一条小溪突然汇进了浩瀚的大海,我感觉自己一下子就被淹没了。我不禁自问:"唐骏,你什么时候 才能在这里熬出头?"

  一年以后,我才终于见到了比尔·盖茨。那是在微软的年度员工大会上,在租来的超大体育场里,我的目光从几百 米之外,掠过上万名同事,默默地落在那个模糊而又清晰的身影上。在那一刻,我又感觉到了自己身上的巨大力量,和想要靠近那个身影的强烈愿望。我要证明,即 使不能达到他的高度,我也有一颗同样向上的心。

附:唐骏自传:我的成功可以复制(连载)

基于神经网络的车牌自动识别系统研究

硕士学位论文
http://218.69.114.37/wf/~CDDBN/Y667566/PDF/INDEX.HTM

2009年3月13日星期五

The IplImage Structure


Before reading this page it is highly advisable to quickly review the IplImage
structure, a version of which is kept on
this
page
. (Use 'Find' or [Ctrl-F] and type in 'IplImage'.)

OpenCV has a tendency to hide information, especially when you only tend to

use the HighGUI functions or the one-liner methods that take 15 parameters.
As such, you tend to miss some of the important stuff that can be useful to
know when working at the lower levels. This page is an attempt to address
the problem by showing you some of the 'inner workings' of the IplImage
structure.
It is worth noting that images are not stored using the 'traditional' RGB
colour space, they're actually
stored in BGR (the other way round). Why this is I'm not entirely sure, but
you don't tend to notice it as all the methods are written to use BGR as well.

Create An Image

To draw a red square we'll need to start off by creating an image.


IplImage *img = cvCreateImage(cvSize(100, 100), IPL_DEPTH_8U, 3);

This creates an image of width/height 100/100, using 8-bit unsigned integers
to represent the colour values, and with 3 colour channels.
However, 8-bit unsigned values are not the only type available; values can
also be held as 32-bit floating point numbers (IPL_DEPTH_32F) and a variety
of other ways. In each case the depth is represented as
IPL_DEPTH_<bits>{U|S|F} where U, S and F stand for unsigned, signed
and floating point. i.e.

  • IPL_DEPTH_8U
  • IPL_DEPTH_8S
  • IPL_DEPTH_16U
  • IPL_DEPTH_16S
  • IPL_DEPTH_32S
  • IPL_DEPTH_32F
  • IPL_DEPTH_64F

Also notice that it's a pointer to an image - all images should be created in
this way when using OpenCV as most (if not all) of its methods take image
pointers as parameters in order to modify images directly.

Image Data

Images are not stored by pixel. Instead they are stored as arrays of colour
levels which means less processor overhead as you're not constantly
dereferencing pointers. These arrays of colour are stored in BGR order
(as mentioned above).

e.g. IplImage's imageData field looks like this...





















imageData[0] imageData[1] imageData[2] imageData[3] imageData[4] imageData[5]
BGRBGR
colour values go in these elements

...as opposed to this:






















imageData[0] imageData[1]
-> red -> green -> blue -> red -> green -> blue
colour values go in these elements

Greyscale image structures differ very slightly - instead of having three

channels they have just the one (for brightness) that can be accessed in the
same way.

i.e. cvCreateImage(cvSize(100, 100), IPL_DEPTH_8U, 1)

In this case the first pixel would be imageData[0], the second would be
imageData[1] and so on.

Finally, images in OpenCV are padded. Most image formats available today such
as JPEG, PNG, TIFF and the like are padded out so that the number of columns
in an image is divisible by 4 - with the exception of BMPs. This means that
if you ever get round to converting between image structures using BMPs, you
can get some rather interesting skewing effects if you try to simply copy the
data arrays over. (This was discovered whilst trying to convert between Leeds'
libRTImage library and OpenCV. If you're interested,
this is what I came up with.)


Direct Pixel Access

So to get our red square going we'll just have to edit every third channel.
Direct access of the pixels is possible using the imageData attribute and the
number of bytes in the image (or img->imageSize) can be used as a
quick way of bounding the for loop.

img->imageData[i] = value;

so we get:
int i;

for (i = 2; i < img->imageSize; i+=3)

img->imageData[i] = 255;


(For a finished file which displays the square in a window, click
here.)


It is worth noting that while most images and methods in OpenCV use or
return 8-bit unsigned data (e.g. cvLoadImage always returns an IPL_DEPTH_8U
image), this is not how OpenCV is written. imageData isn't int
or float, it's actually a char pointer to data within IplImage.

It would seem that this is done for versatility, but presents a little
confusion on use with your first 32-bit float image. 32F images can only hold
values between 0 and 1, but to a rather high degree of accuracy (as you would
expect), so we have to adjust values accordingly. We also have to change the
way for loops are defined - imageSize is measured in bytes and as there
are now four bytes per colour value (floats are four bytes each), the
for loop returns a segmentation fault a quarter of the way through its life
if we use the same code as before. Instead we can use the image's width
and height attributes, multiplying by 3 so that all channels are filled.
Finally, the values themselves need to be converted to float pointers so that
the data is stored in the correct format. The following code should clarify
things.

int i;

for (i = 0; i < img->width*img->height*3; i+=3)

{

((float*)img->imageData)[i] = 64/256.0;

((float*)img->imageData)[i+1] = 196/256.0;

((float*)img->imageData)[i+2] = 256/256.0;


}

The orange square program shows the complete version of the above.
Click here to see it.

Image Representations

There are several colour space conversions available within OpenCV, through
use of the cvCvtColor function:

cvCvtColor(source, destination, space_code);

Here, space_code typically takes the form of the source colour space and
the desired colour space, but note that in each case the source and destination
images must have the correct number of channels. The possible codes are:

Simple:

  • CV_BGR2RGB
  • CV_RGB2BGR
  • CV_BGR2GRAY
  • CV_RGB2GRAY
  • CV_GRAY2BGR
  • CV_GRAY2RGB
CIE XYZ:
  • CV_BGR2XYZ
  • CV_RGB2XYZ
  • CV_XYZ2BGR
  • CV_XYZ2RGB
YCrCb JPEG (a.k.a. YCC)
  • CV_BGR2YCrCb
  • CV_RGB2YCrCb
  • CV_YCrCb2BGR
  • CV_YCrCb2RGB
HSV:
  • CV_BGR2HSV
  • CV_RGB2HSV
  • CV_HSV2BGR
  • CV_HSV2RGB
HLS:
  • CV_BGR2HLS
  • CV_RGB2HLS
  • CV_HLS2BGR
  • CV_HLS2RGB
CIE Lab:
  • CV_BGR2Lab
  • CV_RGB2Lab
  • CV_Lab2BGR
  • CV_Lab2RGB
CIE Luv:
  • CV_BGR2Luv
  • CV_RGB2Luv
  • CV_Luv2BGR
  • CV_Luv2RGB
Bayer (a pattern widely used in CCD and CMOS cameras):
  • CV_BayerBG2BGR
  • CV_BayerGB2BGR
  • CV_BayerRG2BGR
  • CV_BayerGR2BGR
  • CV_BayerBG2RGB
  • CV_BayerGB2RGB
  • CV_BayerRG2RGB
  • CV_BayerGR2RGB
However, whilst IplImage's attributes include one for colorModel,
OpenCV completely ignores this when displaying or processing an image. Instead
it chooses to assume BGR order, and this can lead to strange image output if
displayed using cvShowImage.

2009年3月12日星期四

看到的一份不错的介绍“堆和栈的区别”的资料






http://topic.csdn.net/u/20090306/09/5EC55BDC-F2A9-4048-88B4-63616069DF31.html

堆和栈的区别(转贴,作者为一c++程序员,具体姓名不清楚)
一、预备知识—程序的内存分配
一个由c/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)—> 由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap)—> 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—>全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。- 程序结束后由系统释放
4、文字常量区—>常量字符串就是放在这里的。程序结束后由系统释放
5、程序代码区—>存放函数体的二进制代码。
二、例子程序
这是一个前辈写的,非常详细
//main.cpp
int a = 0; //全局初始化区
char *p1; //全局未初始化区
main()
{
    int b; //栈
char s[] = "abc"; //栈
char *p2; //栈
char *p3 = "123456"; //123456\0在常量区,p3在栈上。
static int c =0; //全局(静态)初始化区
p1 = (char *)malloc(10);
    p2 = (char *)malloc(20); //分配得来的和字节的区域就在堆区。
strcpy(p1, "123456"); //123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。

二、堆和栈的理论知识
2.1申请方式
stack:
由系统自动分配。例如,声明在函数中一个局部变量int b; 系统自动在栈中为b开辟空间
heap:
需要程序员自己申请,并指明大小,在c中malloc函数
如p1 = (char *)malloc(10);
在C++中用new运算符
如p2 = (char *)malloc(10);
但是注意p1、p2本身是在栈中的。
2.2
申请后系统的响应
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。
堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程
序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。
2.3申请大小的限制

栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在
WINDOWS下,栈的大小是M(也有的说是M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能
从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
2.4申请效率的比较:
栈由系统自动分配,速度较快。但程序员是无法控制的。

堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.
另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,他不是在堆,也不是在栈是直接在进程的地址空间中保留一快内存,虽然用起来
最不方便。但是速度快,也最灵活。
2.5堆和栈中的存储内容

栈:在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数
是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地
址,也就是主函数中的下一条指令,
程序由该点继续运行。
堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。
2.6存取效率的比较
char s1[] = "aaaaaaaaaaaaaaa";
char *s2 = "bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa是在运行时刻赋值的;而bbbbbbbbbbb是在编译时就确定的;
但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。
比如:
#include
void main()
{
char a = 1;
char c[] = "1234567890";
char *p ="1234567890";
a = c[1];
a = p[1];
return;
}
对应的汇编代码
10: a = c[1];
00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]
0040106A 88 4D FC mov byte ptr [ebp-4],cl
11: a = p[1];
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]
00401070 8A 42 01 mov al,byte ptr [edx+1]
00401073 88 45 FC mov byte ptr [ebp-4],al
第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指针值读到edx中,在根据edx读取字符,显然慢了。
2.7小结:
堆和栈的区别可以用如下的比喻来看出:
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作
和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。

2009年3月5日星期四

OpenCV中IplImage图像格式

OpenCV中IplImage图像格式与BYTE图像数据的转换

IplImage* iplImage;

BYTE* data;

1 由IplImage*得到BYTE*图像数据:

data = iplImage->imageDataOrigin; //未对齐的原始图像数据

或者

data = iplImage->imageData; //已对齐的图像数据

2 由BYTE*得到IplImage*图像数据

iplImage = cvCreateImageHeader(cvSize(width,height),depth,channels);

cvSetData(iplImage,data,step);

首先由cvCreateImageHeader()创建IplImage图像头,制定图像的尺寸,深度和通道数;然后由cvSetData()根据 BYTE*图像数据指针设置IplImage图像头的数据数据,其中step指定该IplImage图像每行占的字节数,对于1通道的 IPL_DEPTH_8U图像,step可以等于width。

1,如果是从新创造一个Iplimage,则用IplImage* cvCreateImage( CvSize size, int depth, int channels ),它创建头并分配数据。



注:当不再使用这个新图像时,要调用void cvReleaseImage( IplImage** image )将它的头和图像数据释放!



2,如果有图像数据没有为图像头分配存储空间(即,没有为IplImage*指针分配动态存储空间),则先调用IplImage* cvCreateImageHeader( CvSize size, int depth, int channels )创建图像头,再调用void cvSetData( CvArr* arr, void* data, int step )指定图像数据,可以理解为将这个新图像的数据指针指向了一个已存在的图像数据上,不存在图像数据存储空间的分配操作。



注:当不再使用这个新图像时,要调用void cvReleaseImageHeader( IplImage** image )将它的图像头释放!



3,如果有图像数据也有图像头(用于IplImage为静态分配存储空间的情况),则先调用IplImage* cvInitImageHeader( CvSize size, int depth, int channels )更改图像头,再调用void cvSetData( CvArr* arr, void* data, int step )指定图像数据。



注:因为这个新图像使用的是其它图像的数据和已有的图像头,所以不能使用cvReleaseImage将它的头和图像数据释放,也不能使用cvReleaseData将它的图像数据释放!



4,如果从已有的一个图像创建,则用IplImage* cvCloneImage( const IplImage* image ),它制作图像的完整拷贝包括头、ROI和数据。



注:当不再使用这个新图像时,要调用void cvReleaseImage( IplImage** image )将它的头和图像数据释放!


欢迎访问、交流!对本博客有何建议,请
来信告知!
本博内容来源于网络,如有不当或侵犯权益,请来信告知,将及时撤除!
如引用博客内容、论文,请注明原作者!

Google一下本博客

  • 《Getting Things Done》读书笔记 - 本文来自 inertial 原创投稿。 我第一次听说《Getting Things Done》这本书的时候误以为它和世面上的那些成功学书籍没什么区别,后来在不少书中看到了这个名字,也看见了很多人的推荐,由此产生了很大的兴趣。上个月正好有不少空闲,就抽时间把这本书读完了。 本来打算读英文原版,但是原版的生...
    5 年前
  • [原]Linux下编译使用boost库 - Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一。 Boost库由C++标准委员会库工作组成员发起,其中有些内容有望成为下一代C++标准库内容。在C++社区中影响甚大,是不折不扣的“准”标准库。Boost由于其对跨平台的强调,对标准C++的强调,与...
    6 年前
  • [原]猎头、培训与咨询的价值(2)【补1】——北漂18年(93) - 【上期用手机写的,同时用语音输入转化成文字,错字较多,经好友霍师傅提醒本期重写,并增加一部分新内容】 简单谈下我对猎头、培训与咨询的看法。三样都干过,算是有些浅见。 猎头 简单的说就是人才中介。虽然在公司看来是可以直接解决现有企业问题的一个直接方法,但很多时候都不太管用。 猎头费一般是人才的一个月月...
    6 年前
  • OpenCV統計應用-Mahalanobis距離 - Mahalanobis距離是一個可以準確找出資料分布上面極端值(Outliers)的統計方法,使用線性迴歸的概念,也就是說他使用的是共變數矩陣以及該資料分布的平均數來找尋極端值的產生,而可以讓一群資料系統具有穩健性(Robust),去除不必要的雜訊訊息,這邊拿前面共變數矩陣的資料為例,並且新增了兩個點座標向量來做...
    15 年前
  • 努力推进模式识别实际产品的开发与应用 - Salu 无论是手写体识别、文档处理、人脸识别、基于内容的图片搜索、嵌入人工智能的搜索技术、虚拟网络社区、还是其它相关新科技下的信息整合领域,现在都在努力实用化。 前两年、即使现在还有很多人在抱怨说人脸的方法都不能用,但是就今年出现的和正在做的有关人脸识别实际应用的各种形式的产品可以说如雨后春笋。这是一个趋...
    15 年前