在wp8中使用opencv

在wp8中使用opencv


opencv有专门针对win32,Linux,android的库,目前来说,暂时没有支持wp8的计划
但是民间有高手啊,有一个大神构建了wp8可以使用的opencv工程,可以到下面的网址下载:


https://github.com/MSOpenTech/opencv


在公司,网速就是个渣渣,下了好多次才下成功,我是10月中旬下的,有99.3M,现在应该也
是这么大吧,应该没更新


编译就很简单了,下载完之后,解压,在binWP8目录下有个 opencv.sln,我这里直接用vs2013打开的,
上面那个链接下面的说明当中说vs2012也可以,没试过
打开工程,针对需要的平台,编译就好了


当我编译完,兴高采烈地加到wp8的Windows phone动态链接库工程当中后,编译,发现报了好多错误,
就比如将IplImage * 转为Mat类型,本来在win32下,很简单的,直接用

Mat::Mat(const IplImage* img, bool copyData=false);


就好了,但是wp8下就是报错,找不到这个函数,打开mat.hpp查看 Mat的定义,发现确实没有这个函数
Mat类定义在win32下是在core.hpp中1700行前后定义的,而在wp8下,是在mat.hpp中650行前后定义的




再比如在win32下,可以用imdecode函数从内存中生成 Mat,但是wp8下就没有这个函数


//data是内存中图像数据指针
Mat imgbuf = Mat(1200, 1200, CV_8U, data);
Mat decode_data = imdecode(imgbuf, 1);
imshow("img form buf", decode_data);
waitKey();

Google了好久,突然在某个地方发现,wp8是没有highgui库的,因为highgui库依赖于平台函数,会与wp8下一些函数冲突


作为一个懒人,如果没有这个库,好些函数都要想办法重写,当然不信了,于是自己在下载的opencv解决方案中添加了
highgui库,源码用的是modules/highgui/src下的文件,编译成功,太顺利了,把highgui库加入wp8 动态链接库工程
编译,没有任何效果,该报错的还是报错(恩,我记得是这样的),好吧,前人的经验还是有效的


其实在wp8下,跟在win32下差别不是很大,主要就是highgui库了,比如 imread, imwrite, imdecode之类的函数


我主要用的是imdecode,从内存中解压camera生成的jpg, exif之类的图像,查了资料,使用libjpeg库,

借鉴了网上的一些代码,可以从内存中解压jpg,exif,生成IplImage * ,后面会附上工程下载链接,代码如下:

//jpg.h
#include <iostream>
#include <stdio.h>
#include "cv.h"
#include "opencv2/opencv.hpp"
extern "C"{
#include "jpeglib.h"
};

using namespace std;

EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo,
	int desired));

#pragma pack(2)        //两字节对齐,否则bmp_fileheader会占16Byte
struct bmp_fileheader
{
	unsigned short    bfType;        //若不对齐,这个会占4Byte
	unsigned long    bfSize;
	unsigned short    bfReverved1;
	unsigned short    bfReverved2;
	unsigned long    bfOffBits;
};

struct bmp_infoheader
{
	unsigned long    biSize;
	unsigned long    biWidth;
	unsigned long    biHeight;
	unsigned short    biPlanes;
	unsigned short    biBitCount;
	unsigned long    biCompression;
	unsigned long    biSizeImage;
	unsigned long    biXPelsPerMeter;
	unsigned long    biYpelsPerMeter;
	unsigned long    biClrUsed;
	unsigned long    biClrImportant;
};

void write_bmp_header(j_decompress_ptr cinfo);
void write_bmp_data(j_decompress_ptr cinfo, unsigned char *src_buff);
void mem_init_source(j_decompress_ptr cinfo);
boolean mem_fill_input_buffer(j_decompress_ptr cinfo);
void mem_skip_input_data(j_decompress_ptr cinfo, long num_bytes);
boolean mem_resync_to_restart(j_decompress_ptr cinfo, int desired);
void mem_term_source(j_decompress_ptr cinfo);
void analyse_jpeg(unsigned char *data, int size, IplImage ** img);
//void analyse_jpeg(int num, int size, IplImage ** img);

//jpg.cpp
#include "pch.h"
#include "jpg.h"
#include "jpeglib.h"

//#pragma comment(lib,"libjpeg.lib")

FILE *input_file;
FILE *output_file;

void write_bmp_header(j_decompress_ptr cinfo)
{
	struct bmp_fileheader bfh;
	struct bmp_infoheader bih;

	unsigned long width;
	unsigned long height;
	unsigned short depth;
	unsigned long headersize;
	unsigned long filesize;

	width = cinfo->output_width;
	height = cinfo->output_height;
	depth = cinfo->output_components;

	if (depth == 1)
	{
		headersize = 14 + 40 + 256 * 4;
		filesize = headersize + width*height;
	}

	if (depth == 3)
	{
		headersize = 14 + 40;
		filesize = headersize + width*height*depth;
	}

	memset(&bfh, 0, sizeof(struct bmp_fileheader));
	memset(&bih, 0, sizeof(struct bmp_infoheader));

	//写入比较关键的几个bmp头参数
	bfh.bfType = 0x4D42;
	bfh.bfSize = filesize;
	bfh.bfOffBits = headersize;

	bih.biSize = 40;
	bih.biWidth = width;
	bih.biHeight = height;
	bih.biPlanes = 1;
	bih.biBitCount = (unsigned short)depth * 8;
	bih.biSizeImage = width*height*depth;

	fwrite(&bfh, sizeof(struct bmp_fileheader), 1, output_file);
	fwrite(&bih, sizeof(struct bmp_infoheader), 1, output_file);

	if (depth == 1)        //灰度图像要添加调色板
	{
		unsigned char *platte;
		platte = new unsigned char[256 * 4];
		unsigned char j = 0;
		for (int i = 0; i<1024; i += 4)
		{
			platte[i] = j;
			platte[i + 1] = j;
			platte[i + 2] = j;
			platte[i + 3] = 0;
			j++;
		}
		fwrite(platte, sizeof(unsigned char)* 1024, 1, output_file);
		delete[] platte;
	}
}

void write_bmp_data(j_decompress_ptr cinfo, unsigned char *src_buff)
{
	unsigned char *dst_width_buff;
	unsigned char *point;

	unsigned long width;
	unsigned long height;
	unsigned short depth;

	width = cinfo->output_width;
	height = cinfo->output_height;
	depth = cinfo->output_components;

	dst_width_buff = new unsigned char[width*depth];
	memset(dst_width_buff, 0, sizeof(unsigned char)*width*depth);

	point = src_buff + width*depth*(height - 1);    //倒着写数据,bmp格式是倒的,jpg是正的
	for (unsigned long i = 0; i<height; i++)
	{
		for (unsigned long j = 0; j<width*depth; j += depth)
		{
			if (depth == 1)        //处理灰度图
			{
				dst_width_buff[j] = point[j];
			}

			if (depth == 3)        //处理彩色图
			{
				dst_width_buff[j + 2] = point[j + 0];
				dst_width_buff[j + 1] = point[j + 1];
				dst_width_buff[j + 0] = point[j + 2];
			}
		}
		point -= width*depth;
		fwrite(dst_width_buff, sizeof(unsigned char)*width*depth, 1, output_file);    //一次写一行
	}
}

void mem_init_source(j_decompress_ptr cinfo)
{
	//  cinfo->src->bytes_in_buffer = g_buf_len; 
	//     cinfo->src->next_input_byte = (unsigned char*)g_buf;
}
boolean mem_fill_input_buffer(j_decompress_ptr cinfo)
{
	return true;
}
void mem_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
{
	cinfo->src->bytes_in_buffer -= num_bytes;
	cinfo->src->next_input_byte += num_bytes;
}

boolean mem_resync_to_restart(j_decompress_ptr cinfo, int desired)
{
	return jpeg_resync_to_restart(cinfo, desired);
}
void mem_term_source(j_decompress_ptr cinfo)
{
}
/*
void Test()
{
	int ret = TESTADD(2, 3);
}
*/
void analyse_jpeg(unsigned char *data, int size, IplImage ** img)
{
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr jerr;
	jpeg_source_mgr jmgr;

	//unsigned char tmpdata[256 * 1024] = {0};
	//tmpdata[0] = data[0];
	//tmpdata[1] = data[1];
	unsigned char *tmp = data + 2;
	int length = 0;
	while (*tmp == 0xFF && *(tmp + 1) >= 0xE0 && *(tmp + 1) <= 0xEF)
	{
		tmp += 2;
		length = (*tmp << 8) + *(tmp + 1);
		tmp += (length + 2);
		size -= (length + 4);
	}
	tmp -= 3;
	//int i = 0;
	*tmp-- = 0xD8;
	*tmp = 0xFF;
	//for (i = 0; i < size; i++)
	{
		//tmpdata[i + 2] = *tmp++;
	}
	//if (tmpdata[0] == 0x00)
	{
		//tmpdata[0] = 0xFF;
	}
	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_decompress(&cinfo);

	jmgr.init_source = mem_init_source;
	jmgr.fill_input_buffer = mem_fill_input_buffer;
	jmgr.skip_input_data = mem_skip_input_data;
	jmgr.resync_to_restart = mem_resync_to_restart;
	jmgr.term_source = mem_term_source;
	jmgr.next_input_byte = tmp;
	jmgr.bytes_in_buffer = size + 2;

	cinfo.src = &jmgr;
	int retcode = 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 = new char[h*w * 3];
	IplImage *_pImg = cvCreateImage(cvSize(w, h), 8, 3);
	JSAMPARRAY pBuffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, 1, nRowSize, 1);
	while (cinfo.output_scanline < cinfo.output_height) {
		jpeg_read_scanlines(&cinfo, pBuffer, 1);

		int start = (cinfo.output_scanline - 1);
		for (int i = 0; i < nRowSize; i++)
			//	bmpBuffer[start + i] = pBuffer[0][i];
			*(_pImg->imageData + start*_pImg->widthStep + i + 0) = pBuffer[0][i];// *(bmpBuffer + 3 * start * _pImg->width + i);
	}

	
	//*img = cvCreateImage(cvSize(w, h), 8, 3);
	//printf("wid:%d, widstep:%d\n", _pImg->width, _pImg->widthStep);
	/*
	for (h = 0; h<_pImg->height; h++) {
		for (w = 0; w < (_pImg->width * 3); w++)
			*(_pImg->imageData + h*_pImg->widthStep + w + 0) = *(bmpBuffer + 3 * h * _pImg->width + w);
	}*/
	cvCvtColor(_pImg, _pImg, CV_RGB2BGR);
	*img = cvCloneImage(_pImg);
	cvReleaseImage(&_pImg);

	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);
	//delete[] bmpBuffer;
}
/*
void analyse_jpeg(int num, int size, IplImage ** img)
{
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr jerr;
	jpeg_source_mgr jmgr;

	char filename[10] = { 0 };
	filename[0] = num + '0';
	strcpy(&filename[1], ".jpg");
	FILE * fd = fopen(filename, "rb");
	char *data;
	data = (char *)malloc(size);
	fseek(fd, 0, SEEK_SET);
	fread(data, size, 1, fd);
	fclose(fd);
	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_decompress(&cinfo);

	jmgr.init_source = mem_init_source;
	jmgr.fill_input_buffer = mem_fill_input_buffer;
	jmgr.skip_input_data = mem_skip_input_data;
	jmgr.resync_to_restart = mem_resync_to_restart;
	jmgr.term_source = mem_term_source;
	jmgr.next_input_byte = (unsigned char*)data;
	jmgr.bytes_in_buffer = size;

	cinfo.src = &jmgr;
	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 = new char[h*w * 3];
	JSAMPARRAY pBuffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, 1, 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];
	}

	IplImage *_pImg = cvCreateImage(cvSize(w, h), 8, 3);
	//printf("wid:%d, widstep:%d\n", _pImg->width, _pImg->widthStep);
	for (h = 0; h<_pImg->height; h++) {
		for (w = 0; w < (_pImg->width * 3); w++)
			*(_pImg->imageData + h*_pImg->widthStep + w + 0) = *(bmpBuffer + 3 * h * _pImg->width + w);
	}
	cvCvtColor(_pImg, _pImg, CV_RGB2BGR);
	*img = cvCloneImage(_pImg);
	cvReleaseImage(&_pImg);

	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);
	delete[] bmpBuffer;
}
*/
/*
int main()
{
const char *input_file="a.jpg";
output_file=fopen("lena.bmp","wb");
char buffer[128*1024] = {0};

FILE * file = fopen(input_file, "rb");
int len = fread(buffer, sizeof(char), 128 * 1024, file);
fclose(file);
IplImage *img = NULL;
analyse_jpeg(buffer, len, &img);
cvShowImage("pimg", img);
cvWaitKey();
fclose(output_file);
cout<<"end"<<endl;

return 0;
}
*/


最后面注销掉的main是测试用的函数


注意,在wp8中使用动态库时候,动态库所依赖的库必须是dll,不能使lib,wp8工程打包的时候
不会将lib库打包进去的,而后面附注的工程用的lib库


wp8下使用的libjpeg与一般的没什么区别,只是要编译为目标平台,然后注释掉几个重定义就好了,
编译工程后面也会附上


这样下来,wp8就可以使用opencv了,对于上面提到的IplImage *转 Mat的问题,Google了下,用下
面的函数代替原来的转换方法:

//IplImage * img
Mat tmp = cvarrToMat(img, 0, 1, 0);

具体的参数网上一查就是了


最后附上上面提到的工程

从内存生成iplimage(jpg格式,exif格式)

libjpeg

猜你喜欢

转载自blog.csdn.net/ybn187/article/details/40888445