摘要: 以下文本及代码基本基于《OpenCV 2.4.13.0 documentation》的How to scan images, lookup tables and time measurement with OpenCV一节,英文好的同学可以直接看原文。 1. 颜色压缩 1. 颜色压缩 颜色压缩(Co 阅读全文
posted @ 2016-09-12 23:39 qdsclove 阅读(10861) 评论(0) 推荐(1) 编辑
摘要: Chars74K数据集是一个经典的字符识别数据集,主要包括了英文字符与坎那达语(Kannada)字符。数据集一共有74K幅图像,所以叫Chars74K。 英文数据集依据图像采集方式分为三个类别: 1. 自然环境下采集的字符图像数据集; 2. 手写字符图像数据集; 3. 计算机不同字体合成的字符图像数 阅读全文
posted @ 2016-09-12 17:20 qdsclove 阅读(9221) 评论(0) 推荐(0) 编辑
摘要: 数组并非指针“数组和指针是相同的”是一种非常危险、并不完全正确的说法。ANSI标准: extern int *x; // x是个int型的指针 extern int y[]; // y是个int型数组,长度尚未确定数组定义不等同于指针的外部声明的情况:文件1:// 定义了一个int数组int mango [100];文件2: // 外部声明的指向int型的指针 extern int * mango;上述代码的错误如下:什么是定义,什么是声明C语言中的“对象”(不同于C++或其他面向对象编程语言的‘对象’,这里的对象只是跟链接器有关的“东西”,如函数和变量)必须... 阅读全文
posted @ 2014-01-21 01:13 qdsclove 阅读(390) 评论(2) 推荐(0) 编辑
摘要: 3.1 何为内核对象工具WinObj可以查看所有类型的内核对象。每个内核对象都只是一个内存块,它由内核分配,并只能由内核访问。这个内存块是一个数据结构,其成员维护着与对象相关的信息。少数成员是所有对象都有的,但其他大多数成员都是不同的对象类型特有的——比如进程对象的PID,文件对象的共享模式。应用程序利用windows提供的一组函数,以经过良好定义的方式来操纵内核对象。句柄(handle)标识了内核对象,在32位进程中句柄为32位的值,在64位进程中则为64位值。句柄的值与进程是相关的。内核对象的生命期可能长于创建其的进程,内核对象的所有者是内核而非进程。所有的内核对象类型都包含的一个数据成员 阅读全文
posted @ 2014-01-05 00:09 qdsclove 阅读(412) 评论(0) 推荐(0) 编辑
  • 3.1 只有编译器才会喜欢的语法

C语言的声明语法(声明模型)很晦涩,容易成为程序员的障碍,正是由于在组合类型方面的笨拙行为,C语言显得很复杂。

造成这种情况的原因是因为“类型模型(type model)”这个概念对于当时的编程语言理论而言尚属陌生。BCPL(C语言前身)语言几乎没有类型,其以二进制字作为唯一的数据类型。
C语言的设计哲学之一:对象的声明形式与它的使用形式要尽可能相似
int *p[3]是一个int类型的指针数组。
其使用方法如下:
    // p 是一个指针数组,其中的每个元素都是一个指向 int类型的指针
    int * p[3];

    // 声明三个 int数组
    int a0[] = {2, 3, 4};
    int a1[] = {0, 1};
    int a2[] = {-8, 9, 0, 1, 3};

    // 赋值
    p[0] = a0;
    p[1] = a1;
    p[2] = a2;

    int i;
    printf( "a0:\t");
    for( i = 0; i < 3; i++, p[0]++)
    {
        printf("%d\t" , *p[0]);
    }
    printf( "\na1:\t");
    for( i = 0; i < 2; i++, p[1]++)
    {
        printf("%d\t" , *p[1]);
    }
    printf( "\na2:\t");
    for( i = 0; i < 4; i++, p[2]++)
    {
        printf("%d\t" , *p[2]);
    }
其执行结果如下:
 
 
C语言的声明所存在的最大问题是你无法以一种习惯性的从左向右的方式阅读一个声明
 
关于const
指针所指向的对象是只读的两种声明:
    const int i [] = {1024, 1045};

    // 指针所指向的对象是只读的
    const int * grape ;     // 等同于 const int (*grape)
    int const * orange ;    // 等同于 int const (*orange)
    grape = & i ;
    orange = & i ;

    printf( "%d\t" , *grape );  // grape: 1024
    grape++;                    // 合法,改变指针本身的值,grape指向i[1]
    printf( "%d\n" , *grape );  // grape: 1045
    //(*grape) += 4;           // 非法,改变指针所指向的 int 对象的值

 

指针本身是只读的声明:
    int i = 1024;

    // 指针本身是只读的
    int * const apple = &i;

    *apple += 4;   // 合法,改变指针所指向的对象的值

    // apple += 4;  // 非法,改变指针本身的值
       
    printf("i: %d\n", *apple );  // i的值变为1028

指针本身是只读
且指针所指向的对象也是只读的两种声明:
    const int i = 1024;

    // 指针本身只读 && 所指向的对象也只读
    const int * const grape_jam_1 = & i;
    int const * const grape_jam_2 = & i;

    grape_jam_1 += 4;   // 非法,不能改变指针本身的值
    *grape_jam_1 += 4;  // 非法,不能改变指针所指向对象的值
上面这段代码所产生的错误如下:
 
总结的规则:在指针的声明中,只要const“紧挨着”指针变量就说明该指针本身是只读的,否则就是该指针所指向的对象是只读的
 
  • 3.2 声明是如何形成的
声明器(declarator)是所有声明的核心。
声明器:标识符以及与它组合在一起的任何指针(*)、函数括号(())、数组下标([])等。
 
关于结构(struct)
 
结构就是一种把一些数据项组合在一起的数据结构。其语法为:
struct { 内容 ... };
结构的定义后可以跟一些变量名,表示这些变量的类型是这个结构:
struct { 内容 ... } plum, pomegranate, pear ;
struct关键字后可以加一个可选的“结构标签”,可以作为结构的简写形式(struct fruit_tag)用于以后定义变量:
struct fruit_tag { 内容... } plum, pomegranate , pear;
因此,结构的通常形式:
struct 结构标签 (可选){
    类型1 标识符1;
    类型2 标识符2;
    ....
} 变量定义( 可选);
作者建议不要把结构的声明和变量的定义混合在一起,而是分开,使代码更容易阅读。
变量的声明应该与类型的声明分开。
 
两个跟结构有关的参数传递问题:
  1. 函数在传递参数时,首先尽可能地存放在寄存器中(追求速度)。——一个int型参数一般会被传递到寄存器中,而结构参数则很可能被传递到堆栈中。
  2. 在结构中放置数组,可将该结构(内包含数组)当做第一等级的类型(赋值语句拷贝整个数组、作为函数的返回类型、传值调用)。
第二点如下代码所示:
struct s_tag
{
    int a[100];   // 结构内包含数组
};

// 可将该结构作为第一等级的类型
struct s_tag orange, lime, lemon ;

// 结构作为函数参数及函数返回值
struct s_tag twofold( struct s_tag s)
{
    int j;
    for( j = 0; j < 100; j++)
    {
        s.a [j] *= 2;
    }

    return s;
}

int main ()
{
    int i;
    for( i = 0; i < 100; i++)
    {
        lime.a [i] = 1;
    }

    lemon = twofold(lime );
    orange = lemon;      // 给整个结构赋值
}
结构中包含一个指向结构本身的指针,这种方法常用于列表(list)、树(tree)等。
 
关于联合(union)
 
结构中每个成员依次存储,而在联合中,所有成员都成偏移量为0处开始存储,在某一时刻,只有一个成员真正存储于该地址。联合因此也叫“变体记录”。
联合的一般形式:
union 可选的标签
{
    类型  标识符;
    类型  标识符;
    ...
    类型N   标识符N ;
}可选的变量定义;
联合一般作为大型结构的一部分存在。用以节省存储空间,因为某些数据项不可能同时出现
联合也可以把同一个数据解释成两种不同的东西,而不是把两个不同的数据解释为同一种东西。
作者最后列举数据(15W行与机器无关的OS源代码),说明结构出现的次数大约是联合的一百倍。
 
关于枚举(enum)
 
枚举通过一种简单的途径,把一串名字与一串整型值联系在一起。
对于C来说,很少有什么事只能考枚举来完成而无法用#define解决的。
枚举的一版形式:
enum 可选标签
{
    内容...
}可选变量定义;
缺省情况下,整型值从0开始。如果对列表中的某个标识符进行了赋值,那么后面的标识符依次大1。
枚举与#define的一个不同:#define定义的名字一般在编译时被丢弃,而枚举名字通常在调试器中一直可见。
 
  • 3.3 优先级规则
要理解一个声明,必须要懂得其中的优先级规则。
理解C语言声明的优先级规则:
A    声明从它的名字开始读取,然后按照优先级依次读取。
B    优先级顺序:
    B.  1    声明中被括号括起来的部分
    B.  2    后缀操作符:   
               ()  表示这是一个函数
               []  表示这是一个数组
    B.  3    前缀操作符: * 表示“指向...的指针”。
C     如果const、volatile关键字的后面紧跟类型说明符(int long float),那么它作用于类型说明符。在其他情况下,其作用于它紧邻的指针星号。
 
  • 3.5 关于typedef
在某些方面,typedef类似于宏文本替换——它没有引入新类型,而是为现有类型取个新名字。
一般情况下,typedef用于简洁地表示指向其他东西的指针。
不要在一个typedef中放入几个声明器;不要把typedef嵌入到声明的中间部分。
在同一个代码块中,typedef引入的名字不能与其他标识符同名。
 
  • 3.6  typedef和define的区别
typedef和宏文本替换之间存在的两个方面的区别:
1. 可以用其他类型说明符对宏类型名进行扩展,但对typedef定义的类型名就不能这样做;
#define   peach   int
typedef   int   orange;

unsigned peach i;    /* 合法,相当于 unsigned int i */
unsigned orange j;   /* 不合法*/
2. 在连续几个变量的声明语句中,用typedef定义的类型能够保证声明中所有的变量均为同一种类型,而#define定义的类型则无法保证。
#define d_string char*
d_string str1 , str2;   /* str1 的类型为char *, str2 的类型为 char */

typedef char * t_string;
t_string str3 ,  str4;   /* str3 和str4 的类型均为 char* */

 

  • 3.7  C语言中的名字空间
C语言中的名字空间:
  1. 标签名(label name)
  2. 标签(tag)。——用于所有的结构、枚举、联合;
  3. 成员名:每个结构或联合都有自己的名字空间;
  4. 其他
在同一个名字空间里,任何名字都必须具有唯一性,但在不同的名字空间里可以存在相同的名字。
typedef struct fruit
{
    int weight ;
    int price_per_lb ;
} fruit;  /* 结构标签与结构类型具有了相同的名字 */

struct fruit mandarin;  /* 使用结构标签 fruit */
fruit orange ;      /* 使用结构类型 fruit */
如上这种情况,结构标签与typedef的结构别名具有了相同的名字,作者在此处建议:当你有两个不同的东西时,一个比较好的原则就是用不同的名字来称呼它们。这样做减少了混淆的危险(这始终是软件的一个重要准则)。比如此处可以在结构标签后加一个"_tag"后缀。
posted @ 2013-12-27 11:56 qdsclove 阅读(450) 评论(6) 推荐(0) 编辑
摘要: 2.1编程语言的缺陷可以分为三类:不该做的做了。——多做之过。该做的没做。——少做之过。该做但做的不合适。——误做之过。C++对C语言中存在的一些基本问题没有什么改进,而它对C语言最重要的扩展(类)却是建立在C脆弱的类型模型上。2.2 多做之过fall through特性给switch语句带来的的麻烦由于C语言的设计理念(相信程序员,依靠程序员对其行为作出安全性的保证),几乎从来不进行运行时错误检查——对进行解除引用操作的指针进行有效性检查除外,MS-DOS甚至这点都无法保证。一个遵循标准的C编译器至少允许一条switch语句有257个case标签(8bit字符+EOF)。switch语句另一 阅读全文
posted @ 2013-12-20 02:00 qdsclove 阅读(289) 评论(0) 推荐(0) 编辑
摘要: 2.1 字符编码本地化的问题就是处理不同字符集的问题。2.2 ANSI字符和Unicode字符与字符串数据类型Microsoft的C/C++编译器定义了一个内建的数据类型wchar_t,表示一个16位的Unicode(UTF-16)字符。在编译器内建对wchar_t的支持之前,ANSI C头文件(和)定义了一个wchar_t数据类型。在Windows头文件WinNT.h中Windows团队定义了自己的数据类型以及可用于处理字符和字符串指针的大量便利的数据类型。WinNT.h中定义的UNICODE、TEXT宏://// Neutral ANSI/UNICODE types and macros/ 阅读全文
posted @ 2013-12-17 15:10 qdsclove 阅读(419) 评论(0) 推荐(0) 编辑
摘要: 1.1编译器的效率包括两个方面:运行效率(代码的运行速度)和编译效率(产生可执行代码的速度),运行效率起决定性作用;Ken Thompson在PDP-11上重新用汇编语言实现了UNIX,DR创立了能够同时解决多种数据类型和效率的“New B”语言(C),采用编译模式而不是解释模式,并引入类型系统,每个变量在使用前必须先声明。1.2C语言增加类型系统的主要目的是帮助编译器设计者区分新型PDP-11所拥有的不同数据类型(单精度、双精度浮点数、字符等);由于设计哲学,C语言排斥强类型(隐式转换,数组可以越界,几乎没有任何运行期的类型检查,允许在不同类型的对象间赋值);C语言有着许多为了方便编译器设计 阅读全文
posted @ 2013-12-13 13:28 qdsclove 阅读(245) 评论(0) 推荐(0) 编辑
摘要: a部分练习的是图像相减法,图像的减法又称减影技术,是指对同一景物在不同时间拍摄的图像或同一景物在不同波段的图像进行相减。其主要作用如下:1、去除不需要的叠加性图案;2、运动检测;3、梯度图像。这是两张在不同时刻拍摄的图像,为了充分展示出效果,我将图像中的物体移动了一下: 图 一 图 二这两幅图像相减,并取绝对值之后的结果图像: 图 三可以看出,图像相减可以去除两张图像中相同的部分,... 阅读全文
posted @ 2013-11-21 16:39 qdsclove 阅读(3265) 评论(0) 推荐(0) 编辑
摘要: 这部分基本上练习的是如何用非对称的高斯核做高斯滤波。如果用户希望采用非对称的高斯核,则引入param4,最后两个参数分别代表水平核以及垂直核维数。因此,当param3 ≠param4≠0的时候,就采用了非对称的高斯核。param1 = param2 = 0, param3 = 1, param4 = 9的滤波结果:根据上篇博文介绍的那样,实际上在这种情况中滤波核的大小为7 * 55,即平行向的核尺寸为7,竖直向的核尺寸为55,因此,结果图像在竖直方向上更模糊一些。我们可以来看下平行向上的一维高斯变换核:0.0044330.0540060.2420360.3990500.2420360.0540 阅读全文
posted @ 2013-11-19 16:04 qdsclove 阅读(345) 评论(0) 推荐(0) 编辑
点击右上角即可分享
微信分享提示