转载请标明是引用于 http://blog.csdn.net/chenyujing1234

欢迎大家提出意见,一起讨论!

一、OpenCV介绍:

OpenCV是由Intel性能基元(IPP)团队主持,而且几个主要开发者都与IPP团队保持良好的关系,所以OpenCV利用了IPP高度手工优化的代码来实现加速。

使用IPP获得提速是很显著的。

OpenCV使用了优化了的C和C++代码实现,它对IPP不存在任何依赖。但如果安装了IPP,那么OpenCV将会通过自动载入IPP动态链接库获取IPP的优势。

获得IPP并安装: http://www.itel.com/software/products/ipp/index.htm  ; 请使用5.1或更新版本,请确认二进制文件路径(eg:c/program files/intel/ipp/5.1/ia32/bin)

被添加到系统环境变量的PATH中。现在OpenCV会自动探测到IPP,并在运行时装载IPP了。

1 、 OpenCV的结构和内容

OpenCV主体分为五个模块:

OpenCV的CV模块包含基本的图像处理函数和高级的计算机视觉算法。

ML是机器学习库,包含一些基于统计的分析和聚类工具。

HighGUI包含图像和视频输入/输出的函数。

CXCore包含OpenCV的一些基本数据结构和相关函数。

CvAux模块,该模块一般存放一些即将被淘汰的算法和函数(如嵌入式隐马尔可夫模型的人脸识别算法),同时还有一些新出现的实验性的算法(如背景和前景的分割)

二、OpenCV库的获得及编译
1、 OpenCV可以直接下载安装文件安装得到lib与dll文件及源码
OpenCV安装的下载(下载最新版本的OpenCV2.1.0)http://sourceforge.net/projects/opencv/

如果是1.1版本的那么安装文件是:

下载安装程序后,运行安装程序。安装程序将安装openCV并注册DirectShow filter,然后进行一些安装后的处理。

现在可以进入.../opencv/_make,使用MSVC++akg MSVC.NET 2005打开opencv.sln,然后生成Debug版本的库或Release版的库。

2、当然也可去下载它的源码来通过CMake自己编译.

转自: http://hi.baidu.com/zgzhaobo/blog/item/5e0df6263d4499058b82a114.html

OpenCV2.1.0编译详细讲解

准备工作

  1. OpenCV源文件的下载(下载最新版本的OpenCV2.1.0)http://sourceforge.net/projects/opencv/
  2. CMake的安装(2.8.1)http://www.cmake.org/cmake/resources/software.html
  3. CodeBlock安装http://sourceforge.net/projects/codeblocks/

  4. 3rdparty库文件的更新

    由于videoInput库文件是基于gcc 4.4.*之前版本编译,所以在Mingw4.4.*编译OpenCV时出现sjlj相应错误。
    所以在我们编译OpenCV前务必要更新videoInput的库文件
    文件下载:http://code.google.com/p/pyopencv/downloads/list
    下载videoInput.a,覆盖OpenCV的解压路径/3rdparty/lib/libvideoInput.a

处理OpenCV源文件

  1. Cmake交叉编译
    按照下面的设置进行配置,上面一行是解压后的OpenCV的路径
    下面一行是你需要编译后存放动态链接库的文件目录,可供自由选择

    注意:这里两个路径都不能有空格或者中文,不然编译会出现错误

     
    点击下面configure进行配置(第一次点击的时候会挑选编译环境的工具,我们选择codeblock:mingw),会出现上面红色区域内容,勾选你需要的组建,然后再次点击configure,进行配置相关文件。
    接下来Generate按钮呈现可用状态,点击Generate进行生成相应的编译环境的工程文件。
    到此,我们可以关闭cmake工具,交由codeblock进行处理了。
    打开codeblock工具,打开工程文件,选择刚才cmake输出的文件夹下的对应工程文件。界面如下:

    工程上面点击右键,进行build,等待漫长的编译过程完成。
    此时OpenCV编译完成!

=============================================================================================

当然大家也可以把CMake的编译环境配置成VS的。这样CMake后会产生编译VC工程文件:

三、入门程序的实现

在VC开发环境中,我们要配置它的各项设置,以使OpenCV开发包中的highgui.lib  cxcore.lib  ml.lib  cv.lib库能被正确外国投资,并保证编译器的预处理器能搜索到

opencv/*/include 目录下的各个头文件。

它们一般位于:

D:\Program Files\OpenCV\cv\include

D:\Program Files\OpenCV\cxcore\include

D:\Program Files\OpenCV\ml\include

D:\Program Files\OpenCV\otherlibs\highgui

1、 第一个例子-------显示图像

从磁盘中加载并在屏幕上显示一幅图像的简单OpenCV程序

  1. #include "highgui.h"
  2. int main( int argc, char** argv )
  3. {
  4. // 是一个高层调用接口,它通过文件名确定被加载文件的格式;
  5. // 且该函数自动分配图像数据结构所需的内存。
  6. // cvLoadImage可以读取大多数格式的图像文件,BMP、DIB、JPEG、JPE、PNG、BBM、PPM
  7. // SR、RAS、TIFF
  8. // 函数执行完后返回一个指针,此指针指向一块为描述该图像文件的数据结构而分配的内存块。
  9. IplImage* img = cvLoadImage( argv[1] );
  10. //  cvNamedWindow由HighGUI库提供,用于在屏幕上创建一个窗口,将被显示的图像包含于该窗口中。
  11. // 函数第一个参数指定了窗口的的窗口标题。
  12. // 如果要使用HighGUI库所提供的其他函数与该窗口进行交互,我们将通过该参数值引用这个窗口中。
  13. cvNamedWindow("Example1", CV_WINDOW_AUTOSIZE );
  14. // 显示该图像
  15. cvShowImage("Example1", img );
  16. // 使程序暂停,等待用户触发一个按键操作,但如果该函数参数设为一个正数,则程序将暂停一段时间,
  17. // 时间长为该整数值个毫秒单位
  18. // 如果设置为0,那么将一直等待用户触发按键操作。
  19. cvWaitKey(0);
  20. // 内存释放功能
  21. cvReleaseImage( &img );
  22. // 关闭窗口
  23. cvDestroyWindow("Example1");
  24. }
#include "highgui.h"

int main( int argc, char** argv )
{
// 是一个高层调用接口,它通过文件名确定被加载文件的格式;
// 且该函数自动分配图像数据结构所需的内存。
// cvLoadImage可以读取大多数格式的图像文件,BMP、DIB、JPEG、JPE、PNG、BBM、PPM
// SR、RAS、TIFF
// 函数执行完后返回一个指针,此指针指向一块为描述该图像文件的数据结构而分配的内存块。
IplImage* img = cvLoadImage( argv[1] );
// cvNamedWindow由HighGUI库提供,用于在屏幕上创建一个窗口,将被显示的图像包含于该窗口中。
// 函数第一个参数指定了窗口的的窗口标题。
// 如果要使用HighGUI库所提供的其他函数与该窗口进行交互,我们将通过该参数值引用这个窗口中。
cvNamedWindow("Example1", CV_WINDOW_AUTOSIZE );
// 显示该图像
cvShowImage("Example1", img );
// 使程序暂停,等待用户触发一个按键操作,但如果该函数参数设为一个正数,则程序将暂停一段时间,
// 时间长为该整数值个毫秒单位
// 如果设置为0,那么将一直等待用户触发按键操作。
cvWaitKey(0);
// 内存释放功能
cvReleaseImage( &img );
// 关闭窗口
cvDestroyWindow("Example1");
}
2、 第二个例子------播放AVI视频
  1. #include "highgui.h"
  2. int main( int argc, char** argv ) {
  3. cvNamedWindow( "Example2", CV_WINDOW_AUTOSIZE );
  4. // cvCaptureFromAVI()通过参数设置要读入的AVI文件,返回一个指向cvCapture结构的指针
  5. // 这个指针包括了所有关于读入AVI文件的信息,其中包括状态信息。
  6. // 在调用这个函数后,返回指针指向的CvCapture结构被初始化到所对应的AVI文件的开头。
  7. //CvCapture* capture = cvCaptureFromAVI( argv[1] ); // either one will work
  8. CvCapture* capture = cvCreateFileCapture( argv[1] );
  9. IplImage* frame;
  10. while(1) {
  11. // 用来将下一帧视频文件载入内存(实际上是填充或更新CvCapture结构中),返回一个
  12. // 对应当前帧的指针
  13. // 与cvLoadImage不同的是,cvLoadImage为图像分配内存空间,而cvQueryFram使用已经在
  14. // cvCapture结构中分配好的内存,这样的话没必要通过cvReleaseImage()对返回值释放。
  15. frame = cvQueryFrame( capture );
  16. if( !frame ) break;
  17. cvShowImage( "Example2", frame );
  18. char c = cvWaitKey(33);
  19. if( c == 27 ) break;
  20. }
  21. cvReleaseCapture( &capture );
  22. cvDestroyWindow( "Example2" );
  23. }
#include "highgui.h"

int main( int argc, char** argv ) {
cvNamedWindow( "Example2", CV_WINDOW_AUTOSIZE );
// cvCaptureFromAVI()通过参数设置要读入的AVI文件,返回一个指向cvCapture结构的指针
// 这个指针包括了所有关于读入AVI文件的信息,其中包括状态信息。
// 在调用这个函数后,返回指针指向的CvCapture结构被初始化到所对应的AVI文件的开头。
//CvCapture* capture = cvCaptureFromAVI( argv[1] ); // either one will work
CvCapture* capture = cvCreateFileCapture( argv[1] );
IplImage* frame;
while(1) {
// 用来将下一帧视频文件载入内存(实际上是填充或更新CvCapture结构中),返回一个
// 对应当前帧的指针
// 与cvLoadImage不同的是,cvLoadImage为图像分配内存空间,而cvQueryFram使用已经在
// cvCapture结构中分配好的内存,这样的话没必要通过cvReleaseImage()对返回值释放。
frame = cvQueryFrame( capture );
if( !frame ) break;
cvShowImage( "Example2", frame );
char c = cvWaitKey(33);
if( c == 27 ) break;
}
cvReleaseCapture( &capture );
cvDestroyWindow( "Example2" );
}
2、1 视频播放控制

上例中我们无法在视频播放时进行快速拖动,我们接下来通过加入一个滚动条来实现这个功能。

HighGUI不仅提供了简单的显示函数,还包括一些图像和视频控制方法,其中之一个经常用到的是滚动条,它可以使我们方便地从视频一帧跳到另外一帧。

我们通过调用cvCreateTrackbar()来创建一个滚动条,并通过设置参数确定滚动条所属于的窗口。

  1. /* License:
  2. Oct. 3, 2008
  3. Right to use this code in any way you want without warrenty, support or any guarentee of it working.
  4. BOOK: It would be nice if you cited it:
  5. Learning OpenCV: Computer Vision with the OpenCV Library
  6. by Gary Bradski and Adrian Kaehler
  7. Published by O'Reilly Media, October 3, 2008
  8. AVAILABLE AT:
  9. http://www.amazon.com/Learning-OpenCV-Computer-Vision-Library/dp/0596516134
  10. Or: http://oreilly.com/catalog/9780596516130/
  11. ISBN-10: 0596516134 or: ISBN-13: 978-0596516130
  12. OTHER OPENCV SITES:
  13. * The source code is on sourceforge at:
  14. http://sourceforge.net/projects/opencvlibrary/
  15. * The OpenCV wiki page (As of Oct 1, 2008 this is down for changing over servers, but should come back):
  16. http://opencvlibrary.sourceforge.net/
  17. * An active user group is at:
  18. http://tech.groups.yahoo.com/group/OpenCV/
  19. * The minutes of weekly OpenCV development meetings are at:
  20. http://pr.willowgarage.com/wiki/OpenCV
  21. */
  22. #include "highgui.h"
  23. /*
  24. int main( int argc, char** argv )
  25. {
  26. // 是一个高层调用接口,它通过文件名确定被加载文件的格式;
  27. // 且该函数自动分配图像数据结构所需的内存。
  28. // cvLoadImage可以读取大多数格式的图像文件,BMP、DIB、JPEG、JPE、PNG、BBM、PPM
  29. // SR、RAS、TIFF
  30. // 函数执行完后返回一个指针,此指针指向一块为描述该图像文件的数据结构而分配的内存块。
  31. IplImage* img = cvLoadImage( argv[1] );
  32. //  cvNamedWindow由HighGUI库提供,用于在屏幕上创建一个窗口,将被显示的图像包含于该窗口中。
  33. // 函数第一个参数指定了窗口的的窗口标题。
  34. // 如果要使用HighGUI库所提供的其他函数与该窗口进行交互,我们将通过该参数值引用这个窗口中。
  35. cvNamedWindow("Example1", CV_WINDOW_AUTOSIZE );
  36. // 显示该图像
  37. cvShowImage("Example1", img );
  38. // 使程序暂停,等待用户触发一个按键操作,但如果该函数参数设为一个正数,则程序将暂停一段时间,
  39. // 时间长为该整数值个毫秒单位
  40. // 如果设置为0,那么将一直等待用户触发按键操作。
  41. cvWaitKey(0);
  42. // 内存释放功能
  43. cvReleaseImage( &img );
  44. // 关闭窗口
  45. cvDestroyWindow("Example1");
  46. }
  47. */
  48. /* License:
  49. Oct. 3, 2008
  50. Right to use this code in any way you want without warrenty, support or any guarentee of it working.
  51. BOOK: It would be nice if you cited it:
  52. Learning OpenCV: Computer Vision with the OpenCV Library
  53. by Gary Bradski and Adrian Kaehler
  54. Published by O'Reilly Media, October 3, 2008
  55. AVAILABLE AT:
  56. http://www.amazon.com/Learning-OpenCV-Computer-Vision-Library/dp/0596516134
  57. Or: http://oreilly.com/catalog/9780596516130/
  58. ISBN-10: 0596516134 or: ISBN-13: 978-0596516130
  59. OTHER OPENCV SITES:
  60. * The source code is on sourceforge at:
  61. http://sourceforge.net/projects/opencvlibrary/
  62. * The OpenCV wiki page (As of Oct 1, 2008 this is down for changing over servers, but should come back):
  63. http://opencvlibrary.sourceforge.net/
  64. * An active user group is at:
  65. http://tech.groups.yahoo.com/group/OpenCV/
  66. * The minutes of weekly OpenCV development meetings are at:
  67. http://pr.willowgarage.com/wiki/OpenCV
  68. */
  69. #include <stdio.h>
  70. #include <iostream>
  71. #include <fstream>
  72. #include "cv.h"
  73. #include "highgui.h"
  74. /*
  75. OK, you caught us.  Video playback under linux is still just bad.  Part of this is due to FFMPEG, part of this
  76. is due to lack of standards in video files.  But the position slider here will often not work. We tried to at least
  77. find number of frames using the "getAVIFrames" hack below.  Terrible.  But, this file shows something of how to
  78. put a slider up and play with it.  Sorry.
  79. */
  80. using namespace std;
  81. int        g_slider_position = 0;
  82. CvCapture* g_capture         = NULL;
  83. // 定义全局回调函数,它在滚动条被拖动时调用
  84. // 滚动条位置会被作为参数传入。
  85. void onTrackbarSlide(int pos) {
  86. // 允许我们设置CvCapture对象的各种属性
  87. // CV_CAP_PROP_POS_FRAMES表我们以帧数来设置读入位置。
  88. // 如果我们想通过视频长度比例来设置读入位置,我们可以通过用AVI_RATIO代替FRAMES。
  89. cvSetCaptureProperty(
  90. g_capture,
  91. CV_CAP_PROP_POS_FRAMES,
  92. pos
  93. );
  94. }
  95. //Hack because sometimes the number of frames in a video is not accessible.
  96. //Probably delete this on Widows
  97. int getAVIFrames(char * fname) {
  98. char tempSize[4];
  99. // Trying to open the video file
  100. ifstream  videoFile( fname , ios::in | ios::binary );
  101. // Checking the availablity of the file
  102. if ( !videoFile ) {
  103. cout << "Couldn’t open the input file " << fname << endl;
  104. exit( 1 );
  105. }
  106. // get the number of frames
  107. videoFile.seekg( 0x30 , ios::beg );
  108. videoFile.read( tempSize , 4 );
  109. int frames = (unsigned char ) tempSize[0] + 0x100*(unsigned char ) tempSize[1] + 0x10000*(unsigned char ) tempSize[2] +    0x1000000*(unsigned char ) tempSize[3];
  110. videoFile.close(  );
  111. return frames;
  112. }
  113. int main( int argc, char** argv ) {
  114. cvNamedWindow( "Example2_3", CV_WINDOW_AUTOSIZE );
  115. g_capture = cvCreateFileCapture("E:\\OpenCV\\openCV1.1Test\\tree.avi" /*argv[1]*/ );
  116. IplImage *foo = cvQueryFrame( g_capture);
  117. // 获得视频文件的总帧数以对滚动条进行设置。
  118. int frames = (int) cvGetCaptureProperty(
  119. g_capture,
  120. CV_CAP_PROP_FRAME_COUNT
  121. );
  122. // 获得宽
  123. int tmpw = (int) cvGetCaptureProperty(
  124. g_capture,
  125. CV_CAP_PROP_FRAME_WIDTH
  126. );
  127. // 获得高
  128. int tmph = (int) cvGetCaptureProperty(
  129. g_capture,
  130. CV_CAP_PROP_FRAME_HEIGHT
  131. );
  132. printf("opencv frames %d w %d h %d\n",frames,tmpw,tmph);
  133. // 分析视频文件来获得总共有几帧
  134. frames = getAVIFrames("E:\\OpenCV\\openCV1.1Test\\tree.avi"/*argv[1]*/); //This is a hack because on linux, getting number of frames often doesn't work
  135. printf("hacked frames %d w %d h %d\n",frames,tmpw,tmph);
  136. // 创建滚动条
  137. // 可以设置滚动条名称并确定滚动条的所属窗口。
  138. // 将一个变量绑定到这个滚动条来表示滚动条的最大值和一个回调函数
  139. cvCreateTrackbar(
  140. "Position",
  141. "Example2_3",
  142. &g_slider_position,
  143. frames,
  144. onTrackbarSlide
  145. );
  146. IplImage* frame;
  147. frames = 0;
  148. while(1) {
  149. frame = cvQueryFrame( g_capture );
  150. if( !frame ) break;
  151. //      int frames = cvGetCaptureProperty( g_capture, CV_CAP_PROP_POS_FRAMES);//This should work, sometimes it does not on linux
  152. frames++; //My cheat
  153. printf("\nFrame number=%d\n",frames);
  154. cvSetTrackbarPos("Position","Example2_3",frames);
  155. cvShowImage( "Example2_3", frame );
  156. char c = (char)cvWaitKey(10);
  157. if( c == 27 ) break;
  158. }
  159. cvReleaseCapture( &g_capture );
  160. cvDestroyWindow( "Example2_3" );
  161. return(0);
  162. }
/* License:
Oct. 3, 2008
Right to use this code in any way you want without warrenty, support or any guarentee of it working. BOOK: It would be nice if you cited it:
Learning OpenCV: Computer Vision with the OpenCV Library
by Gary Bradski and Adrian Kaehler
Published by O'Reilly Media, October 3, 2008 AVAILABLE AT:
http://www.amazon.com/Learning-OpenCV-Computer-Vision-Library/dp/0596516134
Or: http://oreilly.com/catalog/9780596516130/
ISBN-10: 0596516134 or: ISBN-13: 978-0596516130 OTHER OPENCV SITES:
* The source code is on sourceforge at:
http://sourceforge.net/projects/opencvlibrary/
* The OpenCV wiki page (As of Oct 1, 2008 this is down for changing over servers, but should come back):
http://opencvlibrary.sourceforge.net/
* An active user group is at:
http://tech.groups.yahoo.com/group/OpenCV/
* The minutes of weekly OpenCV development meetings are at:
http://pr.willowgarage.com/wiki/OpenCV
*/
#include "highgui.h" /*
int main( int argc, char** argv )
{
// 是一个高层调用接口,它通过文件名确定被加载文件的格式;
// 且该函数自动分配图像数据结构所需的内存。
// cvLoadImage可以读取大多数格式的图像文件,BMP、DIB、JPEG、JPE、PNG、BBM、PPM
// SR、RAS、TIFF
// 函数执行完后返回一个指针,此指针指向一块为描述该图像文件的数据结构而分配的内存块。
IplImage* img = cvLoadImage( argv[1] );
// cvNamedWindow由HighGUI库提供,用于在屏幕上创建一个窗口,将被显示的图像包含于该窗口中。
// 函数第一个参数指定了窗口的的窗口标题。
// 如果要使用HighGUI库所提供的其他函数与该窗口进行交互,我们将通过该参数值引用这个窗口中。
cvNamedWindow("Example1", CV_WINDOW_AUTOSIZE );
// 显示该图像
cvShowImage("Example1", img );
// 使程序暂停,等待用户触发一个按键操作,但如果该函数参数设为一个正数,则程序将暂停一段时间,
// 时间长为该整数值个毫秒单位
// 如果设置为0,那么将一直等待用户触发按键操作。
cvWaitKey(0);
// 内存释放功能
cvReleaseImage( &img );
// 关闭窗口
cvDestroyWindow("Example1");
} */ /* License:
Oct. 3, 2008
Right to use this code in any way you want without warrenty, support or any guarentee of it working. BOOK: It would be nice if you cited it:
Learning OpenCV: Computer Vision with the OpenCV Library
by Gary Bradski and Adrian Kaehler
Published by O'Reilly Media, October 3, 2008 AVAILABLE AT:
http://www.amazon.com/Learning-OpenCV-Computer-Vision-Library/dp/0596516134
Or: http://oreilly.com/catalog/9780596516130/
ISBN-10: 0596516134 or: ISBN-13: 978-0596516130 OTHER OPENCV SITES:
* The source code is on sourceforge at:
http://sourceforge.net/projects/opencvlibrary/
* The OpenCV wiki page (As of Oct 1, 2008 this is down for changing over servers, but should come back):
http://opencvlibrary.sourceforge.net/
* An active user group is at:
http://tech.groups.yahoo.com/group/OpenCV/
* The minutes of weekly OpenCV development meetings are at:
http://pr.willowgarage.com/wiki/OpenCV
*/
#include <stdio.h>
#include <iostream>
#include <fstream>
#include "cv.h"
#include "highgui.h"
/*
OK, you caught us. Video playback under linux is still just bad. Part of this is due to FFMPEG, part of this
is due to lack of standards in video files. But the position slider here will often not work. We tried to at least
find number of frames using the "getAVIFrames" hack below. Terrible. But, this file shows something of how to
put a slider up and play with it. Sorry.
*/ using namespace std; int g_slider_position = 0;
CvCapture* g_capture = NULL; // 定义全局回调函数,它在滚动条被拖动时调用
// 滚动条位置会被作为参数传入。
void onTrackbarSlide(int pos) {
// 允许我们设置CvCapture对象的各种属性
// CV_CAP_PROP_POS_FRAMES表我们以帧数来设置读入位置。
// 如果我们想通过视频长度比例来设置读入位置,我们可以通过用AVI_RATIO代替FRAMES。
cvSetCaptureProperty(
g_capture,
CV_CAP_PROP_POS_FRAMES,
pos
);
} //Hack because sometimes the number of frames in a video is not accessible.
//Probably delete this on Widows
int getAVIFrames(char * fname) {
char tempSize[4];
// Trying to open the video file
ifstream videoFile( fname , ios::in | ios::binary );
// Checking the availablity of the file
if ( !videoFile ) {
cout << "Couldn’t open the input file " << fname << endl;
exit( 1 );
}
// get the number of frames
videoFile.seekg( 0x30 , ios::beg );
videoFile.read( tempSize , 4 );
int frames = (unsigned char ) tempSize[0] + 0x100*(unsigned char ) tempSize[1] + 0x10000*(unsigned char ) tempSize[2] + 0x1000000*(unsigned char ) tempSize[3];
videoFile.close( );
return frames;
} int main( int argc, char** argv ) {
cvNamedWindow( "Example2_3", CV_WINDOW_AUTOSIZE );
g_capture = cvCreateFileCapture("E:\\OpenCV\\openCV1.1Test\\tree.avi" /*argv[1]*/ );
IplImage *foo = cvQueryFrame( g_capture); // 获得视频文件的总帧数以对滚动条进行设置。
int frames = (int) cvGetCaptureProperty(
g_capture,
CV_CAP_PROP_FRAME_COUNT
); // 获得宽
int tmpw = (int) cvGetCaptureProperty(
g_capture,
CV_CAP_PROP_FRAME_WIDTH
); // 获得高
int tmph = (int) cvGetCaptureProperty(
g_capture,
CV_CAP_PROP_FRAME_HEIGHT
); printf("opencv frames %d w %d h %d\n",frames,tmpw,tmph); // 分析视频文件来获得总共有几帧
frames = getAVIFrames("E:\\OpenCV\\openCV1.1Test\\tree.avi"/*argv[1]*/); //This is a hack because on linux, getting number of frames often doesn't work printf("hacked frames %d w %d h %d\n",frames,tmpw,tmph); // 创建滚动条
// 可以设置滚动条名称并确定滚动条的所属窗口。
// 将一个变量绑定到这个滚动条来表示滚动条的最大值和一个回调函数
cvCreateTrackbar(
"Position",
"Example2_3",
&g_slider_position,
frames,
onTrackbarSlide
);
IplImage* frame;
frames = 0;
while(1) {
frame = cvQueryFrame( g_capture );
if( !frame ) break;
// int frames = cvGetCaptureProperty( g_capture, CV_CAP_PROP_POS_FRAMES);//This should work, sometimes it does not on linux
frames++; //My cheat
printf("\nFrame number=%d\n",frames);
cvSetTrackbarPos("Position","Example2_3",frames);
cvShowImage( "Example2_3", frame );
char c = (char)cvWaitKey(10);
if( c == 27 ) break;
}
cvReleaseCapture( &g_capture );
cvDestroyWindow( "Example2_3" );
return(0);
}
2、2  对图像进行简单的变换

现在我们要对视频的播放中的每一帧进行图像平滑处理,通过对图像数据与高斯或者其他核函数进行卷积有效地减少图像信息内容。

OpenCV使得这个卷积操作非常容易。

我们先创建一个窗口“Example4-out" 用来显示处理后的图像。然后在我们调用cvShowImage()来显示新捕捉的图像以后,我们可以计算

和在输出窗口中显示平滑处理后的图像。

效果如下:

  1. #include "cv.h"
  2. #include "highgui.h"
  3. void example2_4( IplImage* image )
  4. {
  5. // Create some windows to show the input
  6. // and output images in.
  7. //
  8. cvNamedWindow( "Example2_4-in", CV_WINDOW_AUTOSIZE );
  9. cvNamedWindow( "Example2_4-out", CV_WINDOW_AUTOSIZE );
  10. // Create a window to show our input image
  11. //
  12. cvShowImage( "Example2_4-in", image );
  13. // 分配自己的图像结构空间用来存储平滑处理后的图像
  14. // 第一个参数说明了当前图像结构的大小
  15. // 第二个参数告诉了我们各通道每个像素点的数据类型
  16. // 最后一个参数说明了通道的总数。
  17. IplImage* out = cvCreateImage(
  18. cvGetSize(image),
  19. IPL_DEPTH_8U,
  20. 3
  21. );
  22. // 我们通过使用每个像素周围3*3区域进行高斯平滑处理
  23. cvSmooth( image, out, CV_GAUSSIAN, 5,5 );
  24. // 输入与输出可以是相同的,这将会使我们的程序更加有效。
  25. cvSmooth( out, out, CV_GAUSSIAN, 5, 5);
  26. // Show the smoothed image in the output window
  27. //
  28. cvShowImage( "Example2_4-out", out );
  29. // Be tidy
  30. //
  31. cvReleaseImage( &out );
  32. // Wait for the user to hit a key, then clean up the windows
  33. //
  34. cvWaitKey( 0 );
  35. cvDestroyWindow("Example2_4-in" );
  36. cvDestroyWindow("Example2_4-out" );
  37. }
  38. int main( int argc, char** argv )
  39. {
  40. IplImage* img = cvLoadImage("adrian.jpg");
  41. cvNamedWindow("Example1", CV_WINDOW_AUTOSIZE );
  42. cvShowImage("Example1", img );
  43. example2_4( img );
  44. //  cvWaitKey(0);
  45. cvReleaseImage( &img );
  46. cvDestroyWindow("Example1");
  47. }
#include "cv.h"
#include "highgui.h" void example2_4( IplImage* image )
{
// Create some windows to show the input
// and output images in.
//
cvNamedWindow( "Example2_4-in", CV_WINDOW_AUTOSIZE );
cvNamedWindow( "Example2_4-out", CV_WINDOW_AUTOSIZE ); // Create a window to show our input image
//
cvShowImage( "Example2_4-in", image ); // 分配自己的图像结构空间用来存储平滑处理后的图像
// 第一个参数说明了当前图像结构的大小
// 第二个参数告诉了我们各通道每个像素点的数据类型
// 最后一个参数说明了通道的总数。
IplImage* out = cvCreateImage(
cvGetSize(image),
IPL_DEPTH_8U,
3
); // 我们通过使用每个像素周围3*3区域进行高斯平滑处理
cvSmooth( image, out, CV_GAUSSIAN, 5,5 );
// 输入与输出可以是相同的,这将会使我们的程序更加有效。
cvSmooth( out, out, CV_GAUSSIAN, 5, 5); // Show the smoothed image in the output window
//
cvShowImage( "Example2_4-out", out ); // Be tidy
//
cvReleaseImage( &out ); // Wait for the user to hit a key, then clean up the windows
//
cvWaitKey( 0 );
cvDestroyWindow("Example2_4-in" );
cvDestroyWindow("Example2_4-out" ); } int main( int argc, char** argv )
{
IplImage* img = cvLoadImage("adrian.jpg");
cvNamedWindow("Example1", CV_WINDOW_AUTOSIZE );
cvShowImage("Example1", img );
example2_4( img );
// cvWaitKey(0);
cvReleaseImage( &img );
cvDestroyWindow("Example1");
}
2、3  对图像进行复杂一点的变换

这里我们将用输出来覆盖输入变量。在OpenCV中我们通过函数cvPyrDown()来完成上述功能。

从旧的图像中读取所需的信息;在OpenCV中,所有的重要数据结构都是以结构体的形式实现的,并以结构体指针的形式传递。
  openCV中没有私有数据!

  1. #include "cv.h"
  2. #include "highgui.h"
  3. IplImage* doPyrDown(
  4. IplImage* in,
  5. int       filter = IPL_GAUSSIAN_5x5)
  6. {
  7. // 确保输入的宽高能被2整除.
  8. //
  9. //assert( in->width%2 == 0 && in->height%2 == 0 );
  10. // 从旧的图像中读取所需的信息
  11. // 在OpenCV中,所有的重要数据结构都是以结构体的形式实现的,并以结构体指针的形式传递。
  12. // openCV中没有私有数据!
  13. IplImage* out = cvCreateImage(
  14. cvSize( in->width/2, in->height/2 ),
  15. in->depth,
  16. in->nChannels
  17. );
  18. cvPyrDown( in, out );
  19. return( out );
  20. };
  21. int main( int argc, char** argv )
  22. {
  23. IplImage* img = cvLoadImage("adrian.jpg" );
  24. IplImage* img2 = cvCreateImage( cvSize( img->width/2,img->height/2 ), img->depth, img->nChannels);
  25. cvNamedWindow("Example1", CV_WINDOW_AUTOSIZE );
  26. cvNamedWindow("Example2", CV_WINDOW_AUTOSIZE );
  27. cvShowImage("Example1", img );
  28. img2 = doPyrDown( img );
  29. cvShowImage("Example2", img2 );
  30. cvWaitKey(0);
  31. cvReleaseImage( &img );
  32. cvReleaseImage( &img2 );
  33. cvDestroyWindow("Example1");
  34. cvDestroyWindow("Example2");
  35. }
#include "cv.h"
#include "highgui.h" IplImage* doPyrDown(
IplImage* in,
int filter = IPL_GAUSSIAN_5x5)
{ // 确保输入的宽高能被2整除.
//
//assert( in->width%2 == 0 && in->height%2 == 0 ); // 从旧的图像中读取所需的信息
// 在OpenCV中,所有的重要数据结构都是以结构体的形式实现的,并以结构体指针的形式传递。
// openCV中没有私有数据!
IplImage* out = cvCreateImage(
cvSize( in->width/2, in->height/2 ),
in->depth,
in->nChannels
);
cvPyrDown( in, out );
return( out );
}; int main( int argc, char** argv )
{
IplImage* img = cvLoadImage("adrian.jpg" );
IplImage* img2 = cvCreateImage( cvSize( img->width/2,img->height/2 ), img->depth, img->nChannels);
cvNamedWindow("Example1", CV_WINDOW_AUTOSIZE );
cvNamedWindow("Example2", CV_WINDOW_AUTOSIZE );
cvShowImage("Example1", img );
img2 = doPyrDown( img );
cvShowImage("Example2", img2 );
cvWaitKey(0);
cvReleaseImage( &img );
cvReleaseImage( &img2 );
cvDestroyWindow("Example1");
cvDestroyWindow("Example2");
}
2、4  Canny边缘检测

在进行Canny处理前得先进行灰度处理

cvCvtColor(img_rgb, img_gry ,CV_BGR2GRAY);

  1. #include "cv.h"
  2. #include "highgui.h"
  3. IplImage* doCanny(
  4. IplImage* in,
  5. double    lowThresh,
  6. double    highThresh,
  7. double    aperture)
  8. {
  9. if (in->nChannels != 1)
  10. return(0); // Canny 仅处理多通道图像
  11. IplImage* out = cvCreateImage(
  12. cvGetSize( in ),
  13. in->depth, //IPL_DEPTH_8U,
  14. 1);
  15. cvCanny( in, out, lowThresh, highThresh, aperture );
  16. return( out );
  17. };
  18. int main( int argc, char** argv )
  19. {
  20. IplImage* img_rgb = cvLoadImage( "adrian.jpg" );
  21. IplImage* img_gry = cvCreateImage( cvSize( img_rgb->width,img_rgb->height ), img_rgb->depth, 1);
  22. cvCvtColor(img_rgb, img_gry ,CV_BGR2GRAY);
  23. cvNamedWindow("Example Gray", CV_WINDOW_AUTOSIZE );
  24. cvNamedWindow("Example Canny", CV_WINDOW_AUTOSIZE );
  25. cvShowImage("Example Gray", img_gry );
  26. IplImage* img_cny = doCanny( img_gry, 10, 100, 3 );
  27. cvShowImage("Example Canny", img_cny );
  28. cvWaitKey(0);
  29. cvReleaseImage( &img_rgb);
  30. cvReleaseImage( &img_gry);
  31. cvReleaseImage( &img_cny);
  32. cvDestroyWindow("Example Gray");
  33. cvDestroyWindow("Example Canny");
  34. }
#include "cv.h"
#include "highgui.h" IplImage* doCanny(
IplImage* in,
double lowThresh,
double highThresh,
double aperture)
{
if (in->nChannels != 1)
return(0); // Canny 仅处理多通道图像
IplImage* out = cvCreateImage(
cvGetSize( in ),
in->depth, //IPL_DEPTH_8U,
1);
cvCanny( in, out, lowThresh, highThresh, aperture );
return( out );
}; int main( int argc, char** argv )
{
IplImage* img_rgb = cvLoadImage( "adrian.jpg" );
IplImage* img_gry = cvCreateImage( cvSize( img_rgb->width,img_rgb->height ), img_rgb->depth, 1);
cvCvtColor(img_rgb, img_gry ,CV_BGR2GRAY);
cvNamedWindow("Example Gray", CV_WINDOW_AUTOSIZE );
cvNamedWindow("Example Canny", CV_WINDOW_AUTOSIZE );
cvShowImage("Example Gray", img_gry );
IplImage* img_cny = doCanny( img_gry, 10, 100, 3 );
cvShowImage("Example Canny", img_cny );
cvWaitKey(0);
cvReleaseImage( &img_rgb);
cvReleaseImage( &img_gry);
cvReleaseImage( &img_cny);
cvDestroyWindow("Example Gray");
cvDestroyWindow("Example Canny");
}

接下来我们想缩放图像两次,然后在缩放后的图像中寻找边缘,具体如下所示:

  1. #include "cv.h"
  2. #include "highgui.h"
  3. IplImage* doCanny(
  4. IplImage* in,
  5. double    lowThresh,
  6. double    highThresh,
  7. double    aperture)
  8. {
  9. IplImage* out = cvCreateImage(
  10. cvGetSize( in ),
  11. in->depth, //IPL_DEPTH_8U,
  12. 1);
  13. cvCanny( in, out, lowThresh, highThresh, aperture );
  14. return( out );
  15. };
  16. IplImage* doPyrDown(
  17. IplImage* in,
  18. int       filter = IPL_GAUSSIAN_5x5)
  19. {
  20. // Best to make sure input image is divisible by two.
  21. //
  22. //assert( in->width%2 == 0 && in->height%2 == 0 );
  23. IplImage* out = cvCreateImage(
  24. cvSize( in->width/2, in->height/2 ),
  25. in->depth,
  26. in->nChannels
  27. );
  28. cvPyrDown( in, out );
  29. return( out );
  30. };
  31. int main( int argc, char** argv )
  32. {
  33. IplImage* img_rgb  = cvLoadImage( "adrian.jpg" );
  34. IplImage* img_gry  = cvCreateImage( cvSize( img_rgb->width,img_rgb->height ), img_rgb->depth, 1);
  35. cvCvtColor(img_rgb, img_gry ,CV_BGR2GRAY);
  36. IplImage* img_pyr  = doPyrDown( img_gry, IPL_GAUSSIAN_5x5 );
  37. IplImage* img_pyr2 = doPyrDown( img_pyr, IPL_GAUSSIAN_5x5 );
  38. IplImage* img_cny  = doCanny( img_pyr2, 10, 100, 3 );
  39. cvNamedWindow("Example Gray", CV_WINDOW_AUTOSIZE );
  40. cvNamedWindow("Example Pyr", CV_WINDOW_AUTOSIZE );
  41. cvNamedWindow("Example Canny", CV_WINDOW_AUTOSIZE );
  42. cvShowImage("Example Gray", img_gry );
  43. cvShowImage("Example Pyr", img_pyr2 );
  44. cvShowImage("Example Canny", img_cny );
  45. cvWaitKey(0);
  46. cvReleaseImage( &img_rgb);
  47. cvReleaseImage( &img_gry);
  48. cvReleaseImage( &img_pyr);
  49. cvReleaseImage( &img_pyr2);
  50. cvReleaseImage( &img_cny);
  51. cvDestroyWindow("Example Gray");
  52. cvDestroyWindow("Example Pyr");
  53. cvDestroyWindow("Example Canny");
  54. }
#include "cv.h"
#include "highgui.h" IplImage* doCanny(
IplImage* in,
double lowThresh,
double highThresh,
double aperture)
{
IplImage* out = cvCreateImage(
cvGetSize( in ),
in->depth, //IPL_DEPTH_8U,
1);
cvCanny( in, out, lowThresh, highThresh, aperture );
return( out );
}; IplImage* doPyrDown(
IplImage* in,
int filter = IPL_GAUSSIAN_5x5)
{ // Best to make sure input image is divisible by two.
//
//assert( in->width%2 == 0 && in->height%2 == 0 ); IplImage* out = cvCreateImage(
cvSize( in->width/2, in->height/2 ),
in->depth,
in->nChannels
);
cvPyrDown( in, out );
return( out );
}; int main( int argc, char** argv )
{
IplImage* img_rgb = cvLoadImage( "adrian.jpg" );
IplImage* img_gry = cvCreateImage( cvSize( img_rgb->width,img_rgb->height ), img_rgb->depth, 1);
cvCvtColor(img_rgb, img_gry ,CV_BGR2GRAY);
IplImage* img_pyr = doPyrDown( img_gry, IPL_GAUSSIAN_5x5 );
IplImage* img_pyr2 = doPyrDown( img_pyr, IPL_GAUSSIAN_5x5 );
IplImage* img_cny = doCanny( img_pyr2, 10, 100, 3 ); cvNamedWindow("Example Gray", CV_WINDOW_AUTOSIZE );
cvNamedWindow("Example Pyr", CV_WINDOW_AUTOSIZE );
cvNamedWindow("Example Canny", CV_WINDOW_AUTOSIZE );
cvShowImage("Example Gray", img_gry );
cvShowImage("Example Pyr", img_pyr2 );
cvShowImage("Example Canny", img_cny );
cvWaitKey(0);
cvReleaseImage( &img_rgb);
cvReleaseImage( &img_gry);
cvReleaseImage( &img_pyr);
cvReleaseImage( &img_pyr2);
cvReleaseImage( &img_cny);
cvDestroyWindow("Example Gray");
cvDestroyWindow("Example Pyr");
cvDestroyWindow("Example Canny");
}
2、4、1  内存释放考虑方面的改进

(1)像下面这样进行嵌套调用是一个不好的主意,因为内存空间的释放会成为一个很困难的问题。

IplImage* img_pyr  = doPyrDown( img_gry, IPL_GAUSSIAN_5x5 );
 IplImage* img_pyr2 = doPyrDown( img_pyr, IPL_GAUSSIAN_5x5 );
 IplImage* img_cny  = doCanny( img_pyr2, 10, 100, 3 );

(2) 在OpenCV中我们必须确认被释放的空间必须是我们分配,但在我们上面的例子中却释放了非显示分配的内存

cvReleaseImage( &img_pyr);
 cvReleaseImage( &img_pyr2);
 cvReleaseImage( &img_cny);

所以我们把例子改为:

  1. int main( int argc, char** argv )
  2. {
  3. IplImage* img_rgb  = cvLoadImage( "adrian.jpg" );
  4. IplImage* img_gry  = cvCreateImage( cvSize( img_rgb->width,img_rgb->height ), img_rgb->depth, 1);
  5. cvCvtColor(img_rgb, img_gry ,CV_BGR2GRAY);
  6. /*
  7. IplImage* img_pyr  = doPyrDown( img_gry, IPL_GAUSSIAN_5x5 );
  8. IplImage* img_pyr2 = doPyrDown( img_pyr, IPL_GAUSSIAN_5x5 );
  9. IplImage* img_cny  = doCanny( img_pyr2, 10, 100, 3 );
  10. cvNamedWindow("Example Gray", CV_WINDOW_AUTOSIZE );
  11. cvNamedWindow("Example Pyr", CV_WINDOW_AUTOSIZE );
  12. cvNamedWindow("Example Canny", CV_WINDOW_AUTOSIZE );
  13. cvShowImage("Example Gray", img_gry );
  14. cvShowImage("Example Pyr", img_pyr2 );
  15. cvShowImage("Example Canny", img_cny );
  16. cvWaitKey(0);
  17. cvReleaseImage( &img_rgb);
  18. cvReleaseImage( &img_gry);
  19. cvReleaseImage( &img_pyr);
  20. cvReleaseImage( &img_pyr2);
  21. cvReleaseImage( &img_cny);
  22. cvDestroyWindow("Example Gray");
  23. cvDestroyWindow("Example Pyr");
  24. cvDestroyWindow("Example Canny");
  25. */
  26. // 像上面这样进行嵌套调用是一个不好的主意,因为内存空间的释放会成为一个很困难的问题。
  27. IplImage* out;
  28. cvNamedWindow("Example Gray", CV_WINDOW_AUTOSIZE );
  29. cvNamedWindow("Example Pyr", CV_WINDOW_AUTOSIZE );
  30. cvNamedWindow("Example Canny", CV_WINDOW_AUTOSIZE );
  31. // 第一次缩放
  32. cvShowImage("Example Gray", img_gry );
  33. out = doPyrDown( img_gry, IPL_GAUSSIAN_5x5 );
  34. // 第一次缩放
  35. cvShowImage("Example Pyr", out );
  36. out = doPyrDown( out, IPL_GAUSSIAN_5x5 );
  37. // Canny处理
  38. out  = doCanny( out, 10, 100, 3 );
  39. cvShowImage("Example Canny", out );
  40. cvWaitKey(0);
  41. cvReleaseImage( &img_rgb);
  42. cvReleaseImage( &img_gry);
  43. // 在OpenCV中我们必须确认被释放的空间必须是我们分配的
  44. cvReleaseImage( &out);
  45. cvDestroyWindow("Example Gray");
  46. cvDestroyWindow("Example Pyr");
  47. cvDestroyWindow("Example Canny");
  48. }

OpenCV 例子代码的讲解、简介及库的安装 .的更多相关文章

  1. 常用正则表达式最强汇总(含Python代码举例讲解+爬虫实战)

    大家好,我是辰哥~ 本文带大家学习正则表达式,并通过python代码举例讲解常用的正则表达式 最后实战爬取小说网页:重点在于爬取的网页通过正则表达式进行解析. 正则表达式语法 Python的re模块( ...

  2. 第三百三十节,web爬虫讲解2—urllib库爬虫—实战爬取搜狗微信公众号—抓包软件安装Fiddler4讲解

    第三百三十节,web爬虫讲解2—urllib库爬虫—实战爬取搜狗微信公众号—抓包软件安装Fiddler4讲解 封装模块 #!/usr/bin/env python # -*- coding: utf- ...

  3. 第三百二十七节,web爬虫讲解2—urllib库爬虫—基础使用—超时设置—自动模拟http请求

    第三百二十七节,web爬虫讲解2—urllib库爬虫 利用python系统自带的urllib库写简单爬虫 urlopen()获取一个URL的html源码read()读出html源码内容decode(& ...

  4. AndroidStudio用Cmake方式编译NDK代码(cmake配置.a库)

    1.cmake是什么? CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程).他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C+ ...

  5. 【智能算法】粒子群算法(Particle Swarm Optimization)超详细解析+入门代码实例讲解

    喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 01 算法起源 粒子群优化算法(PSO)是一种进化计算技术(evolutionary computation),1995 年由E ...

  6. <<精通iOS开发>>第14章例子代码彻底清除警告

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 上一篇我们解决了<<精通iOS开发>> ...

  7. 第三百三十六节,web爬虫讲解2—urllib库中使用xpath表达式—BeautifulSoup基础

    第三百三十六节,web爬虫讲解2—urllib库中使用xpath表达式—BeautifulSoup基础 在urllib中,我们一样可以使用xpath表达式进行信息提取,此时,你需要首先安装lxml模块 ...

  8. 第三百二十九节,web爬虫讲解2—urllib库爬虫—ip代理—用户代理和ip代理结合应用

    第三百二十九节,web爬虫讲解2—urllib库爬虫—ip代理 使用IP代理 ProxyHandler()格式化IP,第一个参数,请求目标可能是http或者https,对应设置build_opener ...

  9. 第三百二十八节,web爬虫讲解2—urllib库爬虫—状态吗—异常处理—浏览器伪装技术、设置用户代理

    第三百二十八节,web爬虫讲解2—urllib库爬虫—状态吗—异常处理—浏览器伪装技术.设置用户代理 如果爬虫没有异常处理,那么爬行中一旦出现错误,程序将崩溃停止工作,有异常处理即使出现错误也能继续执 ...

随机推荐

  1. Codeforces 492B B. Vanya and Lanterns

    Codeforces  492B   B. Vanya and Lanterns 题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid= ...

  2. linux命令: patch

    一. 针对单文件的patch: 我们以mkprj.sh.1和mkprj.sh两个文件为例: [root@localhost tst]# lsmkprj.sh.1  mkprj.sh 看两个文件的差异: ...

  3. 基础算法-查找:线性索引查找(II)

    索引查找是在索引表和主表(即线性表的索引存储结构)上进行的查找. 索引查找的过程是: 1)首先根据给定的索引值K1,在索引表上查找出索引值等于K1的索引项,以确定对应子表在主表中的开始位置和长度. 2 ...

  4. 基本的编程原则SOLID

    1.单一职责原则:每个类只负责完成一个职责,当它需要完成多个职责时就需要将它拆分开来. 2.开放封闭原则:对扩展开放,对修改封闭. 3.里氏替换原则:子类对象可以替换(代替)它的所有父类(超类)对象. ...

  5. Nginx 之一:编译安装nginx 1.8.1 及配置

    一:基介绍 官网地址www.nginx.org,nginx是由1994年毕业于俄罗斯国立莫斯科鲍曼科技大学的同学为俄罗斯rambler.ru公司开发的,开发工作最早从2002年开始,第一次公开发布时间 ...

  6. spoj 7001

    /*** 大意:计算gcd(x,y,z) =1 0<= x, y , z <= n 问有多少个这样的对 莫比乌斯反演:(反演: 用结果推原因) 函数m(m)的定义如下: 莫比乌斯反演: * ...

  7. C语言之辗转相除法

    最大公约数和最小公倍数 从键盘输入两个正整数,求出其最大公约数和最小公倍数.代码如下: #include<stdio.h>int ss(int);int main(void){ int a ...

  8. Apache的Mod_rewrite学习(RewriteRule重写规则的语法)

    URL:http://www.tenwe.com/tech/web/server/200705/content_1548.shtml 今天学习重写规则的语法.RewriteRuleSyntax: Re ...

  9. IE6不支持<a>标签以外元素的hover的解决方案

    IE6以及更低版本的浏览器对“:hover”的支持不理想,对于类似的“p:hover”.“img:hover”.“#header:hover”...,今天给大家介绍一种新的方法,可以完美解决IE6不支 ...

  10. Qt在各平台上的搭建qt-everywhere

    Qt for windows7-64bit 在电脑上安装mingw(搜索mingw for windows),将C:\MinGW\bin添加进环境变量,打开命令行输入gcc --version和g++ ...