在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下,很简单的,直接用
就好了,但是wp8下就是报错,找不到这个函数,打开mat.hpp查看 Mat的定义,发现确实没有这个函数
Mat类定义在win32下是在core.hpp中1700行前后定义的,而在wp8下,是在mat.hpp中650行前后定义的
再比如在win32下,可以用imdecode函数从内存中生成 Mat,但是wp8下就没有这个函数
Google了好久,突然在某个地方发现,wp8是没有highgui库的,因为highgui库依赖于平台函数,会与wp8下一些函数冲突
作为一个懒人,如果没有这个库,好些函数都要想办法重写,当然不信了,于是自己在下载的opencv解决方案中添加了
highgui库,源码用的是modules/highgui/src下的文件,编译成功,太顺利了,把highgui库加入wp8 动态链接库工程
编译,没有任何效果,该报错的还是报错(恩,我记得是这样的),好吧,前人的经验还是有效的
其实在wp8下,跟在win32下差别不是很大,主要就是highgui库了,比如 imread, imwrite, imdecode之类的函数
我主要用的是imdecode,从内存中解压camera生成的jpg, exif之类的图像,查了资料,使用libjpeg库,
具体的参数网上一查就是了
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格式)