03 Opencv部分经典例程赏析

一、SVM分类器(支持向量机引导)

代码:

//--------------------------------------【程序说明】-------------------------------------------
//		程序说明:支持向量机之SVM引导
//		测试所用操作系统: Windows 10 64bit
//		测试所用IDE版本:Visual Studio 2015(企业版)
//		开发测试所用OpenCV版本:	3.1 beta
//		2017年4月 Revised by 陈梓归
//------------------------------------------------------------------------------------------------

//说明:由于此代码由OpenCV2向OpenCV3升级时改动幅度较大,OpenCV2版本的此代码请参考单独的OpenCV2版本。在此不再列出

//---------------------------------【头文件、命名空间包含部分】----------------------------
//		描述:包含程序所使用的头文件和命名空间
//-------------------------------------------------------------------------------------------------
#include 
  
  
   
   
#include 
   
   
    
    
#include 
    
    
     
     
using namespace cv;

//OpenCV3需额外加入:
#include 
     
     
      
      
#include "opencv2/imgcodecs.hpp"
using namespace cv::ml;


//--------------------------------【help( )函数】----------------------------------------------
//		描述:输出帮助信息
//-------------------------------------------------------------------------------------------------

//-----------------------------------【ShowHelpText( )函数】----------------------------------
//          描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
void ShowHelpText()
{
	//输出欢迎信息和OpenCV版本
	printf("\n\n\t\t\t   作者:陈梓归\n");
	printf("\n\n\t\t\t   当前使用的OpenCV版本为:" CV_VERSION);
	printf("\n\n  ----------------------------------------------------------------------------\n");
}

//-----------------------------------【main( )函数】--------------------------------------------
//		描述:控制台应用程序的入口函数,我们的程序从这里开始
//-------------------------------------------------------------------------------------------------
int main()
{
	// 视觉表达数据的设置(Data for visual representation)
	int width = 512, height = 512;
	Mat image = Mat::zeros(height, width, CV_8UC3);

	//建立训练数据( Set up training data)
	int labels[4] = { 1, -1, -1, -1 };
	Mat labelsMat(4, 1, CV_32SC1, labels);

	float trainingData[4][2] = { { 501, 10 },{ 255, 10 },{ 501, 255 },{ 10, 501 } };
	Mat trainingDataMat(4, 2, CV_32FC1, trainingData);

	ShowHelpText();

	//设置支持向量机的参数(Set up SVM's parameters)
	cv::Ptr
      
      
        svm = cv::ml::SVM::create(); svm->setType(cv::ml::SVM::Types::C_SVC); svm->setKernel(cv::ml::SVM::KernelTypes::LINEAR); svm->setTermCriteria(cv::TermCriteria(cv::TermCriteria::MAX_ITER, 100, 1e-6)); // 训练支持向量机(Train the SVM) svm->train(trainingDataMat, cv::ml::SampleTypes::ROW_SAMPLE, labelsMat); Vec3b green(0, 255, 0), blue(255, 0, 0); //显示由SVM给出的决定区域 (Show the decision regions given by the SVM) for (int i = 0; i < image.rows; ++i) for (int j = 0; j < image.cols; ++j) { Mat sampleMat = (Mat_ 
       
         (1, 2) << j, i); float response = svm->predict(sampleMat); if (response == 1) image.at 
        
          (i, j) = green; else if (response == -1) image.at 
         
           (i, j) = blue; } //显示训练数据 (Show the training data) int thickness = -1; int lineType = 8; circle(image, Point(501, 10), 5, Scalar(0, 0, 0), thickness, lineType); circle(image, Point(255, 10), 5, Scalar(255, 255, 255), thickness, lineType); circle(image, Point(501, 255), 5, Scalar(255, 255, 255), thickness, lineType); circle(image, Point(10, 501), 5, Scalar(255, 255, 255), thickness, lineType); //显示支持向量 (Show support vectors) thickness = 2; lineType = 8; Mat sv = svm->getSupportVectors(); for (int i = 0; i < sv.rows; ++i) { const float* v = sv.ptr 
          
            (i); circle(image, Point((int)v[0], (int)v[1]), 6, Scalar(128, 128, 128), thickness, lineType); } imwrite("CZG.png", image); // 保存图像 imshow("SVM Simple Example", image); // 显示图像 waitKey(0); } 
           
          
         
        
      
     
     
    
    
   
   
  
  

效果:



二、SVM分类器(支持向量机之处理线性不可分数据)

注:此例子主要讲解在训练数据线性不可分时,如何定义支持向量机器最优化问题;
代码:
//--------------------------------------【程序说明】-------------------------------------------
//		程序说明:支持向量机之SVM引导
//		测试所用操作系统: Windows 10 64bit
//		测试所用IDE版本:Visual Studio 2015(企业版)
//		开发测试所用OpenCV版本:	3.1 beta
//		2017年4月 Revised by 陈梓归
//------------------------------------------------------------------------------------------------

//说明:由于此代码由OpenCV2向OpenCV3升级时改动幅度较大,OpenCV2版本的此代码请参考单独的OpenCV2版本。在此不再列出

//---------------------------------【头文件、命名空间包含部分】----------------------------
//		描述:包含程序所使用的头文件和命名空间
//------------------------------------------------------------------------------------------------
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
        
        
#include 
        
        
         
         

//OpenCV3需额外加入:
#include 
         
         
           #include "opencv2/imgcodecs.hpp" using namespace cv::ml; #define NTRAINING_SAMPLES 100 // 每类训练样本的数量 #define FRAC_LINEAR_SEP 0.9f // 部分(Fraction)线性可分的样本组成部分 using namespace cv; using namespace std; //-----------------------------------【ShowHelpText( )函数】---------------------------------- // 描述:输出一些帮助信息 //---------------------------------------------------------------------------------------------- void ShowHelpText() { //输出欢迎信息和OpenCV版本 printf("\n\n\t\t\t 作者:陈梓归\n"); printf("\n\n\t\t\t 当前使用的OpenCV版本为:" CV_VERSION); printf("\n\n ----------------------------------------------------------------------------\n"); } //-----------------------------------【main( )函数】-------------------------------------------- // 描述:控制台应用程序的入口函数,我们的程序从这里开始 //------------------------------------------------------------------------------------------------- int main() { //设置视觉表达的参数 const int WIDTH = 512, HEIGHT = 512; Mat I = Mat::zeros(HEIGHT, WIDTH, CV_8UC3); ShowHelpText(); //---------------------【1】随机建立训练数据--------------------------------------- Mat trainData(2 * NTRAINING_SAMPLES, 2, CV_32FC1); Mat labels(2 * NTRAINING_SAMPLES, 1, CV_32SC1); RNG rng(100); // 随机生成值 //建立训练数据的线性可分的组成部分 int nLinearSamples = (int)(FRAC_LINEAR_SEP * NTRAINING_SAMPLES); // 为Class1生成随机点 Mat trainClass = trainData.rowRange(0, nLinearSamples); // 点的x坐标为[0,0.4) Mat c = trainClass.colRange(0, 1); rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(0.4 * WIDTH)); // 点的Y坐标为[0,1) c = trainClass.colRange(1, 2); rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT)); // 为Class2生成随机点 trainClass = trainData.rowRange(2 * NTRAINING_SAMPLES - nLinearSamples, 2 * NTRAINING_SAMPLES); // 点的x坐标为[0.6, 1] c = trainClass.colRange(0, 1); rng.fill(c, RNG::UNIFORM, Scalar(0.6*WIDTH), Scalar(WIDTH)); // 点的Y坐标为[0, 1) c = trainClass.colRange(1, 2); rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT)); //------------------建立训练数据的非线性可分组成部分 --------------- // 随机生成Class1和Class2的点 trainClass = trainData.rowRange(nLinearSamples, 2 * NTRAINING_SAMPLES - nLinearSamples); // 点的x坐标为[0.4, 0.6) c = trainClass.colRange(0, 1); rng.fill(c, RNG::UNIFORM, Scalar(0.4*WIDTH), Scalar(0.6*WIDTH)); // 点的y坐标为[0, 1) c = trainClass.colRange(1, 2); rng.fill(c, RNG::UNIFORM, Scalar(1), Scalar(HEIGHT)); //------------------------- 为类设置标签 --------------------------------- labels.rowRange(0, NTRAINING_SAMPLES).setTo(1); // Class 1 labels.rowRange(NTRAINING_SAMPLES, 2 * NTRAINING_SAMPLES).setTo(2); // Class 2 //------------------------ 2. 设置支持向量机的参数 -------------------- cv::Ptr 
          
            svm = cv::ml::SVM::create(); svm->setType(cv::ml::SVM::Types::C_SVC); svm->setKernel(cv::ml::SVM::KernelTypes::LINEAR); svm->setTermCriteria(cv::TermCriteria(cv::TermCriteria::MAX_ITER, 100, 1e-6)); //------------------------ 3. 训练支持向量机 ---------------------------------------------------- svm->train(trainData, cv::ml::SampleTypes::ROW_SAMPLE, labels); //------------------------ 4. 标出决策区域(decision regions)---------------------------------------- Vec3b green(0, 100, 0), blue(100, 0, 0); for (int i = 0; i < I.rows; ++i) for (int j = 0; j < I.cols; ++j) { Mat sampleMat = (Mat_ 
           
             (1, 2) << i, j); float response = svm->predict(sampleMat); if (response == 1) I.at 
            
              (j, i) = green; else if (response == 2) I.at 
             
               (j, i) = blue; } //----------------------- 5. 显示训练数据(training data)-------------------------------------------- int thick = -1; int lineType = 8; float px, py; // Class 1 for (int i = 0; i < NTRAINING_SAMPLES; ++i) { px = trainData.at 
              
                (i, 0); py = trainData.at 
               
                 (i, 1); circle(I, Point((int)px, (int)py), 3, Scalar(0, 255, 0), thick, lineType); } // Class 2 for (int i = NTRAINING_SAMPLES; i <2 * NTRAINING_SAMPLES; ++i) { px = trainData.at 
                
                  (i, 0); py = trainData.at 
                 
                   (i, 1); circle(I, Point((int)px, (int)py), 3, Scalar(255, 0, 0), thick, lineType); } //------------------------- 6. 显示支持向量(support vectors)------------------------------------------- thick = 2; lineType = 8; Mat sv = svm->getSupportVectors(); for (int i = 0; i < sv.rows; ++i) { const float* v = sv.ptr 
                  
                    (i); circle(I, Point((int)v[0], (int)v[1]), 6, Scalar(128, 128, 128), thick, lineType); } imwrite("CZG.png", I); //保存图像到文件 imshow("SVM for Non-Linear Training Data", I); // 显示最终窗口 waitKey(0); } 
                   
                  
                 
                
               
              
             
            
           
         
        
        
       
       
      
      
     
     

效果:


在这里感谢:http://blog.csdn.net/wfh2015/article/details/51163890
笔者开始运行的时候出现错误(依照大神的代码摸索这解决,感谢~):
1>e:\c++\opencv\opencv\main.cpp(61): error C2039: “Params”: 不是“cv::ml::SVM”的成员
1>  d:\vs2015\opencv\opencv\build\include\opencv2\ml.hpp(481): note: 参见“cv::ml::SVM”的声明
1>e:\c++\opencv\opencv\main.cpp(61): error C2065: “Params”: 未声明的标识符

三、人脸识别

注:记得将haarcascade_eye_tree_eyeglasses.xml和haarcascade_frontalface_alt.xml 和源代码放在同一目录(两个.xml文件自己去官网或者opencv\sources\data\haarcascades\)
代码:
//--------------------------------------【程序说明】-------------------------------------------
//		程序说明:支持向量机之SVM引导
//		测试所用操作系统: Windows 10 64bit
//		测试所用IDE版本:Visual Studio 2015(企业版)
//		开发测试所用OpenCV版本:	3.1 beta
//		2017年4月 Revised by 陈梓归
//------------------------------------------------------------------------------------------------


/**
* @file ObjectDetection.cpp
* @author A. Huaman ( based in the classic facedetect.cpp in samples/c )
* @brief A simplified version of facedetect.cpp, show how to load a cascade classifier and how to find objects (Face + eyes) in a video stream
*/

//---------------------------------【头文件、命名空间包含部分】----------------------------
//		描述:包含程序所使用的头文件和命名空间
//-------------------------------------------------------------------------------------------------
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include 
     
     
      
      
#include 
      
      
       
       

using namespace std;
using namespace cv;




void detectAndDisplay(Mat frame);

//--------------------------------【全局变量声明】----------------------------------------------
//		描述:声明全局变量
//-------------------------------------------------------------------------------------------------
//注意,需要把"haarcascade_frontalface_alt.xml"和"haarcascade_eye_tree_eyeglasses.xml"这两个文件复制到工程路径下
String face_cascade_name = "haarcascade_frontalface_alt.xml";
String eyes_cascade_name = "haarcascade_eye_tree_eyeglasses.xml";
CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;
string window_name = "Capture - Face detection";
RNG rng(12345);


//--------------------------------【help( )函数】----------------------------------------------
//		描述:输出帮助信息
//-------------------------------------------------------------------------------------------------
static void ShowHelpText()
{
	//输出欢迎信息和OpenCV版本
	cout << "\n\n\t\t\t   作者:陈梓归\n"
		<< "\n\n\t\t\t   当前使用的OpenCV版本为:" << CV_VERSION
		<< "\n\n  ----------------------------------------------------------------------------";
}


//-----------------------------------【main( )函数】--------------------------------------------
//		描述:控制台应用程序的入口函数,我们的程序从这里开始
//-------------------------------------------------------------------------------------------------
int main(void)
{
	VideoCapture capture;
	Mat frame;


	//-- 1. 加载级联(cascades)
	if (!face_cascade.load(face_cascade_name)) { printf("--(!)Error loading\n"); return -1; };
	if (!eyes_cascade.load(eyes_cascade_name)) { printf("--(!)Error loading\n"); return -1; };

	//-- 2. 读取视频
	capture.open(0);
	ShowHelpText();
	if (capture.isOpened())
	{
		for (;;)
		{
			capture >> frame;

			//-- 3. 对当前帧使用分类器(Apply the classifier to the frame)
			if (!frame.empty())
			{
				detectAndDisplay(frame);
			}
			else
			{
				printf(" --(!) No captured frame -- Break!"); break;
			}

			int c = waitKey(10);
			if ((char)c == 'c') { break; }

		}
	}
	return 0;
}


void detectAndDisplay(Mat frame)
{
	std::vector
       
       
        
         faces;
	Mat frame_gray;

	cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
	equalizeHist(frame_gray, frame_gray);

	//-- 人脸检测
	//此句代码的OpenCV2版为:
	//face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
	//此句代码的OpenCV3版为:
	face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));


	for (size_t i = 0; i < faces.size(); i++)
	{
		Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2);
		ellipse(frame, center, Size(faces[i].width / 2, faces[i].height / 2), 0, 0, 360, Scalar(255, 0, 255), 2, 8, 0);

		Mat faceROI = frame_gray(faces[i]);
		std::vector
        
        
         
          eyes;

		//-- 在脸中检测眼睛
		//此句代码的OpenCV2版为:
		// eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CV_HAAR_SCALE_IMAGE, Size(30, 30) );
		//此句代码的OpenCV3版为:
		eyes_cascade.detectMultiScale(faceROI, eyes, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));

		for (size_t j = 0; j < eyes.size(); j++)
		{
			Point eye_center(faces[i].x + eyes[j].x + eyes[j].width / 2, faces[i].y + eyes[j].y + eyes[j].height / 2);
			int radius = cvRound((eyes[j].width + eyes[j].height)*0.25);
			circle(frame, eye_center, radius, Scalar(255, 0, 0), 3, 8, 0);
		}
	}
	//-- 显示最终效果图
	imshow(window_name, frame);
}

        
        
       
       
      
      
     
     
效果:


四、点追踪

注:按键盘"r"键来实现自动点追踪。
代码:
//--------------------------------------【程序说明】-------------------------------------------
//		程序说明:支持向量机之SVM引导
//		测试所用操作系统: Windows 10 64bit
//		测试所用IDE版本:Visual Studio 2015(企业版)
//		开发测试所用OpenCV版本:	3.1 beta
//		2017年4月 Revised by 陈梓归
//------------------------------------------------------------------------------------------------

//---------------------------------【头文件、命名空间包含部分】----------------------------
//		描述:包含程序所使用的头文件和命名空间
//-------------------------------------------------------------------------------------------------
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

#include 
     
     
      
      
#include 
      
      
       
       

using namespace cv;
using namespace std;



//--------------------------------【help( )函数】----------------------------------------------
//		描述:输出帮助信息
//-------------------------------------------------------------------------------------------------
static void help()
{
	//输出欢迎信息和OpenCV版本
	cout << "\n\n\t\t\t    作者:陈梓归\n"
		<< "\n\n\t\t\t   当前使用的OpenCV版本为:" << CV_VERSION
		<< "\n\n  ----------------------------------------------------------------------------";
	cout << "\n\n\t该Demo演示了 Lukas-Kanade基于光流的lkdemo\n";
	cout << "\n\t程序默认从摄像头读入视频,可以按需改为从视频文件读入图像\n";
	cout << "\n\t操作说明: \n"
		"\t\t通过点击在图像中添加/删除特征点\n"
		"\t\tESC - 退出程序\n"
		"\t\tr -自动进行追踪\n"
		"\t\tc - 删除所有点\n"
		"\t\tn - 开/光-夜晚模式\n" << endl;
}

Point2f point;
bool addRemovePt = false;

//--------------------------------【onMouse( )回调函数】------------------------------------
//		描述:鼠标操作回调
//-------------------------------------------------------------------------------------------------
static void onMouse(int event, int x, int y, int /*flags*/, void* /*param*/)
{
	//此句代码的OpenCV2版为:
	//if( event == CV_EVENT_LBUTTONDOWN )
	//此句代码的OpenCV3版为:
	if (event == EVENT_LBUTTONDOWN)
	{
		point = Point2f((float)x, (float)y);
		addRemovePt = true;
	}
}

//-----------------------------------【main( )函数】--------------------------------------------
//		描述:控制台应用程序的入口函数,我们的程序从这里开始
//-------------------------------------------------------------------------------------------------
int main(int argc, char** argv)
{
	help();

	VideoCapture cap;

	//此句代码的OpenCV2版为:
	//TermCriteria termcrit(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS, 20, 0.03);
	//此句代码的OpenCV3版为:
	TermCriteria termcrit(TermCriteria::MAX_ITER | TermCriteria::EPS, 20, 0.03);
	Size subPixWinSize(10, 10), winSize(31, 31);

	const int MAX_COUNT = 500;
	bool needToInit = false;
	bool nightMode = false;


	cap.open(0);

	if (!cap.isOpened())
	{
		cout << "Could not initialize capturing...\n";
		return 0;
	}

	namedWindow("LK Demo", 1);
	setMouseCallback("LK Demo", onMouse, 0);

	Mat gray, prevGray, image;
	vector
       
       
        
         points[2];

	for (;;)
	{
		Mat frame;
		cap >> frame;
		if (frame.empty())
			break;

		frame.copyTo(image);
		cvtColor(image, gray, COLOR_BGR2GRAY);

		if (nightMode)
			image = Scalar::all(0);

		if (needToInit)
		{
			// 自动初始化
			goodFeaturesToTrack(gray, points[1], MAX_COUNT, 0.01, 10, Mat(), 3, 0, 0.04);
			cornerSubPix(gray, points[1], subPixWinSize, Size(-1, -1), termcrit);
			addRemovePt = false;
		}
		else if (!points[0].empty())
		{
			vector
        
        
         
          status;
			vector
         
         
           err; if (prevGray.empty()) gray.copyTo(prevGray); calcOpticalFlowPyrLK(prevGray, gray, points[0], points[1], status, err, winSize, 3, termcrit, 0, 0.001); size_t i, k; for (i = k = 0; i < points[1].size(); i++) { if (addRemovePt) { if (norm(point - points[1][i]) <= 5) { addRemovePt = false; continue; } } if (!status[i]) continue; points[1][k++] = points[1][i]; circle(image, points[1][i], 3, Scalar(0, 255, 0), -1, 8); } points[1].resize(k); } if (addRemovePt && points[1].size() < (size_t)MAX_COUNT) { vector 
          
            tmp; tmp.push_back(point); //此句代码的OpenCV2版为: //cornerSubPix( gray, tmp, winSize, cvSize(-1,-1), termcrit); //此句代码的OpenCV3版为: cornerSubPix(gray, tmp, winSize, Size(-1, -1), termcrit); points[1].push_back(tmp[0]); addRemovePt = false; } needToInit = false; imshow("LK Demo", image); char c = (char)waitKey(10); if (c == 27) break; switch (c) { case 'r': needToInit = true; break; case 'c': points[0].clear(); points[1].clear(); break; case 'n': nightMode = !nightMode; break; } std::swap(points[1], points[0]); cv::swap(prevGray, gray); } return 0; } 
           
         
        
        
       
       
      
      
     
     
效果:



五、光流法检测运动目标

注:光流是目前运动图像分析的重要方法,由Gibso于1950年首先提出。光流用来指定时变图像中模式的运动速度,因为当物体在运动时,在图像上对应点的高度模式也在运动。这种图像高亮模式的表观运动就是光流。光流表达了图像的变化,由于它包含了目标运动的信息,因此可被观察者用来确定目标的运动情况。
代码:
//--------------------------------------【程序说明】-------------------------------------------
//		程序说明:支持向量机之SVM引导
//		测试所用操作系统: Windows 10 64bit
//		测试所用IDE版本:Visual Studio 2015(企业版)
//		开发测试所用OpenCV版本:	3.1 beta
//		2017年4月 Revised by 陈梓归
//------------------------------------------------------------------------------------------------


/************************************************************************
* Copyright(c) 2011  Yang Xian
* All rights reserved.
*
* File:	opticalFlow.cpp
* Brief: lk光流法做运动目标检测
* Version: 1.0
* Author: Yang Xian
* Email: xyang2011@sinano.ac.cn
* Date:	2011/11/18
* History:
************************************************************************/


//---------------------------------【头文件、命名空间包含部分】----------------------------
//		描述:包含程序所使用的头文件和命名空间
//-------------------------------------------------------------------------------------------------
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
        
        
#include 
        
        
          #include 
         
           using namespace std; using namespace cv; //-----------------------------------【全局函数声明】----------------------------------------- // 描述:声明全局函数 //------------------------------------------------------------------------------------------------- void tracking(Mat &frame, Mat &output); bool addNewPoints(); bool acceptTrackedPoint(int i); //-----------------------------------【全局变量声明】----------------------------------------- // 描述:声明全局变量 //------------------------------------------------------------------------------------------------- string window_name = "optical flow tracking"; Mat gray; // 当前图片 Mat gray_prev; // 预测图片 vector 
          
            points[2]; // point0为特征点的原来位置,point1为特征点的新位置 vector 
           
             initial; // 初始化跟踪点的位置 vector 
            
              features; // 检测的特征 int maxCount = 500; // 检测的最大特征数 double qLevel = 0.01; // 特征检测的等级 double minDist = 10.0; // 两特征点之间的最小距离 vector 
             
               status; // 跟踪特征的状态,特征的流发现为1,否则为0 vector 
              
                err; //--------------------------------【help( )函数】---------------------------------------------- // 描述:输出帮助信息 //------------------------------------------------------------------------------------------------- static void help() { //输出欢迎信息和OpenCV版本 cout << "\n\n\t\t\t 作者:陈梓归\n" << "\n\n\t\t\t 当前使用的OpenCV版本为:" << CV_VERSION << "\n\n ----------------------------------------------------------------------------"; } //-----------------------------------【main( )函数】-------------------------------------------- // 描述:控制台应用程序的入口函数,我们的程序从这里开始 //------------------------------------------------------------------------------------------------- int main() { Mat frame; Mat result; VideoCapture capture("1.avi"); help(); if (capture.isOpened()) // 摄像头读取文件开关 { while (true) { capture >> frame; if (!frame.empty()) { tracking(frame, result); } else { printf(" --(!) No captured frame -- Break!"); break; } int c = waitKey(50); if ((char)c == 27) { break; } } } return 0; } //------------------------------------------------------------------------------------------------- // function: tracking // brief: 跟踪 // parameter: frame 输入的视频帧 // output 有跟踪结果的视频帧 // return: void //------------------------------------------------------------------------------------------------- void tracking(Mat &frame, Mat &output) { //此句代码的OpenCV3版为: cvtColor(frame, gray, COLOR_BGR2GRAY); //此句代码的OpenCV2版为: //cvtColor(frame, gray, CV_BGR2GRAY); frame.copyTo(output); // 添加特征点 if (addNewPoints()) { goodFeaturesToTrack(gray, features, maxCount, qLevel, minDist); points[0].insert(points[0].end(), features.begin(), features.end()); initial.insert(initial.end(), features.begin(), features.end()); } if (gray_prev.empty()) { gray.copyTo(gray_prev); } // l-k光流法运动估计 calcOpticalFlowPyrLK(gray_prev, gray, points[0], points[1], status, err); // 去掉一些不好的特征点 int k = 0; for (size_t i = 0; i 
               
                 2); } 
                
               
              
             
            
           
          
        
       
       
      
      
     
     
    
    
效果:


六、彩色目标跟踪

注:根据鼠标框选区域的色度光谱来进行摄像头读入的视屏目标的跟踪。(主要采用Camshift算法)。
代码:
//--------------------------------------【程序说明】-------------------------------------------
//		程序说明:支持向量机之SVM引导
//		测试所用操作系统: Windows 10 64bit
//		测试所用IDE版本:Visual Studio 2015(企业版)
//		开发测试所用OpenCV版本:	3.1 beta
//		2017年4月 Revised by 陈梓归
//------------------------------------------------------------------------------------------------

//---------------------------------【头文件、命名空间包含部分】----------------------------
//		描述:包含程序所使用的头文件和命名空间
//-------------------------------------------------------------------------------------------------
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include 
    
    
     
     
#include 
     
     
      
      

using namespace cv;
using namespace std;



//-----------------------------------【全局变量声明】-----------------------------------------
//		描述:声明全局变量
//-------------------------------------------------------------------------------------------------
Mat image;
bool backprojMode = false;
bool selectObject = false;
int trackObject = 0;
bool showHist = true;
Point origin;
Rect selection;
int vmin = 10, vmax = 256, smin = 30;


//--------------------------------【onMouse( )回调函数】------------------------------------
//		描述:鼠标操作回调
//-------------------------------------------------------------------------------------------------
static void onMouse( int event, int x, int y, int, void* )
{
	if( selectObject )
	{
		selection.x = MIN(x, origin.x);
		selection.y = MIN(y, origin.y);
		selection.width = std::abs(x - origin.x);
		selection.height = std::abs(y - origin.y);

		selection &= Rect(0, 0, image.cols, image.rows);
	}

	switch( event )
	{
	//此句代码的OpenCV2版为:
	//case CV_EVENT_LBUTTONDOWN:
	//此句代码的OpenCV3版为:
	case EVENT_LBUTTONDOWN:
		origin = Point(x,y);
		selection = Rect(x,y,0,0);
		selectObject = true;
		break;
	//此句代码的OpenCV2版为:
	//case CV_EVENT_LBUTTONUP:
	//此句代码的OpenCV3版为:
	case EVENT_LBUTTONUP:
		selectObject = false;
		if( selection.width > 0 && selection.height > 0 )
			trackObject = -1;
		break;
	}
}

//--------------------------------【help( )函数】----------------------------------------------
//		描述:输出帮助信息
//-------------------------------------------------------------------------------------------------
static void ShowHelpText()
{
	cout <<"\n\n\t\t\t   作者:陈梓归\n"
		<<	"\n\n\t\t\t   当前使用的OpenCV版本为:" << CV_VERSION 
		<<"\n\n  ----------------------------------------------------------------------------" ;

	cout << "\n\n\t此Demo显示了基于均值漂移的追踪(tracking)技术\n"
		"\t请用鼠标框选一个有颜色的物体,对它进行追踪操作\n";

	cout << "\n\n\t操作说明: \n"
		"\t\t用鼠标框选对象来初始化跟踪\n"
		"\t\tESC - 退出程序\n"
		"\t\tc - 停止追踪\n"
		"\t\tb - 开/关-投影视图\n"
		"\t\th - 显示/隐藏-对象直方图\n"
		"\t\tp - 暂停视频\n";
}

const char* keys =
{
	"{1|  | 0 | camera number}"
};


//-----------------------------------【main( )函数】--------------------------------------------
//		描述:控制台应用程序的入口函数,我们的程序从这里开始
//-------------------------------------------------------------------------------------------------
int main( int argc, const char** argv )
{
	ShowHelpText();

	VideoCapture cap;
	Rect trackWindow;
	int hsize = 16;
	float hranges[] = {0,180};
	const float* phranges = hranges;

	cap.open(0);

	if( !cap.isOpened() )
	{
		cout << "不能初始化摄像头\n";
	}

	namedWindow( "Histogram", 0 );
	namedWindow( "CamShift Demo", 0 );
	setMouseCallback( "CamShift Demo", onMouse, 0 );
	createTrackbar( "Vmin", "CamShift Demo", &vmin, 256, 0 );
	createTrackbar( "Vmax", "CamShift Demo", &vmax, 256, 0 );
	createTrackbar( "Smin", "CamShift Demo", &smin, 256, 0 );

	Mat frame, hsv, hue, mask, hist, histimg = Mat::zeros(200, 320, CV_8UC3), backproj;
	bool paused = false;

	for(;;)
	{
		if( !paused )
		{
			cap >> frame;
			if( frame.empty() )
				break;
		}

		frame.copyTo(image);

		if( !paused )
		{
			cvtColor(image, hsv, COLOR_BGR2HSV);

			if( trackObject )
			{
				int _vmin = vmin, _vmax = vmax;

				inRange(hsv, Scalar(0, smin, MIN(_vmin,_vmax)),
					Scalar(180, 256, MAX(_vmin, _vmax)), mask);
				int ch[] = {0, 0};
				hue.create(hsv.size(), hsv.depth());
				mixChannels(&hsv, 1, &hue, 1, ch, 1);

				if( trackObject < 0 )
				{
					Mat roi(hue, selection), maskroi(mask, selection);
					calcHist(&roi, 1, 0, maskroi, hist, 1, &hsize, &phranges);
					//此句代码的OpenCV3版为:
					normalize(hist, hist, 0, 255, NORM_MINMAX);
					//此句代码的OpenCV2版为:
					//normalize(hist, hist, 0, 255, CV_MINMAX);

					trackWindow = selection;
					trackObject = 1;

					histimg = Scalar::all(0);
					int binW = histimg.cols / hsize;
					Mat buf(1, hsize, CV_8UC3);
					for( int i = 0; i < hsize; i++ )
						buf.at
      
      
       
       (i) = Vec3b(saturate_cast
       
       
        
        (i*180./hsize), 255, 255);

					//此句代码的OpenCV3版为:
					cvtColor(buf, buf, COLOR_HSV2BGR);
					//此句代码的OpenCV2版为:
					//cvtColor(buf, buf, CV_HSV2BGR);

					for( int i = 0; i < hsize; i++ )
					{
						int val = saturate_cast
        
        
          (hist.at 
         
           (i)*histimg.rows/255); rectangle( histimg, Point(i*binW,histimg.rows), Point((i+1)*binW,histimg.rows - val), Scalar(buf.at 
          
            (i)), -1, 8 ); } } calcBackProject(&hue, 1, 0, hist, backproj, &phranges); backproj &= mask; RotatedRect trackBox = CamShift(backproj, trackWindow, //此句代码的OpenCV3版为: TermCriteria( TermCriteria::EPS | TermCriteria::COUNT, 10, 1 )); //此句代码的OpenCV2版为: //TermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 )); if( trackWindow.area() <= 1 ) { int cols = backproj.cols, rows = backproj.rows, r = (MIN(cols, rows) + 5)/6; trackWindow = Rect(trackWindow.x - r, trackWindow.y - r, trackWindow.x + r, trackWindow.y + r) & Rect(0, 0, cols, rows); } if( backprojMode ) cvtColor( backproj, image, COLOR_GRAY2BGR ); //此句代码的OpenCV3版为: ellipse( image, trackBox, Scalar(0,0,255), 3, LINE_AA ); //此句代码的OpenCV2版为: //ellipse( image, trackBox, Scalar(0,0,255), 3, CV_AA ); } } else if( trackObject < 0 ) paused = false; if( selectObject && selection.width > 0 && selection.height > 0 ) { Mat roi(image, selection); bitwise_not(roi, roi); } imshow( "CamShift Demo", image ); imshow( "Histogram", histimg ); char c = (char)waitKey(10); if( c == 27 ) break; switch(c) { case 'b': backprojMode = !backprojMode; break; case 'c': trackObject = 0; histimg = Scalar::all(0); break; case 'h': showHist = !showHist; if( !showHist ) destroyWindow( "Histogram" ); else namedWindow( "Histogram", 1 ); break; case 'p': paused = !paused; break; default: ; } } return 0; } 
           
          
        
       
       
      
      
     
     
    
    
效果:


大家有没有更加有兴趣呢~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

种瓜大爷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值