您的位置:首页 > 运维架构

opencv1.0移植到arm中的问题

2013-06-12 08:53 309 查看
毕业设计是关于嵌入式图像采集和处理的。软件方面我的设计方案是用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

参考资料

/article/10665880.html
http://www.opencv.org.cn/forum/viewtopic.php?p=1844
关于YUV420的讲解

/article/7852173.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: