机器视觉与图像处理
多功能和易用运动控制框架
支持图像模板深度学习

第二部分 基础对象操作

在介绍图像处理和机器视觉算法之前,有必要对一些基础对象进行说明。这些基础对象为最基本的数据结构,在后续的模块里面可能会被使用到。是一些功能模块的基础。

2.1动态数据操作对象

动态数据操作对象有序列,聚合,列表。序列(Sequence)是由一系列的相同数据类型的数据组成,数据元素之间有先后次序的关系。聚合(Cluster)也是由很多相同数据类型的数据组成,与序列不同的是,聚合之间不保证数据之间的先后顺序。列表(List)仅支持数据指针,他是线程安全的一种对象,主要用于多线程的情况。由于只支持数据指针操作,因此,主要用于c/c++的编程语言环境中。

动态数据操作对象的数据有多种数据类型。但是不管什么数据类型,只能都只能通过变量引用的方式进行添加或修改。如:

int n=20;

rsqAddLast(sequence, &n);

动态数据操作对象遵循创建/销毁模式。为了加快数据操作速度,序列和聚合对象有专门的宏进行数据读写操作。

2.1.1序列

序列比较常用的动态数据结构。序列可用用在很多场所。如作为先进后出栈,先进先出队。在使用序列之前,通常需要创建:

RvSequence seq = rvCreateSequence(RDT_INT);

创建序列的时候,需要指定元素的数据类型。

当序列创建成功以后,可以将新的数据添加到序列头部或序列尾部。如:

int n=12;

rsqAppend(seq, &n);

也可以插入中间某个位置。如

rsqInsert(seq, 10,&n);

同样,在删除的时候,可以从头部删除或者尾部删除,也可以将某个具体的元素删除如:

HITEM item = rsqSeekToBegin(seq);

rsqRemoveItem(seq, item);

上面的语句将头部的元素对象获取到,然后,进行删除。有时候,可能用户需要将序列中元素值等于某个具体的值删除(可能同时删除若干个元素),如:

n=1;

rsqRemoveElem(seq, &n);

这些语句将元素值等于1的所有元素删除。当然,也可以无条件地将序列中所有的元素全部清除,如:

rsqClear(seq);

索引操作

可以对序列中的元素按照位置进行索引读取或写入。如下面的语句首先将生成一个包含15个元素的序列,然后,按照顺序将每个元素的值设置成新值:

Int total =15;

for (int i=0; i< total; i++){

rsqAppend(seq, &i);

}

for (int i=0; i< total; i++){

n = i+100;

rsqSetItemValue(seq,i , &n);}

(TIPS:在使用索引的方式进行元素读写的时候,一定要确保序列里面存在已经元素节点。)

如果要对元素进行索引方式读取,可以按照下面的方式进行:

for (int i=0; i< rsqGetCount(seq); i++){

rsqGetItemValue(seq, i, &n);

sprintf("%d, ", n);

}

快速操作

使用快速操作方式,可以明显提高应用程序的效率。快速操作主要用在某个函数全部为读或全部为写的情况,主要按照顺序方式进行。如:

RvSeqWriter sw;

RV_BEGIN_WRITE_SEQ(seq, &sw);

for (int i=0; i< total; i++){

n = i+100;

RV_WRITE_TO_SEQ_EX(&sw, &n, TRUE);

}

RV_END_WRITE_SEQ(seq, &sw);

上面的语句,按照顺序写入若干个元素。

如果要顺序读取某一个序列的所有元素,可以按照下面的方式进行。

RvSeqReader sr;

RV_BEGIN_READ_SEQ(seq, &sr);

while(!RV_IS_SEQ_END(&sr)){

RV_READ_FR_SEQ(&sr, &n);

sprintf("%d, ", n);}

RV_END_READ_SEQ(seq, &sr);

序列作为队数据结构,也可以使用快速方式进行入对或出队工作:

RvSeqWriter sw;

RV_BEGIN_QUEUE(seq, &sw);

for (int i=0; i< total; i++){

n = i+100;

RV_PUSH_TO_QUEUE(&sw,&n);}

RV_END_QUEUE(seq, &sw);

出队的典型方式如下:

while(!RV_IS_QUEUE_EMPTY(&sw)){

RV_POP_FROM_QUEUE(&sw,&n);

sprintf("%d, ", n);}

(TIPS:快速操作仅适合c/c++编程语言)

2.1.2聚合

聚合是同类型数据的集合,在对聚合的操作过程中,不保证数据元素之间的先后顺序。创建聚合与创建序列一样,需要指定元素类型。如:

RvCluster clust = rvCreateCluster(RDT_INT);

元素添加通常在数据集合的末尾。如:

Int n=12;

rclAppend(clust, &n);

删除可以通过元素值的方法进行,同时可以删除多个元素(具有相同的值)。

rclRemove(clust, &n);

很多情况下,可能需要将两个聚合的元素合并成到一个集合里面,如:

rclMerge(clust, clust1, TRUE);

这个函数将clust1里面的所有元素合并到clust, 同时将clust1里面的元素清空。

索引操作

与序列操作一样,聚合也支持索引操作。在进行索引操作之前,也一定要保证聚合里面有元素存在。下面的语句对聚合对象按照索引的方式进行数据读写:

for (int i=0; i< total; i++){

rclAppend(clust, &i);

}

for (int i=0; i< rclGetCount(clust); i++){

n = rclGetCount(clust)-1 -i;

rclSetAt(clust, i, &n);

}

for (int i=0; i< rclGetCount(clust); i++){

n = *((int*)rclGetAt(clust, i));

sprintf ("%d, ", n);

}

(TIPS:当聚合操作在进行不断的添加和删除操作以后,用索引的方式进行读写的时候,数据与前面的同一位置的数据可能不一样。)

快速操作

对于聚合来说,里面的数据量一般很大,应用快速读写操作,可以显著提高应用程序的处理性能。下面的语句对聚合写入若干个元素:

RvClusterWriter cw;

int n,i;

RV_BEGIN_WRITE_CLUST(clust, &cw);

for (i =0; i<64; i++){

n=i ;

RV_WRITE_TO_CLUST(&cw, &n);

}

RV_END_WRITE_CLUST(clust, &cw);

如果要快速读出数据,可以按照下面方式进行:

RvClusterReader cr;

RV_BEGIN_READ_CLUSTER(clust, &cr);

while(TRUE){

if ( RV_IS_CLUST_END(&cr)) break;

RV_READ_FR_CLUSTER(&cr, &n);

sprintf ("%d, ", n);

}

RV_END_READ_CLUST(clust, &cr);

当然,也可以使用索引的方式对聚合对象的数据读出。

(TIPS:快速操作仅适合c/c++编程语言)

2.1.3列表

列表的数据结构与序列类似,但列表仅支持一种数据类型,即数据指针,这限制了列表在除c/c++以外的其他语言里面的使用。但是列表是线程安全的,它可以在多线程里面进行插入和删除,(不能针对同一元素)。在使用列表之前,首先创建:

RvList list = rvCreateList();

新的数据可以添加到列表的首尾位置,下面的函数将若干个元素添加到列表首部,即最后插入的数据在列表头部:

int total = 15;

int* pN;

for (int i=0; i< total; i++){

pN = new int;

ASSERT(pN);

*pN = i;

rlsAddHead(list, pN);

}

使用完成以后,一般用户需要自己将元素的数据内存释放。如:

for (int i=0; i< rlsGetCount(list); i++){

pN = (int*)rlsGetAt(list, i);

sprintf ("%d, ",*pN);

delete pN;

}

rlsRemoveAll(list);

这些语句将列表的元素空间释放,同时,清除列表中所有的元素。

列表没有相应的快速读写宏。在需要对元素进行遍历的时候建议按照下面的方式进行,以取得较好的处理性能。

if (rlsGoHead(list)){

while(TRUE){

pN =(int*) rlsGetCur(list);

sprintf ("%d, ",*pN);

if (rlsStep(list) ==FALSE) break;

} }

2.2读数银行对象

读数银行对象是保存图像分析的结果的对象,读数对象可以由若干不同类型的数值组成,这些对象已索引值的形式进行访问。银行读数对象用于需要返回多个值的函数,这些值的数据类型可能一样也可能不一样。通常情况下,读数银行在使用之前需要创建,如:

RvReadingBank bank = rvCreateReadingBank();

使用完成以后,进行销毁。

rvDestroyReadingBank(bank);

下面的语句将整数12赋值给索引值为9(索引从0开始)的元素,

rrdSetInteger(bank, 12, 9);

如果索引值小于0,则自动添加一个新的元素到读数银行对象最尾部。

(TIPS: 一般复合型数据类型如RvRgb, RvSize等的元素采用引用传递的方式进行修改或写入,读取的时候全部使用引用的方式进行。一般情况下,如果没有输入读数银行对象,函数会自动生成一个并返回,由函数自动生成的这些读数对象也需要进行显示销毁)。

2.3感兴趣区域(ROI)模板

感兴趣区域模板(RvMask)是一个矩阵,里面的元素表示对应的感兴趣区域图像的象素。矩阵的元素只有两个值,如果为1表示,该象素参与运算,如果为0,表示忽略。 模板遵循创建和销毁模式,如:

RvMask mask = rvCreateMask(RV_MT_RECT, 128, 100);

这个语句创建一个宽度为128,高度为100的矩形形状的模板。有时候,经过处理后的二元图像也可能被用做模板,这样可以直接使用二元图像的图像数据作为模板矩阵数据。如:

RvImage image = rvLoadImage(“mybin.bmp”);

rviCast(image, RIT_BIN);

RvMask mask = rvCreateMaskEx(rviGetWidth(image), rviGetHeight(image), rviGetData(image), rviGetSize(image), rviGetPitch(image));

上面的方式创建的mask将不会分配额外的矩阵数据。

(TIPS: 不管用何种方式创建模板,记得使用rvDestroyMask销毁哦。)



抖音视频号: 第一感机器视觉
微信公众号: 精浦科技
深圳市软云动力科技有限公司
东莞办事处: 广东省东莞市松湖智谷B6栋225b
公司地址: 广东省深圳市南山区桃园路金桃园大厦2191

二维码1 二维码2 二维码3


深圳市软云动力科技有限公司 版权所有  鄂ICP备2022015826号-2   

统计显示 ▼