用openCV实现对视频中动态目标的追踪
第一步,是要建立一个编程环境,然后加载opencv的库路径等等。具体步骤在
https://www.doczj.com/doc/0412472376.html,/ 的“安装”中有详细介绍。
第二步,建立一个MFC的对话框程序,做两个按钮,一个“打开视频文件”,一个“运动跟踪处理”。
具体操作:
1 建立MFC对话框程序的框架:File ->New -> MFC AppWizard(exe),选取工程路径,并取工程名“VideoProcesssing”-> Next -> 选择Dialog based后,点Finish,点OK.
2 添加按钮:直接Delete掉界面默认的两个“确定”“取消”按钮。然后添加两个button,分别名为“打开视频”,“运动跟踪处理”,其ID分别设为IDC_OPEN_VIDEO,IDC_TRACKING.
3 添加消息响应函数:双击按钮“打开视频”,自动生成响应函数名OnOpenVideo,点Ok。然后添加如下代码:
CFileDialog dlg(true,"*.avi",NULL,NULL,"*.avi|*.avi||");
if (dlg.DoModal()==IDOK)
{
strAviFilePath = dlg.GetPathName();
}else
{
return;
}
同样,双击“运动跟踪处理”,选择默认的响应函数名,然后添加代码:
//声明IplImage指针
IplImage* pFrame = NULL;
IplImage* pFrImg = NULL;
IplImage* pBkImg = NULL;
CvMat* pFrameMat = NULL;
CvMat* pFrMat = NULL;
CvMat* pBkMat = NULL;
CvCapture* pCapture = NULL;
int nFrmNum = 0;
//打开AVI视频文件
if(strAviFilePath=="") //判断文件路径是否为空
{
MessageBox("请先选择AVI视频文件!");
return;
}else
{
if(!(pCapture = cvCaptureFromFile(strAviFilePath)))
{
MessageBox("打开AVI视频文件失败!");
return;
}
}
//创建窗口
cvNamedWindow("Video", 1);
cvNamedWindow("Background",1);
cvNamedWindow("Foreground",1);
//使窗口有序排列,窗口宽330
cvMoveWindow("Video", 30, 0);
cvMoveWindow("Background", 360, 0);
cvMoveWindow("Foreground", 690, 0);
//逐帧读取视频
while(pFrame = cvQueryFrame( pCapture ))
{
nFrmNum++;
//如果是第一帧,需要申请内存,并初始化
if(nFrmNum == 1)
{
pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,1); // 存放背景图像(灰度)
pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,1); // 存放中间图像(灰度)
pBkMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
pFrMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
pFrameMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
//转化成单通道图像再处理(灰度)
cvCvtColor(pFrame, pBkImg, CV_BGR2GRAY);
cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);
cvConvert(pFrImg, pFrameMat);
cvConvert(pFrImg, pFrMat);
cvConvert(pFrImg, pBkMat);
}
else
{
cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY); //转化成单通道图像再处理(灰度)
cvConvert(pFrImg, pFrameMat);
//高斯滤波先,以平滑图像
//cvSmooth(pFrameMat, pFrameMat, CV_GAUSSIAN, 3, 0, 0);
//当前帧跟背景图相减(求背景差并取绝对值)
cvAbsDiff(pFrameMat, pBkMat, pFrMat);
//二值化前景图(这里采用特定阈值进行二值化)
cvThreshold(pFrMat, pFrImg, 60, 255.0, CV_THRESH_BINARY);
//进行形态学滤波,去掉噪音
cvErode(pFrImg, pFrImg, 0, 1);
cvDilate(pFrImg, pFrImg, 0, 1);
//滑动平均更新背景(求平均)
cvRunningAvg(pFrameMat, pBkMat, 0.003, 0);
//将背景转化为图像格式,用以显示
cvConvert(pBkMat, pBkImg);
// 保持原图像的旋转方向
pBkImg->origin = pFrImg->origin = pFrame->origin;
//显示图像
cvShowImage("Video", pFrame);
cvShowImage("Background", pBkImg);
cvShowImage("Foreground", pFrImg);
//如果有按键事件,则跳出循环
//此等待也为cvShowImage函数提供时间完成显示
//等待时间可以根据CPU速度调整
if( cvWaitKey(200) >= 0 )
break;
}
}
//销毁窗口
cvDestroyWindow("Video");
cvDestroyWindow("Background");
cvDestroyWindow("Foreground");
//释放图像和矩阵
cvReleaseImage(&pFrImg);
cvReleaseImage(&pBkImg);
cvReleaseMat(&pFrameMat);
cvReleaseMat(&pFrMat);
cvReleaseMat(&pBkMat);
cvReleaseCapture(&pCapture);
4 选fileview选项卡中VideoProcessingDlg.h,在CVideoProcessingDlg类中添加公有类成员:
CString strAviFilePath;
5 选fileview选项卡中VideoProcessingDlg.cpp,添加opencv头文件
#include "cv.h"
#include "highgui.h"
#include "cxcore.h"
6 点击Project——settings——link——Object/library modules下填入cxcore.lib cv.lib cvaux.lib highgui.lib cvcam.lib ml.lib
7 编译执行,成功!
#include "stdafx.h" #include "mymfc.h" #include "mymfcDlg.h" #include "afxdialogex.h" #include
CmymfcDlg::CmymfcDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CmymfcDlg::IDD, pParent) , TheImage(NULL) , rePath(_T("")) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CmymfcDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CmymfcDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_ReadImg, &CmymfcDlg::OnBnClickedReadimg) ON_BN_CLICKED(IDC_EdgeDetect, &CmymfcDlg::OnBnClickedEdgedetect) ON_BN_CLICKED(IDC_Refresh, &CmymfcDlg::OnBnClickedRefresh) ON_BN_CLICKED(IDC_GrayProcess, &CmymfcDlg::OnBnClickedGrayprocess) ON_BN_CLICKED(IDC_Sobel, &CmymfcDlg::OnBnClickedSobel) ON_BN_CLICKED(IDC_Laplace, &CmymfcDlg::OnBnClickedLaplace) ON_BN_CLICKED(IDC_FFT2, &CmymfcDlg::OnBnClickedFft2) ON_BN_CLICKED(IDC_CImage, &CmymfcDlg::OnBnClickedCimage) ON_BN_CLICKED(IDC_Mirror, &CmymfcDlg::OnBnClickedMirror) ON_BN_CLICKED(IDC_CColor, &CmymfcDlg::OnBnClickedCcolor) ON_BN_CLICKED(IDC_MedianBlur, &CmymfcDlg::OnBnClickedMedianblur) ON_BN_CLICKED(IDC_Gaussian, &CmymfcDlg::OnBnClickedGaussian) ON_BN_CLICKED(IDC_BothSide, &CmymfcDlg::OnBnClickedBothside) ON_BN_CLICKED(IDC_Equally, &CmymfcDlg::OnBnClickedEqually) ON_BN_CLICKED(IDC_Corrosion, &CmymfcDlg::OnBnClickedCorrosion) ON_BN_CLICKED(IDC_Dilate, &CmymfcDlg::OnBnClickedDilate) END_MESSAGE_MAP() // CmymfcDlg 消息处理程序 BOOL CmymfcDlg::OnInitDialog() { CDialogEx::OnInitDialog();
/. #include "stdafx.h" #include "mymfc.h" #include "mymfcDlg.h" #include "afxdialogex.h" #include
CmymfcDlg::CmymfcDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CmymfcDlg::IDD, pParent) , TheImage(NULL) , rePath(_T("")) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CmymfcDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CmymfcDlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_ReadImg, &CmymfcDlg::OnBnClickedReadimg) ON_BN_CLICKED(IDC_EdgeDetect, &CmymfcDlg::OnBnClickedEdgedetect) ON_BN_CLICKED(IDC_Refresh, &CmymfcDlg::OnBnClickedRefresh) ON_BN_CLICKED(IDC_GrayProcess, &CmymfcDlg::OnBnClickedGrayprocess) ON_BN_CLICKED(IDC_Sobel, &CmymfcDlg::OnBnClickedSobel) ON_BN_CLICKED(IDC_Laplace, &CmymfcDlg::OnBnClickedLaplace) ON_BN_CLICKED(IDC_FFT2, &CmymfcDlg::OnBnClickedFft2) ON_BN_CLICKED(IDC_CImage, &CmymfcDlg::OnBnClickedCimage) ON_BN_CLICKED(IDC_Mirror, &CmymfcDlg::OnBnClickedMirror) ON_BN_CLICKED(IDC_CColor, &CmymfcDlg::OnBnClickedCcolor) ON_BN_CLICKED(IDC_MedianBlur, &CmymfcDlg::OnBnClickedMedianblur) ON_BN_CLICKED(IDC_Gaussian, &CmymfcDlg::OnBnClickedGaussian) ON_BN_CLICKED(IDC_BothSide, &CmymfcDlg::OnBnClickedBothside) ON_BN_CLICKED(IDC_Equally, &CmymfcDlg::OnBnClickedEqually) ON_BN_CLICKED(IDC_Corrosion, &CmymfcDlg::OnBnClickedCorrosion) ON_BN_CLICKED(IDC_Dilate, &CmymfcDlg::OnBnClickedDilate) END_MESSAGE_MAP() // CmymfcDlg 消息处理程序 BOOL CmymfcDlg::OnInitDialog() { CDialogEx::OnInitDialog();
// cvCalib.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include
本程序主要实现的是车牌的定位与检测 主要是利用申继龙论文里面的方法 1、采集得到的图像 2、把RGB图像转换成HSI彩色图像 3、利用设定的H、S阈值得到二值图像 4、对二值图像水平投影获得候选区域 5、对候选区域的HSI图像边缘检测 */ #include "stdafx.h" #include "opencv2/opencv.hpp" #include "opencv2/objdetect/objdetect.hpp" #include "opencv2/features2d/features2d.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/calib3d/calib3d.hpp" #include "opencv2/nonfree/nonfree.hpp" #include "opencv2/nonfree/features2d.hpp" #include "opencv2/imgproc/imgproc_c.h" #include "opencv2/legacy/legacy.hpp" #include "opencv2/legacy/compat.hpp" #include
#include "cv.h" #include "highgui.h" #include
竭诚为您提供优质文档/双击可除opencv,模板匹配源码 篇一:opencv模板匹配 opencv模板匹配 V1.0 zhbrain 1、2、1)2)3、1)2) opencv模板匹配原理--没有金字塔................................................. ..........................4模板匹配—使用金字塔................................................. ...............................................5主要函数简介................................................. ................................................... ........5程序流程................................................. ................................................... ................5验证和结
果................................................. ................................................... ...............5实验环境................................................. ................................................... ................5实验结果................................................. ................................................... . (5) opencv模板匹配 1、opencv模板匹配原理--没有金字塔 函数: cvmatchtemplate(source,target,result,method);说明:source:源图像,一般我们使用灰度图像;如果source 为Rgb图像,使用函数cvcvtcolor(source,dst,cV_Rgb2gRay)这里,dst为转换后的灰度图像。target:模板图像。 Result:匹配后的矩阵,width=s_width–t_taget+1,height=s_height–t_height+1使用函数 iplimage*result=cvcreateimage(resultsize,ipl_depth_ 32F,1)获得。method:cV_tm_sqdiFF: cV_tm_sqdiFF_noRmed cV_tm_ccoRR
1.void cvSkinSegment(IplImage* img, IplImage* mask){ 2. CvSize imageSize = cvSize(img->width, img->height); 3. IplImage *imgY = cvCreateImage(imageSize, IPL_DEPTH_8U, 1); 4. IplImage *imgCr = cvCreateImage(imageSize, IPL_DEPTH_8U, 1); 5. IplImage *imgCb = cvCreateImage(imageSize, IPL_DEPTH_8U, 1); 6. 7. 8. IplImage *imgYCrCb = cvCreateImage(imageSize, img->depth, img->nChannels ); 9. cvCvtColor(img,imgYCrCb,CV_BGR2YCrCb); 10. cvSplit(imgYCrCb, imgY, imgCr, imgCb, 0); 11.int y, cr, cb, l, x1, y1, value; 12. unsigned char *pY, *pCr, *pCb, *pMask; 13. 14. pY = (unsigned char *)imgY->imageData; 15. pCr = (unsigned char *)imgCr->imageData; 16. pCb = (unsigned char *)imgCb->imageData; 17. pMask = (unsigned char *)mask->imageData; 18. cvSetZero(mask); 19. l = img->height * img->width; 20.for (int i = 0; i < l; i++){ 21. y = *pY; 22. cr = *pCr; 23. cb = *pCb; 24. cb -= 109; 25. cr -= 152 26. ; 27. x1 = (819*cr-614*cb)/32 + 51; 28. y1 = (819*cr+614*cb)/32 + 77; 29. x1 = x1*41/1024; 30. y1 = y1*73/1024; 31. value = x1*x1+y1*y1; 32.if(y<100) (*pMask)=(value<700) ? 255:0; 33.else (*pMask)=(value<850)? 255:0; 34. pY++; 35. pCr++; 36. pCb++; 37. pMask++; 38. } 39. cvReleaseImage(&imgY); 40. cvReleaseImage(&imgCr); 41. cvReleaseImage(&imgCb); 42. cvReleaseImage(&imgYCrCb);
1.打开Microsoft Visual Studio 2008,新建一个Win32控制台项目; 2.配置好项目的包含文件和库文件; 3.将……\OpenCV\data\haarcascades中的haarcascade_frontalface_alt.xml拷贝到所建项目的文件夹中; 4.然后添加代码: #include"stdafx.h" #include"cv.h" #include"highgui.h" #include
(1)分配内存给一幅新图像 IplImage* cvCreateImage(CvSizesize, int depth, int channels); size: cvSize(width,height); depth: 像素深度: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U, channels: 像素通道数. Can be 1, 2, 3 or 4. 示例: // Allocate a1-channel byte image IplImage* img1=cvCreateIm age(cvSize(640,480),IPL_DEPTH_8U,1); (2)释放图像 IplImage* img=cvCreateIma ge(cvSize(640,480),IPL_DEPTH_8U,1); cvReleaseImage(&img); (3)复制图像 IplImage* img1=cvCreateIm age(cvSize(640,480),IPL_DEPTH_8U,1); IplImage* img2;
img2=cvCloneImage(img1); (4)从文件中读入图像 IplImage* img=0; img=cvLoadImage (fileName); if(!img) printf("Couldnot load imagefile:%s\n",fileName); (5)头文件: #include
/* //////////////////////////////////////////////////////////////////// // // CvMat, CvMatND, CvSparceMat and IplImage support functions // (creation, deletion, copying, retrieving and setting elements etc.) // // */ #include "_cxcore.h" static struct { Cv_iplCreateImageHeader createHeader; Cv_iplAllocateImageData allocateData; Cv_iplDeallocate deallocate; Cv_iplCreateROI createROI; Cv_iplCloneImage cloneImage; } CvIPL; // Makes the library use native IPL image allocators CV_IMPL void cvSetIPLAllocators( Cv_iplCreateImageHeader createHeader, Cv_iplAllocateImageData allocateData, Cv_iplDeallocate deallocate, Cv_iplCreateROI createROI, Cv_iplCloneImage cloneImage ) { CV_FUNCNAME( "cvSetIPLAllocators" ); __BEGIN__; if( !createHeader || !allocateData || !deallocate || !createROI || !cloneImage ) { if( createHeader || allocateData || deallocate || createROI || cloneImage ) CV_ERROR( CV_StsBadArg, "Either all the pointers should be null or " "they all should be non-null" ); } CvIPL.createHeader = createHeader; CvIPL.allocateData = allocateData; CvIPL.deallocate = deallocate; CvIPL.createROI = createROI; CvIPL.cloneImage = cloneImage;
CMake编译Opencv自带源码及程序形成工程并运行教程 本教程基于https://www.doczj.com/doc/0412472376.html,/2014/09/66490.html,感谢网友的贡献,本教程首先回顾一下网友的教程,重点在于解决网友没有提到的各种问题(第5章),因此前四章,大家也可以看原网址上提供的内容。 声明:纯粹经验之谈,重点是解决问题,若有理解错误,请多包涵~~ 一直很想直接打开运行opencv自带的示例程序,或者看看里面一些函数的源码,奈何opencv库里面给出的都是源文件,直接打开不能运行,没有编译形成VS中的工程方案,所以要看时,只得自己新建工程,然后复制过去,先不说麻烦,就算真弄过去了,还不一定能运行,因为它还可能有依赖项什么的问题(猜的),总之不一定能够顺利运行。后来听说可以用CMake对其进行编译,可以形成VS中的工程方案,然后直接就可以打开运行了,这当然方便多了,于是就有了下面的东西~~~ 1下载及安装CMake 在写本教程的时候,CMake最新版本为CMake3.4.1,下载网址为:https://https://www.doczj.com/doc/0412472376.html,/download/,CMake有很多的发行版本,具体有哪些,作为一个小白,也不懂什么,只是知道其中有分source和binary两种版本,前面的那个版本貌似是对应源码版本,也就是给的是CMake的源码,如果我们要用它去编译其他如opencv的源码,那得先编译CMake的source文件,然后还要写CMakeList.txt(相当于是通过编程来实现编译其他文件,本人这么理解,若有误,莫怪~),这么复杂,对我来说,肯定不想要;因此,我选择了binary版本(直接是二进制文件,已经编译好了,并形成了可执行程序),下载之后是一个.exe文件,这个就好办多了,下载下来,点击运行一顿安装就可以了~~~ 开始进入正题~~~ 下面摘录一段关于CMake的介绍(摘自教程开头的网址): CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C 特性,类似UNIX下的automake。只是CMake的组态档取名为CmakeLists.txt。Cmake并不直接建构出最终的软件,而是产生标准的建构档(如Unix 的Makefile或Windows Visual C 的projects/workspaces),然后再依一般的建构方式使用。这使得熟悉某个集成开发环境(IDE)的开发者可以用标准的方式建构他的软件,这种可以使用各平台的原生建构系统的能力是CMake
提供函数DWT()和IDWT(),前者完成任意层次的小波变换,后者完成任意层次的小波逆变换。输入图像要求必须是单通道浮点图像,对图像大小也有要求(1层变换:w,h必须是2的倍数;2层变换:w,h必须是4的倍数;3层变换:w,h必须是8的倍数......),变换后的结果直接保存在输入图像中。 1、函数参数简单,图像指针pImage和变换层数nLayer。 2、一个函数直接完成多层次二维小波变换,尽量减少下标运算,避免不必要的函数调用,以提高执行效率。 3、变换过程中,使用了一个指针数组pData用于保存每行数据的起始位置,pRow和pColumn 用于保存一行和一列临时数据,用于奇偶分离或合并,内存消耗较少 // 二维离散小波变换(单通道浮点图像) void DWT(IplImage *pImage, int nLayer) { // 执行条件 if (pImage) { if (pImage->nChannels == 1 && pImage->depth == IPL_DEPTH_32F && ((pImage->width >> nLayer) << nLayer) == pImage->width && ((pImage->height >> nLayer) << nLayer) == pImage->height) { int i, x, y, n; float fValue = 0; float fRadius = sqrt(2.0f); int nWidth = pImage->width; int nHeight = pImage->height; int nHalfW = nWidth / 2; int nHalfH = nHeight / 2; float **pData = new float*[pImage->height]; float *pRow = new float[pImage->width]; float *pColumn = new float[pImage->height]; for (i = 0; i < pImage->height; i++) { pData[i] = (float*) (pImage->imageData + pImage->widthStep * i); } // 多层小波变换 for (n = 0; n < nLayer; n++, nWidth /= 2, nHeight /= 2, nHalfW /= 2, nHalfH /= 2) { // 水平变换 for (y = 0; y < nHeight; y++) { // 奇偶分离 memcpy(pRow, pData[y], sizeof(float) * nWidth);
源代码: #include"highgui.h" int main( int argc, char** argv ) //主函数至少有两个参数:argc和argv,argc是程序的运行参数个数(程序接受参数的个数),argv是运行参数的字符串数组(每个char* 表示程序路径名和参数){ IplImage* img = cvLoadImage( "1.jpg");//加载图像至内存,执行完返回一个指针,IplImage是一个指针,cvloadimage可以读取大多数格式的图像文件 cvNamedWindow("Example1", CV_WINDOW_AUTOSIZE ); //创建一个标题为“Example1”窗口,“Example1”类似句柄,其参数为“CV_WINDOW_AUTOSIZE” cvShowImage("Example1", img ); //显示图像在“Example1”窗口中显示img指针所指的图像cvWaitKey(0);//等待(暂停)函数,“正数n”—暂停n毫秒,“0或负数”—等待用户触发按键 cvReleaseImage( &img );//释放内存,释放img所指向的内存块,执行完后,img被设置成NULL //关闭/销毁窗口 }运行结果:
源代码: #include"highgui.h" int main( int argc, char** argv ) { cvNamedWindow( "Example2", CV_WINDOW_AUTOSIZE ); //创建窗口 CvCapture* capture = cvCreateFileCapture("2.mp4");//生成一个指向视频文件的结构体指针 IplImage* frame; //声明一个图像结构体指针 while(1) {//装载下一帧视频文件至内存,返回对应当前帧的指针 frame = cvQueryFrame( capture ); if( !frame ) break; cvShowImage( "Example2", frame ); //无触发——返回 -1,按键触发——返回该按键的ASCII码,ESC键的ASCII码是 27 char c = cvWaitKey(33); if( c == 27 ) break; } cvReleaseCapture( &capture ); //释放CvCapture结构体的内存空间 cvDestroyWindow( "Example2" ); //关闭/销毁窗口 }运行结果:
Opencv源码编译 For Ubuntu For Android For Windows Version0.1 2013.06.06 目录 1.Ubuntu下编译opencv源代码(For linux&Android) (2) 1.1下载opencv源码 (2) 1.2下载安装Cmake (2) 1.3安装一些ubuntu下必要的库文件: (2) 1.4使用Cmake进行配置: (3) 1.5编译opencv生成linux下的opencv库文件 (3) 1.6测试linux下Opencv例程: (4) 1.7Opencv For Android的编译 (4) 1.7.1安装ndk: (4) 1.7.2安装Android SDK (5) 1.7.4开始编译opencv中关于android相关的源码 (5) 2.Ubuntu下codeblocks Opencv开发环境配置 (7) 2.1下载安装codeblocks (7) 2.2打开cldeblocks建立一个摄像头的测试程序: (8) 2.3配置工程的头文件和链接库 (8) 3.Windows7+codeblocks Opencv开发环境搭建 (11) 3.1下载opencv2.2 (11) 3.5打开CMake (12) 3.6环境变量的设置 (12) 3.7在CMake中点击configure (14) 3.8编译oepncv源码 (15) 3.8.1先进入E盘 (15) 3.8.2进入目录OpenCV-2.2.0-build (15) 3.8.3编译opencv源码 (16) 3.8.4安装opencv库文件 (16) 3.9使用codeblocks建立openv工程 (17) 3.10测试代码 (18) 3.11给工程文件添加opencv相关路径 (19) 3.12编译工程文件 (22) 附其他参考资料备忘 (23)
特征提取代码总结 来自https://www.doczj.com/doc/0412472376.html,/source/3208155#acomment 特征提取代码总结 颜色提取 颜色直方图提取: C ode: #include