EMCV Guide


EMCV使用说明

emcvOpenCV针对C6000系列DSP的移植版本,目前只完成了部分功能,如读取图片,轮廓检测。

网上emcv相关资料很少,不少资料也有错误,所以对于开发相当不利,在此记录相关使用方法备查,也希望能帮到后来人。

开发环境:ccs3.3 C6421 Little Endian Simulator TMS320C6400_0(注意emulatorsimulator区别,无dsp连接时用simulator可实现大部分功能,且无需下载,比较方便开发调试)

安装方法:

下载Emcv源文件:https://emcv.svn.sourceforge.net/

基于http://www.ti.com/ww/cn/uprogram/share/pdfs/BeagleBoard4.pdf

的方法编译lib并加载至项目。

文档中有以下几点需要说明或更正:

l  Emcv已经完成highgui库的移植,虽然部分函数对dsp无意义,但最为重要的loadsave也在这个文件夹下,所以也需要编译与加载highgui目录的内容。

l  加载lib库可以实现功能,但是如果希望断点、分步调试,仍需要将emcv源文件加入include,否则调试中F11进入函数时会提示缺少文件。

l  文档例程载入的是rgb格式的图片。这种格式非常不主流,如需编辑查看图片,可下载ps插件RGBFormat.8BI  也可自己编辑十六进制文件。格式大致如下:前64位文件头+红色通道信息+绿色通道信息+蓝色通道信息 通道信息每两位十六进制数代表一个像素的色深00~ff0~255 顺序按照行从下到上,每行从左到右的顺序,即左下是第一个点,右上是最后一点

l  使用view-graph-image查看图片需要注意通道选择,interleaved data source选择否,rgb通道分别根据rgb编码规则分别填入相应地址。Image origin选择bottom left

l  加载highgui后无需用load载入,可以用其中的cvLoadImage函数,可以载人bmp格式。使用cvSaveImage可以保存图像,便于调试,而无需使用view-graph-image查看

 

使用说明:

l  Emcv尚未开发完全,不少函数仍无法使用。如cvCvtColorcvCanny等。辨别能否使用,可以先在emcv源文件中查找相应函数名称,如果没有,一定不能使用。如果存在,仍需项目连接时确认其函数实现的代码存在,如果函数没有实现的代码,则会在连接时报错,如cvCanny

<Linking>

 undefined first referenced                      

  symbol       in file                           

 --------- ----------------                      

 _cvCanny  H:\\dm642\\test\\test3\\Debug\\main.obj

error: unresolved symbols remain

error: errors encountered during linking; "./Debug/test3.out" not built

l  目前测试,与图像检测有关的函数,测试可以使用的有:cvLoadImagecvCreateImagecvGetSizecvThresholdcvSaveImagecvCreateMemStoragecvFindContourscvInitTreeNodeIteratorcvCreateSeqcvNextTreeNodecvStartReadSeqcvSeqPushcvPolyLinecvRectangle

l  存在函数声明但经测试缺少函数实现的有:cvCvtColorcvCannycvBoundingRectcvminarearect2cvCirclecvApproxPoly

l  注意dsp工程需要cmd文件指定存储位置,常见的位置有SRAMexternal memory。注意每一存储区域的起始位置和长度限制。如SRAM开始于00000000h 最长00040000h 程序的不同部分(代码,变量,动态分配空间等)需要指定每一section的存储区域,写于cmd文件并需添加入工程。如果位置分配不当,如sysmen分到SRAM则会在运行cvCreateMemStorage()时报错:out of memory。每一位置介绍详见http://wenku.baidu.com/link?url=ov_0JtTkGTWMgSBYev5l2Dr_NWIq0DsUkq7I9rOgYt5fK3F2l4oN7FU8hBeHGYnRH8HdzwhoKy8c9PIWBQmwhqhqu3ZuB07qZn9Cb0M0-f_

 

 

错误与修改(如有不当请指正)

Emcv源文件中有部分错误需要注意

l  cvCreateMemStorage函数申请的空间后block_size为指定值,但free_space却始终是0,需要人为指定为申请值,否则之后的步骤将显示缺少空间。且free_space不能等于block_size否则seq会分配到全零地址,导致cvSetSeqBlockSize的错误。

l  cxdatastructs.cpp:468 怀疑CV_ELEM_SIZE存在错误,使得typesize != elem_size,方便起见,直接改为int typesize =8;

l  cvcontours.cpp635调用cvBoundingRect( contour, 1 );出错,原因可能是cvBoundingRect的函数未写完,由于这一功能并非必须,所以删除该行。

l  warningincompatible redefinition of macro "CV_8TO32F"incompatible redefinition of macro "CV_FAST_CAST_8U” 两个变量出现在不同emcv文件夹下,但删除重复后,文件下内的其他文件会出错,直接忽视即可。

 

程序效果:

Input:     blob.png

Output: blob.png

 

代码见附件

/*
Example of finding contours in a gray scale image and calculating its center point using EMCV
By Chen Li, Kang Feng
2014.8
*/
#include <stdio.h>
#include <stdlib.h>
#include "cv/_cv.h"
#include "cxcore/_cxcore.h"
#include "highgui/_highgui.h"
#include "highgui/highgui.h"

int main(int argc,char** argv)
{
	IplImage* img = cvLoadImage("100gray.bmp",CV_LOAD_IMAGE_GRAYSCALE);
//cannot link cvtcolor 
//cvCvtColor(img,img_grey,CV_RGB2GRAY);
//so ensure input image is grayscale
	IplImage* thres_img= cvCreateImage(cvGetSize(img),8,1);
	cvThreshold(img, thres_img, 128, 255, CV_THRESH_BINARY); 
	cvSaveImage( "out_thres_img.bmp", thres_img);
	CvMemStorage* storage1 = cvCreateMemStorage((int)sizeof(double)*1000);
	storage1->free_space=storage1->block_size-(int)sizeof(double);
//genrally use canny before finding contour, but can not link cvCanny
//cvCanny(img, img, 100, 100 * 2);
	CvSeq *contours = NULL;//store first contour in the pic
	//find all contours. count is all contour numbers
	int count = cvFindContours(thres_img,storage1,&contours,sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
//use cvApproxPoly to find rough outer contour, but cannot link 
//contours = cvApproxPoly( contours, sizeof(CvContour), storage1, CV_POLY_APPROX_DP, 3, 1 );   
	//start fetch and analyse each contour
	CvTreeNodeIterator iterator;   
	cvInitTreeNodeIterator(&iterator,contours,3);
	CvSeq* allpointsSeq = cvCreateSeq(CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvContour), sizeof(CvPoint), storage1);  
	while( 0 != (contours = (CvSeq*)cvNextTreeNode(&iterator)) ){  
		int totalx=0;
		int totaly=0;
		int onetourlength = contours->total;    //total points in a contour
		CvPoint *points = (CvPoint *)malloc(sizeof(CvPoint) * onetourlength);    
		CvSeqReader reader;
		CvPoint pt = cvPoint(0,0);   
		cvStartReadSeq(contours,&reader);
		for(int i = 0 ;i < onetourlength; i++){   
	 		CV_READ_SEQ_ELEM(pt,reader);    
			points[i] = pt;   
			cvSeqPush(allpointsSeq,&pt);
			totalx+=pt.x;
			totaly+=pt.y; 
		}         
		//draw polygon by points in the contour     
		cvPolyLine(thres_img,&points,&onetourlength,1,0,CV_RGB(255,255,255),1,8,0);  
//cannot link cvMinAreaRect2 to find the center point or rotate angle of the rectangle contour
//CvBox2D rect = cvMinAreaRect2(contours);
		//mean number of all x and y of contour points is the center point
		printf("center node:(%d,%d)\n",totalx/onetourlength,totaly/onetourlength);
		CvPoint centernode1,centernode2;
		centernode1.x=totalx/onetourlength-1;
		centernode1.y=totaly/onetourlength-1;
		centernode2.x=totalx/onetourlength+1;
		centernode2.y=totaly/onetourlength+1;
		//draw a 2*2 rectangle to mark the middle point
		cvRectangle(thres_img,centernode1,centernode2,CV_RGB(255,255,255),1,8,0);
	} 
    cvSaveImage( "out_final.bmp", thres_img);      
	return 0;
}

This article is among the series of FDUROP project. More information: http://104.131.150.53/thinkcmfx/index.php?g=&m=article&a=index&id=17



By:陈力

2014.9.1


Last Article Next article

Comment 评论



Share 分享

New Users 最新加入

  • hokurikustr

  • refrain

New comments 最新评论

test123: aasdas Details Apr 13 16:39
admin: Thanks! Details Apr 09 11:46
admin: Google map api Details Apr 09 11:46
lqj12: cooooooooool Details Apr 08 21:34
Yunhan Huang: 这个功能是如何实现的? Details Apr 08 13:23