opencv1.0移植到arm中的问题

毕业设计是关于嵌入式图像采集和处理的。软件方面我的设计方案是用spcaview进行图像采集,调用opencv库进行图像处理。

spcaview的移植相对比较简单,都是按照常规的交叉编译的步骤。下面主要讲一下我在移植opencv1.0到arm中遇到的两个问题:

1.cvLoadImage()函数没办法使用

IplImage *pImg = cvLoadImage(argv[1], 0);

是opencv程序中常见的语句,如果调用成功,pImg将指向保存该图片的IplImage结构体,否则为NULL。原本在PC机上运行没有问题的程序,移植到arm平台上,每一次pImg却得到NULL。后来上网查看了一下,发现很多人都遇到了这个问题,其中,有人提出了一个靠谱的方案,就是手动给pImg赋值。对于我的毕设而言,这个方案具有可行性,原因是固定的摄像头型号,采集保存成的图像基本参数均一致,只有pImg->imageData域不同。

下面是具体的代码实现,由于图片事先保存成了jpeg格式,这也意味着需要对图像先进行解压缩,然后转为BGR(因为opencv中为BGR而不是RGB)才可以。

/************************************************
 *To use IplImage structure in OpenCV when OpenCV
 *has been transplant to arm. 
 *Time 	2013/05/28
 *Author  JunLi
 ***********************************************/
#include "jpeglib.h"
#include "highgui.h"
#include "convform.h"
#include <string.h>
#include <stdio.h>
/*************************************************
 *Note: this function based on following information.
 *nSize = 112
 *ID = 0
 *nChannels = 3
 *alphaChannel = 0
 *depth = 8
 *colorModel = "RGB"
 *channelSeq = "BGR"
 *dataOrder = 0
 *origin = 0
 *align = 4
 *width = 320
 *height = 240
 *roi = NULL
 *maskROI = NULL
 *imageId = NULL
 *tileInfo = NULL
 *imageSize = 230400
 *imageData = ?
 *widthStep = 960
 *BorderMode = {0, 0, 0, 0}
 *BorderConst = {0, 0, 0, 0}
 *imageDataOrigin = ?
 ********************************************/

//将jpeg格式转为bmp,即bgr
IplImage *jpeg2Ipl(/*char *jpegData,*/FILE *fp/*,  int jpegSize*/)
{
	IplImage *pImg = NULL;
	struct jpeg_error_mgr jerr;
	struct jpeg_decompress_struct cinfo;


	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_decompress(&cinfo);

	//jpeg_stdio_mem_src(&cinfo,jpegData,jpegSize);
	jpeg_stdio_src(&cinfo, fp);

	jpeg_read_header(&cinfo, TRUE);
	jpeg_start_decompress(&cinfo);

	int nRowSize = cinfo.output_width*cinfo.output_components;
	int w = cinfo.output_width;
	int h = cinfo.output_height;

	char *bmpBuffer = (char *)malloc(h*w*3);
	assert(bmpBuffer);

	JSAMPARRAY pBuffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, nRowSize, 1);

	while (cinfo.output_scanline < cinfo.output_height)
	{
		jpeg_read_scanlines(&cinfo, pBuffer, 1);
		int start = nRowSize*(cinfo.output_scanline-1);
		for (int i = 0; i < nRowSize; i++) {
			bmpBuffer[start+i] = pBuffer[0][i];
		}
	}

	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);
	
	pImg = cvCreateImage(cvSize(w, h), 8, 3);	
	for (h = 0; h < pImg->height; h++) {
		for (w = 0; w < pImg->widthStep; w+=3) {
			*(pImg->imageData+h*pImg->widthStep+w+0) = *(bmpBuffer+h*pImg->widthStep+w+2);

			*(pImg->imageData+h*pImg->widthStep+w+1) = *(bmpBuffer+h*pImg->widthStep+w+1);
			
			*(pImg->imageData+h*pImg->widthStep+w+2) = *(bmpBuffer+h*pImg->widthStep+w+0);

		}
	}
	free(bmpBuffer);
	bmpBuffer = NULL;
	return pImg;
}

//手动创建IplImage
IplImage* myCreateImage(char *filename)
{

	FILE *fp = fopen(filename, "r");
	if (!fp) {
		fprintf(stderr, "open image file failed\n");
		return NULL;
	}
	//将jpeg转化为IplImage 格式
	IplImage *pImg;

	pImg = jpeg2Ipl(fp);	
	assert(pImg);

	unsigned char *imageData;
	
	pImg->nSize = 112;
	pImg->ID = 0;
	//pImg->nChannels;
	pImg->alphaChannel = 0;
	//pImg->depth;
	
	//colorModel--> char[]
	strcpy(pImg->colorModel, "RGB");	
	//channelSeq--> char[]
	strcpy(pImg->channelSeq, "BGR");

	pImg->dataOrder = 0;
	pImg->origin = 0;
	pImg->align = 4;
	//pImg->width;
	//pImg->height;
	pImg->roi = NULL;
	pImg->maskROI = NULL;
	pImg->imageId = NULL;
	pImg->tileInfo = NULL;
	pImg->imageSize = 230400;

	//pImg->imageData = ;
	pImg->widthStep = 960;
	//BorderMode---> int[]
	pImg->BorderMode[0] = 0;
	pImg->BorderMode[1] = 0;
	pImg->BorderMode[2] = 0;
	pImg->BorderMode[3] = 0;
	//BorderConst---> int[]
	pImg->BorderConst[0] = 0;
	pImg->BorderConst[1] = 0;
	pImg->BorderConst[2] = 0;
	pImg->BorderConst[3] = 0;

	//pImg->imageDataOrigin = ;
	return pImg;
}
对与jpeg格式的图像解压缩,可使用libjpeg库,网上有很多关于如何使用libjpeg库的教程,可参阅。

总的来说,这种方法具有一定的条件限制,不具有通用性。


2.cvCanny()函数出错

本来打算对图像进行边缘提取,那自然想到使用canny方法。但程序中每次调用canny都失败,究其原因原来是cvRound()函数的问题。

http://www.opencv.org.cn/forum/viewtopic.php?p=1844

给出了很好解释和解决策略,我在这不重复了。


顺便提一下关于usb摄像头驱动,这个折腾了我两周时间。

1、不要认为什么型号的摄像头都可以,linux kernel对摄像头的支持还没有达到那么好。可以先在PC中的linux系统中试一下,看看是否支持。

2、一般摄像头插到usb口,minicom中会打印两类信息:1)usb口识别了这个usb设备,2)该设备的信息。 如果摄像头插到usb口后,只打印了usb相关信息,而没有关于摄像头的信息,那就说明很有可能是摄像头驱动问题。这里推荐是使用spcv5xx


参考资料

http://blog.csdn.net/dg1683wen/article/details/6861116

http://www.opencv.org.cn/forum/viewtopic.php?p=1844

关于YUV420的讲解



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值