posts - 119, comments - 71, trackbacks - 5, articles - 0
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

公告

2011年12月11日

Emgu.CV,OpenCV for C#

 
Emgu.CV是OpenCV的.net framework封装,可以用于C#,现在已经出到2.0/2.1版本了。它分两层:

The basic layer (layer 1) containsfunction,structureandenumerationmappings which directly reflect those inOpenCV. The second layer (layer 2) contains classes that mix inadvantangesfrom the .NET world.

目前的OpenCV增加了一些新的vision功能,例如SURF特征(SURF与SIFT的对比见:12),HOG算子等,都是近几年conference上提出的新东西。

 


另外,新的OpenCV(EmguCV) 在机器学习部分的算法也比以前增加了,神经网络,boost,EM,SVM……常用的一些计算工具都具备了。

C#作为一个编程工具,必须承认,上手比VC要快得多,我们的学生,尤其是女生,碰到要做界面的程序,都很自觉地用它。既然有了Emgu.CV,下学期的vision课用它也无妨了。


posted @ 2011-12-11 21:43 张冰 阅读(53) 评论(0) 编辑

首先介绍一下EmguCV 。

EmguCV a是.NET 平台下对OpenCV 图像处理库的封装。也就是OpenCV的.NET 版。它运行在.NET 兼容的编程语言下调用OpenCV 的函数,如C#、VB、VC++、IronPython 等。这个封装库可以在Mono 下编译和在Linux / Mac OS X 上运行。

 

接着简要介绍一下EmguCV的安装步骤:

1、首先保证你的电脑已经装好了openCV,并且保证环境变量已经设置好。具体参照OpenCV官方中文网站,写得很清楚。

2、下载EmguCV压缩包,其实就是几个可以在Visual Studio2005/2008中引用OpenCV的函数的dll库。我下的是1.50版,“Emgu.CV.Windows.Binary-1.5.0.0.zip”。解压该压缩包,并把其DLL拷贝在OpenCV安装目录下的Bin文件夹里。

3、新建一个c#窗体应用程序,添加Bin目录下“Emgu.CV.dll”,“Emgu.Util.dll”等DLL的引用,还有些窗体的控件,主要是將 Emgu.CV.UI.dll 加入工具箱中,加入後會出現 ImageBox、HistogramCtrl。

4、然后,再程序的开头中加上 using Emgu.CV; using Emgu.Util;等命名空间之后就可以用EmguCV中所有的库函数了。

 

然后说说几个使用EmguCV的基础问题及要注意的地方:

1、在.net中使用OpenCv和EmguCv时,必须在三者支持的图像格式之间进行转换。.net中用Bitmap类来承载图像,OpenCv中用IplImage指针来承载图像,EmguCv中用Image<TColor,TDepth>来承载图像。

读入图像的方法有几种,在OpenCV中,可以使用:

IntPtr srcImage;//IntPtr代替IplImage*
srcImage = CvInvoke.cvLoadImage("lena.jpg",Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U,1);

在EmguCV中,建议使用Image类来实现读入操作,写法如下

//读入一张BGR图像,要将lena.jpg放入DEBUG目录下。

Image<Bgr, byte> img = new Image<Bgr, byte>("lena.jpg");

//ToBitmap()将IImage格式转换为Bitmap格式,便能为PictureBox所用了。

pictureBox1.Image = img.ToBitmap();或者pictureBox1.Image=img.Bitmap;

Image格式还可以转换成IntPtr,如:

srcImage = img.Ptr;

Image类实在功能强大,还有封装了很多常用的图像处理的函数。

2、图片的数据处理

可以使用c++中OpenCV的指针访问的办法,但是在c#.net的环境下,是不安全代码,要加上unsafe关键字

unsafe
{
   ((byte*)img.MIplImage.imageData + img.MIplImage.widthStep * i)[j] = 0;

}

建议使用EmguCV的写法

//对Image<Bgr,byte>的第y行第x列进行读取和写入操作。

Bgr color=img[y,x];

img[y,x]=color;

Bgr格式的数据可以通过Bgr.Blue,Bgr.Green,Bgr.Red访问,Gray格式的数据可以通过Gray.intensity访问,所有数据都是可以读写的。

3、判断一个视频是否读到文件尾,不能用null,要用一个为空类型的IntPtr,就是IntPtr eof = new IntPtr(),看其是否与eof相等。
4、IplImage*,CvCapture*等指针在C#中都用IntPtr来代替,且其中没有cvGetMCvSize函数,故用cvGetImageROI来暂时代替
5、由于C#中没有取地址符号&,所以在这里所有的取地址都用引用来代替,即ref。
6、OpenCV中的所有的预定义的常量,都封装在Emgu.CV.CvEnum这个枚举类型里面。

 

 

 


参考:

1、http://www.cnblogs.com/xrwang/archive/2010/01/26/TheInteractionOfOpenCv-EmguCvANDDotNet.html

2、http://hi.baidu.com/pengjun/blog/item/4ce4cb80213c3ddf9123d9c3.html

3、http://www.dotblogs.com.tw/chou/archive/2009/06/13/8812.aspx

4、http://hi.baidu.com/barty/blog/item/0bc7353eac40393671cf6c42.html

 

posted @ 2011-12-11 21:42 张冰 阅读(39) 评论(0) 编辑

利用IJG JPEG Library压缩图像为jpg格式

作者:赵新国

下载源代码

关键字: jpeg,图像压缩

摘要:文章介绍了采用libjpeg压缩图像的方法

前一段时间做了一个项目,项目中有一部分是关于图像采集的,相关硬件有:高速数字相机(我们采用Basler A312f),工控机,服务器。其中相机通过1394视频线连接到工控机的1394视频卡上,工控机与服务器通过百兆网连接。具体工作流程为:工控机控制相机采集图像,帧率一般为40HZ左右,采集的图像为位图数据,需要自己在程序中封装为bmp格式,然后压缩成jpg格式,压缩后的图像一方面保存到本地硬盘,同时要传输到服务器上。

  本文只介绍jpeg压缩的相关内容,刚开始我贪图省事,采用微软 的GDI Plus提供的功能,很是方便,先获取jpg图像的编码,然后根据图像的位图数据创建一个Bitmap类的对象,再保存图像为jpg格式就行了。但是我对GDI+还是很信任,总感觉不踏实(没有理由的),我们的系统一旦安装就要长期运行,我就是担心长期运行一段时间后GDI+会出问题,结果也证实了我的担心,我们实际使用的10套系统中有一套,连续运行3-5天后,GDI+就会崩溃,于是我决心采用IJG JPEG Library。您可以到www.ijg.org网站下载libjpeg的源码, IJG JPEG Library就是jpeg压缩库,是以源码的形式提供给软件开发人员的,当然在软件包里也有编译好的库文件,我们这里就只用到其中的libjpeg.lib,jconfig.h,jmorecfg.h,jpeglib.h这几个文件,下面我就介绍一下怎样在自己的程序里嵌入图像压缩功能。

一、建立编译环境

  所谓建立编译环境,其实非常简单,就是把上面提到的4个文件拷贝到你的项目文件夹下,把libjpeg.lib添加到你的项目中,然后在你完成压缩功能的那个文件里加入#include "jpeglib.h",需要注意的是,libjpeg.lib是用c语言开发的,如果要用在你的C++程序里,需要用到extern "C",如下:

// TestLibjpeg.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "memory.h"
extern "C" {
 #include "jpeglib.h"
}

二、压缩步骤

1、申请并初始化jpeg压缩对象,同时要指定错误处理器

  struct jpeg_compress_struct jcs;

	// 声明错误处理器,并赋值给jcs.err域
 	struct jpeg_error_mgr jem;
 	jcs.err = jpeg_std_error(&jem);

 	jpeg_create_compress(&jcs);
2、指定压缩后的图像所存放的目标文件,注意,目标文件应以二进制模式打开
  f=fopen("03.jpg","wb");
 	if (f==NULL) 
 	{
  		delete [] data;
  		delete [] pDataConv;
  		return 0;
 	}
 	jpeg_stdio_dest(&jcs, f);
3、设置压缩参数,主要参数有图像宽、高、色彩通道数(1:索引图像,3:其他),色彩空间(JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像),压缩质量等,如下:
  jcs.image_width = nWidth;    // 为图的宽和高,单位为像素 
 	jcs.image_height = nHeight;
 	jcs.input_components = 1;   // 在此为1,表示灰度图, 如果是彩色位图,则为3 
 	jcs.in_color_space = JCS_GRAYSCALE; //JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色图像 

 	jpeg_set_defaults(&jcs); 
	jpeg_set_quality (&jcs, 80, true);

需要注意的是,jpeg_set_defaults函数一定要等设置好图像宽、高、色彩通道数计色彩空间四个参数后才能调用,因为这个函数要用到这四个值,调用jpeg_set_defaults函数后,jpeglib库采用默认的设置对图像进行压缩,如果需要改变设置,如压缩质量,调用这个函数后,可以调用其它设置函数,如jpeg_set_quality函数。其实图像压缩时有好多参数可以设置,但大部分我们都用不着设置,只需调用jpeg_set_defaults函数值为默认值即可。

  4、上面的工作准备完成后,就可以压缩了,压缩过程非常简单,首先调用jpeg_start_compress,然后可以对每一行进行压缩,也可以对若干行进行压缩,甚至可以对整个的图像进行一次压缩,压缩完成后,记得要调用jpeg_finish_compress函数,如下:

	jpeg_start_compress(&jcs, TRUE);

 	JSAMPROW row_pointer[1];   // 一行位图
 	int row_stride;      // 每一行的字节数 

	 row_stride = jcs.image_width;  // 如果不是索引图,此处需要乘以3

 	// 对每一行进行压缩
 	while (jcs.next_scanline < jcs.image_height) {
     		row_pointer[0] = & pDataConv[jcs.next_scanline * row_stride];
     		jpeg_write_scanlines(&jcs, row_pointer, 1);
 	}

 	jpeg_finish_compress(&jcs);
5、最后就是释放压缩工作过程中所申请的资源了,主要就是jpeg压缩对象,由于在本例中我是直接用的局部变量,所以只需调用jpeg_destroy_compress这个函数即可,如下:
jpeg_destroy_compress(&jcs);
三、解压缩步骤

  解压缩步骤与压缩步骤非常相似,只是解压缩对象为jpeg_decompress_struct类型,步骤如下:
  1、声明并初始化解压缩对象,同时制定错误信息管理器
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr jerr;

	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_decompress(&cinfo);
  2、打开jpg图像文件,并指定为解压缩对象的源文件
	FILE *f = fopen(strSourceFileName,"rb");
	if (f==NULL)
	{
		printf("Open file error!\n");
		return;
	}
	// 
	jpeg_stdio_src(&cinfo, f);
  3、读取图像信息
   jpeg_read_header(&cinfo, TRUE);
  4、根据图像信息申请一个图像缓冲区
   data = new BYTE cinfo.image_width*cinfo.image_height*cinfo.num_components];
  5、开始解压缩
	jpeg_start_decompress(&cinfo);

	JSAMPROW row_pointer[1];
	while (cinfo.output_scanline < cinfo.output_height)
	{
		row_pointer[0] = &data[(cinfo.output_height - cinfo.output_scanline-1)*cinfo.image_width*cinfo.num_components];
		jpeg_read_scanlines(&cinfo,row_pointer ,
					1);
	}
	jpeg_finish_decompress(&cinfo);
  6、释放资源
  jpeg_destroy_decompress(&cinfo);

	fclose(f);
  好了,利用IJG JPEG Library进行图像压缩就介绍到这里,希望对大家有所帮助,实例代码已经实现了图像的压缩和解压缩的全部功能,命令格式为:“TestLibjpeg.exe j|j24|b 源文件名 目标文件名”,其中,j选项将源文件压缩为jpg格式,不改变色彩模式,j24选项将源文件压缩为24为jpg格式,b选项将源文件解压缩为bmp格式,该实例并没有提供文件有效性的验证,如果要引入自己的代码,请自己实现文件有效性的验证。

 

posted @ 2011-12-11 21:32 张冰 阅读(27) 评论(0) 编辑