2009年4月27日星期一

MFC中应用OpenCV教程

申明:来源于网络,引用请注明出处!

论文:下载
下载后,是没有扩展名的一个文件,拖到你的word后即可打开。
部分内容来自网络,所引内容并不代表认同其观点。本博内容如有不当或侵犯权益,请来信告知!

2009年4月26日星期日

自信是怎样炼成的[转帖]

转自

本文摘自文汇报《开放你的人生》

关于如何培养自信,很多的书中都有介绍各种理论。但自信是怎样炼成的,用案例最有说服力,这里有几个小案例供大家分享。

  • 有才华就要大胆地展示

1984年,现中国科技部部长、当时还是同济大学力学系研究生的万钢,登上了前往德国的飞机。在德国第一件事,就是跟同伴一起到克劳斯塔尔大学的外办,了解学习计划的安排。当时,外办的老师提出,作为外国留学生,首先必须参加PNDS考试(德语入学考试)。考试半年举行一次,他必须等到秋季参加考试通过后才能开始他的博士学业。万钢当场就很自信地表示:自己的德语这么好,为什么一定要考试?一定要等这么久才开始正式的学习?

外办的老师表示怀疑,来该校就读的留学生不知道有多少,还从来没人敢说自己德语好到不需要考试的地步。但经过万钢用德语毫不妥协的"攻关"之后,外办老师最后只能表态:"如果你真觉得不需要考试,那去跟几个教授谈谈,看看是否可以免试。"

后来,万钢就和外办指定的几个教授聊了整整一个小时,用德语回答各种问题,接受各种语言测试,最终让教授们心服口服――同意免试。万钢也因此成了克劳斯塔尔大学历史上唯一一个没有参加PNDS考试而直接入学的外国留学生。他自己总结说:在该自信的地方就一定要敢于自信,不过分谦虚就是实事求是的精神,有才华就要大胆地展示。

许多人都有过这样的亲身经历,一旦认定某件事不可能取得成功,那么,你就算尽力而为,成功的可能性也大大降低。因为你戴上了心理的镣铐,拒绝了超常的努力,所以也拒绝了奇迹的发生。而你相信自己在擅长和具有优势的方向上的努力,并坚持行动,虽然不一定能够迎来转机,但奇迹发生的可能性肯定会大大增加。

  • 潘杰客初到美国为什么会被看不起?

北京华商会监事潘杰客的人生事业非常开放,他做过国家建设部党委宣传部副部长,当过凤凰卫视的主持人,还创业当过老板,也做过职业经理人。但是他初到美国时,却被身边的同学所看不起。

潘杰客刚去美国时,住在美国的父母家里,吃、穿、用都依赖父母。这在中国人看来,是再习以为常不过了。但是,潘杰客晚上去英文夜校补习外语时,却发现周围的同学都看不起他,并且孤立他。

"我特别骄傲地跟人说我父亲是康奈尔大学毕业的,英文特别好,我还说我父亲教我英文。结果这些同学对我不屑一顾,说我们也英语不行,可我们一样能打工,然后到夜校读书,你竟然还有优越感?你都是靠别人啊!"

最后,潘杰客不得不改变自己:"我在家里住了三个月就搬出来,住在纽约的地下室,因为地下室便宜,并且还在快餐店送外卖养活自己。我觉得,如果我再要兄弟姐妹和父母的帮助,是一种耻辱,因为美国的文化是18岁就开始靠自己,我那时30岁了,所以我必须靠自己。"

这样来看西方国家的家庭教育就很好理解了:一方面,他们淡化家庭之间互相依附的关系,培养孩子独立、自立的意识和能力,个性的文化正是其教育观的体现;另一方面,他们尊重普遍性的人性和人权,实际上也就尊重了孩子的基本权益,并引导孩子养成这样的价值观。

自立并不意味着不需要别人的帮助,而是强调自主,不成为他人的附属物。独立也不意味着排他性或者封闭性,不去学习和借鉴成功者,只是强调要有自己的思考和判断。

  • 克服消极浮躁的心态

前亚洲开发银行驻中国首席经济学家汤敏曾回忆道,1973年,他被派到广西南宁第四中学当数学老师。他高中都没有毕业,但他必须去给一群跟自己差不多大的学生上课。有人这样问他:"你在讲台上如何能够自信?"

汤敏的回答是:克制情绪,保持乐观,然后自学。他经常是"上周自己刚自学完,这周就要给学生上课"。

1977年10月恢复高考,广西考区对考生的年龄限制是25岁,汤敏已经24岁了。他很想参加高考,可有三个原因在向他说"NO":第一,没有把握,除了数学自学过外,英语、物理、化学都没学过;第二,朋友家人不支持,因为他已经有份稳定的教师工作,普通师范大学毕业也不过当一个中学老师;第三,面子问题,和学生一起考试,"压力很大,如果考不过学生或者考砸了,肯定很丢脸"。

人要做成什么事,就不能有那么多的疑虑,人生难免有些尴尬,关键在于保持心态的良好和积极,汤敏这样认为。最后,他参加了考试,并且改变了自己的一生,最终成为中国著名的经济学家。

对于刚毕业的大学生以及初入职场的年轻人来说,最常见的心态问题有两种,一是眼高手低;二是有些自卑,不敢争取机会。

年轻人在找工作之前,应该结合自己的具体情况,包括学历、专业、年龄、籍贯、学习、工作、兴趣、理想等各方面因素,进行综合考虑,进行恰当定位,这样心态的积极才有落点和杠杆。

如何培养良好的心态和情绪,坚定自己的自信,在对200多位成功人士调研的基础上,我归纳出如下建议:

    1. 永远不要有绝对不可能的消极想法;
    2. 确立切实可行的目标,然后树立必胜的信念;
    3. 罗列自己的特长和优点以及能够在竞争中取胜的优势;
    4. 学会宽容该宽容的人包括自己的过失,也欣赏别人以及自己的成就;
    5. 学会感激别人的帮助,培养双赢的合作思维;
    6. 学会乐观地看待身边的人和事,哪怕是一些不如意的。
    • 敢于放弃也是一种冒险

    美国凯雷投资集团董事总经理何欣曾提到过自己一次没有"敢于放弃"的经历。2001年,何欣从INTEL投资部加盟凯雷投资集团担任亚太投资部副总裁。年底,他接触一个韩国"下一代OLED"的有机显示屏项目。何欣看上了这个团队的技术能力和OLED的市场潜力,但这也是一个非常典型的早期项目," 我们开始看这个项目时,只有专利和图纸。"

    第一轮融资,凯雷投入500万美元。随后问题来了:"OLED技术的实现,需要周边配套技术。"技术发明人是个姓金的博士,而金博士团队只有产品研发能力和生产流程的设计,没有生产技术设备的制造能力。凯雷和其他VC第二轮于是又投入1500万美元,可问题又来了,原材料价格上升,公司需要降低生产成本等等。凯雷再次联合众多VC进行了第三轮融资。

    第三次投资之后,问题还是不断。这时,金博士说:"我想辞职。"何欣了解到作为发起人的金博士还有另外一个公司,他的心已经不在这儿了。"在凯雷的带动下有三轮融资,最后项目融资总额接近1亿美元。但第四轮时,我决定不投了。我对团队很失望。"

    最后的损失当然很大。凯雷的亚太基金负责人祖文萃评价说:第一笔投资没有问题,经过8个月的调研,事先的风险都想过。错就错在第三笔投资不应该再追加,出现这么多的问题,说明团队的执行力不行。不能一错再错了,这时放弃也是值得去冒险的行为。

    我们有胆略去冒险,其实就意味着把冒险当作一门战略艺术。我归纳了一些成功人士的经验教训,希望能为年轻人作些参考:

      1. 首先要确立可以专注的核心目标。冒险不是无头苍蝇一般乱飞乱闯,或者飞蛾扑火一般莽撞,千万不要异想天开,没有企业能够什么都做得好。
      2. 评估风险。行动前要明确自己所能承受的风险范围,有时不可不做最坏的估算,不要相信这个世界上有大收益却没有风险的好事,天上不会掉馅饼。
      3. 不要拒绝盟友,也切勿替别人去冒险,替别人冒险通常不是件吃力就能讨好的事。
      4. 制定合适的行动计划。不要怀着试试看的心态在重要的事上冒险。如果是为了失败而行动,那又是何苦呢?最可怕的事永远是你既不全力去争取成功,又继续投入精力和成本。
      5. 注意随机应变。勇敢不是没有恐惧和担心,问题也绝不会忽视你,到头来你仍然要逐一解决,因此,应该选择最有利的时机做最有利的事。
        • 刘江南立足阿尔卡特公司的"非常道"策划

        阿尔卡特公司中国区副总裁刘江南刚进公司时,他发现公司里每个人都忙忙碌碌,像机器一样定期把自己的工作和业绩变成表格上的数字,逐级上报直至变成公司的报表。而公司的几个核心人物再根据这些数字,把好的分出来拿到市场上去卖了。而他来公司快一个月了,"还不知道自己应该干什么。参加了几次公司的业务会,满篇的专有名词,弄得我一头雾水,不知所云。我甚至怀疑,阿尔卡特是否找错人了。"

        刘江南认为"在这样的公司里,命运不是掌握在自己手里的"。他曾找到公司总裁,但是"总裁说他很忙,顾不上细想我的事……"刘江南意识到,"自己不是这个专业出身,在这样技术很强的公司里,能有什么作为?"经过思考,刘江南认为"要以非常态的作为使自己进入常态",就必须策划一件"公司上下都认为不可能的大事"。

        刘江南的计划就是让中国的国家主席会见公司的最高领导――这是一个"乍看起来有点像铤而走险,但仔细想想实际上是一项风险极小而获利极高的策划"。后来,当CCTV播放中国国家主席接见阿尔卡特公司董事长的新闻时,刘江南一下子受到了公司高层的认可。

        许多人的人生之所以失败,就是因为对自己的人生缺乏主动策划,或者缺乏有效的策划,因此总是被命运和生活所奴役,不能自主人生。

        缺少策划者多半是自己都不知道自己在做什么、不为自己而是为现实生活主控的人,也是"当一天和尚,撞一天钟"随波逐流混日子的人。当然,我们也不会知道他能做出什么来。

        英文的车牌识别综述文章

        英文的车牌识别综述文章

        汉王车牌识别指标

        申明:来源于网络,引用请注明原作者!
        内容来自网络,所引内容并不代表认同其观点。本博内容如有不当或侵犯权益,请来信告知!

        车牌识别技术指标

          1、系统具备对92式民用、2002式民用、警用、2004式军用、武警、港澳式等汽车号牌的计算机自动识别能力。
          2、车牌整牌识别率 ≥95%
          3、车牌定位率 ≥99%
          4、车牌字符识别率 ≥99%
          5、识别速度 <0.15s
          6、抓拍车辆通行速度 <250km/h
          7、图像分辨率 768x576
          8、输出图像格式 JPGE
          9、输出图像色彩 彩色
          10、通讯端口 RS485/RS232串口/以太网
          11、平均无故障运行时间(MTBF) >30000小时
          12、工作电压 165V~240V AC 50Hz±1Hz
          13、功耗 10―15W







        基于Hausdorff距离的多尺度轮廓匹配算法

        来源于网络,引用请注明出处
        论文:下载


        2009年4月25日星期六

        综述性论文——几种车牌字符识别算法的比较


        几种车牌字符识别算法的比较.pdf

        The full "Square Detector" program.//检测矩形的例子

        矩形检测程序,
        浏览
        //
        // The full "Square Detector" program.
        // It loads several images subsequentally and tries to find squares in
        // each image
        //
        #ifdef _CH_
        #pragma package
        #endif

        #ifndef _EiC
        #include "cv.h"
        #include "highgui.h"
        #include
        #include
        #include
        #endif

        int thresh = 50;
        IplImage* img = 0;
        IplImage* img0 = 0;
        CvMemStorage* storage = 0;
        CvPoint pt[4];
        const char* wndname = "Square Detection Demo";

        // helper function:
        // finds a cosine of angle between vectors
        // from pt0->pt1 and from pt0->pt2
        double angle( CvPoint* pt1, CvPoint* pt2, CvPoint* pt0 )
        {
        double dx1 = pt1->x - pt0->x;
        double dy1 = pt1->y - pt0->y;
        double dx2 = pt2->x - pt0->x;
        double dy2 = pt2->y - pt0->y;
        return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
        }

        // returns sequence of squares detected on the image.
        // the sequence is stored in the specified memory storage
        CvSeq* findSquares4( IplImage* img, CvMemStorage* storage )
        {
        CvSeq* contours;
        int i, c, l, N = 11;
        CvSize sz = cvSize( img->width & -2, img->height & -2 );
        IplImage* timg = cvCloneImage( img ); // make a copy of input image
        IplImage* gray = cvCreateImage( sz, 8, 1 );
        IplImage* pyr = cvCreateImage( cvSize(sz.width/2, sz.height/2), 8, 3 );
        IplImage* tgray;
        CvSeq* result;
        double s, t;
        // create empty sequence that will contain points -
        // 4 points per square (the square's vertices)
        CvSeq* squares = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage );

        // select the maximum ROI in the image
        // with the width and height divisible by 2
        cvSetImageROI( timg, cvRect( 0, 0, sz.width, sz.height ));

        // down-scale and upscale the image to filter out the noise
        cvPyrDown( timg, pyr, 7 );
        cvPyrUp( pyr, timg, 7 );
        tgray = cvCreateImage( sz, 8, 1 );

        // find squares in every color plane of the image
        for( c = 0; c < l =" 0;" l ="=" result =" cvApproxPoly(">total == 4 &&
        fabs(cvContourArea(result,CV_WHOLE_SEQ)) > 1000 &&
        cvCheckContourConvexity(result) )
        {
        s = 0;

        for( i = 0; i <>= 2 )
        {
        t = fabs(angle(
        (CvPoint*)cvGetSeqElem( result, i ),
        (CvPoint*)cvGetSeqElem( result, i-2 ),
        (CvPoint*)cvGetSeqElem( result, i-1 )));
        s = s > t ? s : t;
        }
        }

        // if cosines of all angles are small
        // (all angles are ~90 degree) then write quandrange
        // vertices to resultant sequence
        if( s < i =" 0;" contours =" contours-">h_next;
        }
        }
        }

        // release all the temporary images
        cvReleaseImage( &gray );
        cvReleaseImage( &pyr );
        cvReleaseImage( &tgray );
        cvReleaseImage( &timg );

        return squares;
        }


        // the function draws all the squares in the image
        void drawSquares( IplImage* img, CvSeq* squares )
        {
        CvSeqReader reader;
        IplImage* cpy = cvCloneImage( img );
        int i;

        // initialize reader of the sequence
        cvStartReadSeq( squares, &reader, 0 );

        // read 4 sequence elements at a time (all vertices of a square)
        for( i = 0; i <>total; i += 4 )
        {
        CvPoint* rect = pt;
        int count = 4;

        // read 4 vertices
        memcpy( pt, reader.ptr, squares->elem_size );
        CV_NEXT_SEQ_ELEM( squares->elem_size, reader );
        memcpy( pt + 1, reader.ptr, squares->elem_size );
        CV_NEXT_SEQ_ELEM( squares->elem_size, reader );
        memcpy( pt + 2, reader.ptr, squares->elem_size );
        CV_NEXT_SEQ_ELEM( squares->elem_size, reader );
        memcpy( pt + 3, reader.ptr, squares->elem_size );
        CV_NEXT_SEQ_ELEM( squares->elem_size, reader );

        // draw the square as a closed polyline
        cvPolyLine( cpy, &rect, &count, 1, 1, CV_RGB(0,255,0), 3, CV_AA, 0 );
        }

        // show the resultant image
        cvShowImage( wndname, cpy );
        cvReleaseImage( &cpy );
        }


        void on_trackbar( int a )
        {
        if( img )
        drawSquares( img, findSquares4( img, storage ) );
        }

        char* names[] = { "pic1.png", "pic2.png", "pic3.png",
        "pic4.png", "pic5.png", "pic6.png", 0 };

        int main(int argc, char** argv)
        {
        int i, c;
        // create memory storage that will contain all the dynamic data
        storage = cvCreateMemStorage(0);

        for( i = 0; names[i] != 0; i++ )
        {
        // load i-th image
        img0 = cvLoadImage( names[i], 1 );
        if( !img0 )
        {
        printf("Couldn't load %s\n", names[i] );
        continue;
        }
        img = cvCloneImage( img0 );

        // create window and a trackbar (slider) with parent "image" and set callback
        // (the slider regulates upper threshold, passed to Canny edge detector)
        cvNamedWindow( wndname, 1 );
        cvCreateTrackbar( "canny thresh", wndname, &thresh, 1000, on_trackbar );

        // force the image processing
        on_trackbar(0);
        // wait for key.
        // Also the function cvWaitKey takes care of event processing
        c = cvWaitKey(0);
        // release both images
        cvReleaseImage( &img );
        cvReleaseImage( &img0 );
        // clear memory storage - reset free space position
        cvClearMemStorage( storage );
        if( c == 27 )
        break;
        }

        cvDestroyWindow( wndname );

        return 0;
        }

        #ifdef _EiC
        main(1,"squares.c");
        #endif

        2009年4月14日星期二

        Re: ANPR/Car number-plate recognition


        Re: ANPR/Car number-plate recognition


        Posted by: "beat.naef"
        beat.naef@yahoo.com

         

        beat.naef



        Mon Apr 13, 2009 3:11 am (PDT)





        Monica,

        I uploaded a small image set taken by an IR LPC to the file/LPR Project dir and some BlobAnalysis-based code.



        Are you working on a LPR project also? If so would you mind sharing your experience and code?



        Regards

        Beat

        --- In OpenCV@yahoogroups.com, Monica Guzman <monait2003@...> wrote:

        > Hi, can you send me a lot of images and videos obtained from your ir camera....

        > Grettings..


        > --- El vie 10-abr-09, beat.naef <beat.naef@...> escribió:



        > De:: beat.naef <beat.naef@...>

        > Asunto: [OpenCV] Re: ANPR/Car number-plate recognition

        > A: OpenCV@yahoogroups.com

        > Fecha: viernes 10 de abril de 2009, 10:26



        > I have also started a LPR project using OpenCV. I am using
        gray-scale images taken by a true IR LPC (Bosch/ ExtremeCCTV Reg-X,
        combined with Axis 241S video server to capture jpg image sequences
        (M-JPEG)) that is installed in the field (actually several LPC
        installations) .

        >

        > I have tried a number of approaches:

        > 1. using the square.c code in the OpenCV src samples (experiment
        with different image smoothing, morphing techniques, etch/ contour
        detection techniques)

        > 2. tested with some SIFT code

        > 3. in the process of testing haar-like feature method

        > 4. in the process of testing background averaging method

        >

        > Approach 1 was initially promising. But when I tested about 100
        randomly selected images against it, the success rate was not very high
        (that maybe a reflection of my lack of experience in computer vision
        technologies and to fine-tune object recognition) .

        > Approach 2 initial tests were not very exciting because not too
        many matching candidates points were found. However, I have not spend a
        lot of time to fine-tune and experiment

        > Approach 3 still need to adapt code and learn more about the technology

        > Approach 4 same as 3

        >

        > I am interested in sharing my experience and data sets and
        starting an OpenSource project on SF anybody interested? Anybody
        interested?

        >

        > Beat

        >

        > --- In OpenCV@yahoogroups. com, Alper Yaman <alperyaman@ ...> wrote:

        > >

        > > You can use bottomhat transform to get rid of trouble in case
        of the same  color of car and plate. In addition, you can use radon
        transform to correct skewing. I tried so many methods to divide
        characters from the plate candidate region. First I extract the exact
        plate rectangle from the plate candidate region. Then I apply global
        threshold and labeling to get characters as objects. I elect the
        noncharacter object by some rules (area, width/length etc.). This
        method has some trouble while the exact plate region is somehow
        connected to the other regions. Does anyone have suggestion?

        > >

        > > Alper

        > >

        > >

        > > --- On Sat, 1/24/09, Carlos Frederico Mendes <opencvlist@ ...> wrote:

        > >

        > > From: Carlos Frederico Mendes <opencvlist@ ...>

        > > Subject: Re: [OpenCV] ANPR/Car number-plate recognition

        > > To: OpenCV@yahoogroups. com

        > > Date: Saturday, January 24, 2009, 3:36 PM



        > > Hi,

        > >

        > >

        > >

        > > I'm a novice in this area, but i already worked on a car license plate

        > >

        > > recognition program, i think you will have trouble to detect the rectangles

        > >

        > > in case the car have the same colour as the background of the license plate.

        > > Fred.


        > > On Fri, Jan 23, 2009 at 7:30 AM, ckd600 <alanp23@gmail. com> wrote:


        > > > Hi all,


        > > > Whilst I await delivery of my Learning OpenCV book, I'm thinking of

        > >

        > > > projects I'd like to look at. One is real-time car

        > >

        > > > license/registratio n plate alpha-numeric character recognition.


        > > > It's probably worth mentioning I had this idea in mind for UK plates

        > >

        > > > which are standard size, font, and colour.


        > > > My first idea of how it would work was like this:

        > > > - Detect rectangles(potentia l number plates) in an image

        > >

        > > > - Extract each rectangle found and try to split in to characters (not

        > >

        > > > sure how I'm going to do this, maybe I can detect the spacing between

        > > > the characters)

        > > > - Run each split character through a SURF scan of the standard UK font

        > > > character set and choose the highest % match

        > > > - Move to the next char



        > > > The only problem I can see is that it wont match if the image is

        > >

        > > > skewed, but that can be overcome by carefully planning the camera

        > >

        > > > position. An advantage is that it wont need to be trained, it will

        > >

        > > > just need a character set to work from.



        > > > What do you think?

        > >

        2009年4月11日星期六

        什么是库(library)

        http://docs.google.com/Doc?id=dcqjrshn_1373gx6cjcfx

        MFC与opencv示例文档

        http://docs.google.com/Doc?id=dcqjrshn_1370cvh8xdfd

        建立工程见

        http://www.opencv.org.cn/index.php/MFC%E4%B8%AD%E5%BF%AB%E9%80%9F%E5%BA%94%E7%94%A8OpenCV

        在Doc类中添加变量

        不要建立CImage m_image,改为

        public:

        IplImage *m_image;

        加头文件:

        #include "highgui.h"

        初始化 m_image

        CMFC_testDoc::CMFC_testDoc()

        {

        // TODO: add one-time construction code here

        m_image = NULL;

        }

        在工程中加入以下两个文件

        http://opencv-extension-library.googlec ... CvxWin32.h
        http://opencv-extension-library.googlec ... xWin32.cpp

        在stdafx.h中,加入#include "CvxWin32.h"

        在CvxWin32.cpp中加入 #include "stdafx.h"


        BOOL CMFC_testDoc::OnOpenDocument(LPCTSTR lpszPathName)

        {

        if (!CDocument::OnOpenDocument(lpszPathName))

        return FALSE;

        // TODO: Add your specialized creation code here

        m_image = cvLoadImage(lpszPathName);

        return TRUE;

        }

        BOOL CMFC_testDoc::OnSaveDocument(LPCTSTR lpszPathName)

        {

        // TODO: Add your specialized code here and/or call the base class

        cvSaveImage(lpszPathName,m_image);

        return TRUE;//CDocument::OnSaveDocument(lpszPathName);

        }

        在View类中添加显示图像代码

        void CMFC_testView::OnDraw(CDC* pDC)

        {

        CMFC_testDoc* pDoc = GetDocument();

        ASSERT_VALID(pDoc);

        // TODO: add draw code for native data here

        CvxWin32::DrawToHDC(pDoc->m_image,pDC->GetSafeHdc(),NULL);

        }

        如果需要实现canny

        BOOL CMFC_testDoc::OnOpenDocument(LPCTSTR lpszPathName)

        {

        if (!CDocument::OnOpenDocument(lpszPathName))

        return FALSE;

        // TODO: Add your specialized creation code here

        m_image = cvLoadImage(lpszPathName,0);

        return TRUE;

        }


        void CMFC_testDoc::OnCanny()

        {

        // TODO: Add your command handler code here

        cvCanny(m_image,m_image,50,150,3);

        UpdateAllViews(NULL);

        }

        CvvImage的CopyOf()单通道解决


        另外听说,opencv1.1已经解决这个问题!

        2009年4月10日星期五

        关于CvvImage的CopyOf()函数的问题

        今天发现了一个问题,结果被证实貌似是OpenCV的bug。
        CvvImage cimg;
        cimg.CopyOf(img);
        其中img肯定是个 单通道的IplImage图像,cimg.CopyOf(img);出错。
        把img改成一个3通道的图像就没有问题了,是不是CopyOf只能拷3单通道的?

        我没有办法,又必须用CvvImage ,我用如下笨方法,结果是可以的
        CvvImage cimg;
        cimg.Create(img->width,img->height,8);
        IplImage* timg = cimg.GetImage();
        timg->imageData = img->imageData;//img为单通道

        我在论坛上发帖求助。我又尝试搜了一下,看又有其他人遇到此问题,
        结果果然有哥们比我先遇到了,呵呵。
        另外如果有用到
        CvvImage 的CopyOf()函数;而调试出错,估计都是这个问题。请注意!

        注: CvvImage 的CopyOf()函数常用于在控件 ID上显示图片。
        转一段代码
        void CTestDlg::DrawPicToHDC(IplImage *img, UINT ID)
        {
        CDC *pDC = GetDlgItem(ID)->GetDC();
        HDC hDC= pDC->GetSafeHdc();
        CRect rect;
        GetDlgItem(ID)->GetClientRect(&rect);
        CvvImage cimg;
        cimg.CopyOf(img);
        cimg.DrawToHDC(hDC,&rect);
        ReleaseDC(pDC);
        }


        2009年4月8日星期三

        基于笔画描述的文字识别OCR系统——技术说明

        基于笔画描述的文字识别OCR系统——技术说明
        时间: 2004-04-28 15:04:08 | [<<] [>>]

        1. 已排除的方法
          以下方法经过我们编写程序代码来实践验证了其不可行性。
          1.1 游程统计法
           思路:统计出点阵中的任意一点向六个角度0°、30°、60°、90°、120°、150°所能遍历的点数。如图2,最上一点往六个方向的最大值是 13,方向为上下方向(90°);又如,最左一点往六个方向的最大值是30,方向为左右方向(0°)。通过统计周围的点,可以轻易得到横竖捌捺点。

          
        图1 “南”字的游程统计

          缺点:文字在有杂点或扫描不清楚时,识别率很低或无法识别。例如:图2的“操”字就无法用游程统计法区分出横竖捌撇。

        图2

          1.2 瘦边法
          思路:对文字的笔画进行腐蚀、细线化处理,从而得到文字的骨架。

        图3 左图是瘦边法的理想效果,右图是黑体、粗体等瘦边后的效果

          缺点:由于黑体、粗体的笔画较粗,在进行腐蚀、细线化处理后,往往造成笔画丢失或产生多余笔画。如图4,由于“操”字有连笔,在使用瘦边法细化后产生了多余笔画,会造成误识别。

        图4

          1.3 X、Y方向归一法
          思路:对文字的笔画按X、Y方向求中点进行简化笔画。
          缺点:同上。
          
          此外,还有汉字特征法、匹配法、字根特征、粗外围特征法、笔画密度法等算法,但经我们编写代码来实践证明其效果不理想,所以在此不一一介绍。

        2. 我们现在采用的识别算法----双识别引擎
          我们采用双识别引擎,即:轮廓笔画描述、边角特征数据库。其中笔画描述是主要的识别算法,边角特征数据库是辅助的识别算法。
          2.1 轮廓笔画描述
           轮廓笔画描述为主要的识别方法,其关键是找出汉字点阵的轮廓,并对笔画的特性、关键性确定取舍。通过上面对传统OCR使用方法的分析,我公司花了近2年 的时间调研、编程测试,用实践来证明了:只有通过分析轮廓,才能更准确地得到横竖捌捺点。游程统计法、瘦边法、汉字特征法、匹配法、字根特征、归一法等算 法都无法成功地描述出笔画。
          原因一:只有基于“笔画描述”才能识别手写体文字,任何边角特征、匹配法、游程统计法等都无法归纳出手写体文字的特征,只能归纳印刷体。所以,“笔画描述”是手写体识别的唯一出路。
           原因二:经过我们编写代码来实践证明了瘦边法、归一法等简化笔画的识别方法是低效的、误差大的算法,这些算法容易丢失笔画或者产生多余的笔画。只有使用 “轮廓”才能体现出手写体文字的原貌,“轮廓”能够原汁原味地体现手写体文字的字形,而且能够实现二维的汉字点阵转化为二维矢量,实现汉字的高效识别。
          通过轮廓来描述笔画,使用许多无关大局的“短边”被“长边”归纳吞并,“曲线”被描述为“两段线段”,“局部凹凸”视周围环境也被归纳合并……这样,一个复杂的文字就被能用“尽可能少”的笔画描述出来。关键技术如下:
          2.1.1 描述轮廓,使用“逆(顺)时针搜索”算法描述出汉字的轮廓。见图5中的左图。
          假设:汉字是Width╳Height的点阵,任意一点都有左上、上、右上、右、右下、下、左下、左这8个方向的邻点。
          首先,x: 0→Width-1, y: 0→Height-1 搜索出一个黑点,该点设为P1;从点P1逆(顺)时针搜索出下一轮廓点P2,再从点P2逆(顺)时针搜索出下一轮廓点Pn……
          2.1.2 使用“切线最陡”算法区分出相邻的两个笔画。描述轮廓之后,笔画描述的关键在于决定从何处开始属于下一段笔画。经理论证明,使用“切线最陡”算法可以算出任意一点属于哪一笔画。见图5中的右图。
          假设:从第一步得到汉字的轮廓点的数组P1、P2……Pn,并且由于二维汉字点阵至少可以得到x、y坐标最大最小极值点(且至少存在4个符合这样条件的点MaxMin1、MaxMin2、MaxMin3、MaxMin4等);
           首先,遍历任意2个极值点(例如:MaxMin1和MaxMin2)之间的轮廓点,如果某一点Px的切线与MaxMin1、MaxMin2所在的直线的 夹角最大,且大于一定的角度Angle(如30°),则该点能把MaxMin1、MaxMin2“至少”分为两段笔画。
          接着,遍历MaxMin1和Px之间的轮廓点,同上步的原理判断是否再分为两段笔画;遍历Px和MaxMin2之间的轮廓点,同上步的原理判断是否再分为两段笔画。
          重复以上的步骤,就可以实现汉字轮廓矢量化。
          2.1.3 无关大局的“短边”被归纳、吞并、省略,一般取矩形的1/8或1/10为参考值,小于该参考值的边就考虑吞并、省略。
          2.1.4 由于描述曲线(撇、捺等)比较复杂,比较两条曲线的相对位置关系更复杂。因此,把曲线描述为两条或多条线段,转换为计算机易于操作的对象来处理。
          2.1.5 宋体字的横或竖等笔画起始端常有一个三角形的凸出点,通过强制记忆的方法,把它们省略。
          这样,所有印刷体、手写体都能用简单的笔画描述出来。

        图5 左图书是“林”的轮廓,右图是笔画描述的效果

          优点:识别速度快,不需要搜索数据库,直接由笔画得到识别结果。如果笔画足够清晰,能轻易地识别不同人书写的手写体,手写体文字识别率达到了80%以上。这正是传统OCR无法比拟的,因为传统OCR不是基于笔画描述的,不能识别或很难识别手写体。
          缺点:如果笔画模糊不清,很难用笔画来描述,如下图。

        图6 笔画描述对这样模糊不清的文字“矗”就无能为力

          解决方法:不要因为某方面的缺陷,而放弃一种不错的算法。使用下面介绍的第二种识别引擎,取长补短。


          2.2 边角特征数据库:改进型四边轮廓特征
          2.2.1 传统OCR的识别算法----四边轮廓特征法
           思路:每一汉字用32╳32点阵表示,分别从上下左右四个方向扫描汉字点阵,得到四个数值P1、P2、P3、P4,把这四个数值存入数据库。通过大量的 学习、记忆,得到一个所有汉字的四边特征数据库。用该方法识别汉字时,系统会从数据库中检索出一个最相似的汉字,得到识别结果。经我们编写程序、测试发 现,用该方法对印刷体文字进行识别,识别率可达60%以上。

        图1 “木”字的上边特征

          评价:中等

          2.2.2 改进型四边轮廓特征
           传统OCR的四边轮廓特征法,识别率不高,如:“国”、“囚”、“四”、“因”等字,因为它们的四边特征值是相同的,使用此方法无法区分、无法识别。因 此,我们使用提出了新的构思,使用新的算法:在汉字内部再次切割(按1/4切割),切割后再取四边特征Q1、Q2、Q3、Q4,这样,一个文字就的特征描 述就是P1、P2、P3、P4、Q1、Q2、Q3、Q4。通过大量的学习、记忆,得到一个所有汉字的内外四边特征数据库。识别汉字时,从数据库中检索出一 个最相似的汉字,得到识别结果。经过我们这样的改进,印刷体文字识别率达到了80%以上。

        图4 “囚”字按1/4切割后得到右边的图形

          评价:良

           通过以上同时使用两种识别引擎,扬长避短,印刷体文字的识别率提高到99%以上,手写体文字的识别率提高到90%以上。其中最显著的就是:成功解决了手 写体识别的关键问题。传统OCR识别局限于某种识别方法,无法同时解决模糊不清的印刷体、变形较多的手写体,而我们提出的两种识别引擎,将能轻易地解决这 种问题,并能在识别率、识别速度上有质的提高,可扩展性较强。

        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一下本博客

        • [原]Linux下编译使用boost库 - Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一。 Boost库由C++标准委员会库工作组成员发起,其中有些内容有望成为下一代C++标准库内容。在C++社区中影响甚大,是不折不扣的“准”标准库。Boost由于其对跨平台的强调,对标准C++的强调,与...
          8 年前
        • [原]猎头、培训与咨询的价值(2)【补1】——北漂18年(93) - 【上期用手机写的,同时用语音输入转化成文字,错字较多,经好友霍师傅提醒本期重写,并增加一部分新内容】 简单谈下我对猎头、培训与咨询的看法。三样都干过,算是有些浅见。 猎头 简单的说就是人才中介。虽然在公司看来是可以直接解决现有企业问题的一个直接方法,但很多时候都不太管用。 猎头费一般是人才的一个月月...
          9 年前
        • 我的时间管理道与术(三) - 本系列来自 水中颉 原创投稿。 本文续上篇《我的时间管理道与术(一):接受现实和感知时间》和《我的时间管理道与术(二):目标与计划》。 建立至上而下的检视机制 六个关注层面和检视周期 宗旨和使命、关键路径是云端;关键点和平衡点是方向指导层;项目是最接地气的现实目标层;下一步行动 是非常具体的待执行事务层...
          10 年前
        • OpenCV統計應用-Mahalanobis距離 - Mahalanobis距離是一個可以準確找出資料分布上面極端值(Outliers)的統計方法,使用線性迴歸的概念,也就是說他使用的是共變數矩陣以及該資料分布的平均數來找尋極端值的產生,而可以讓一群資料系統具有穩健性(Robust),去除不必要的雜訊訊息,這邊拿前面共變數矩陣的資料為例,並且新增了兩個點座標向量來做...
          17 年前
        • 努力推进模式识别实际产品的开发与应用 - Salu 无论是手写体识别、文档处理、人脸识别、基于内容的图片搜索、嵌入人工智能的搜索技术、虚拟网络社区、还是其它相关新科技下的信息整合领域,现在都在努力实用化。 前两年、即使现在还有很多人在抱怨说人脸的方法都不能用,但是就今年出现的和正在做的有关人脸识别实际应用的各种形式的产品可以说如雨后春笋。这是一个趋...
          18 年前