【haartraining】正样本 只框头部 (I)

这个版本的头部可以框出,但是好像不是很清晰,最好能改在原尺寸上。。。

后面改进后好一些了。。


//opencv2.0风格

//本程序有几个可调值
//1.背景更新 学习率 learningRate
//2.去掉小面积阈值 area_threshold

#include "cv.h"
#include "highgui.h"

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>

#include <iostream>
#include <string>
#include <cstdio>

using namespace std;
using namespace cv;


//函数声明

void findBoundary(Rect r,Point &a,Point &c);//找到贴合矩形框
void biggerRect(Point &a,Point &c,Mat img);  //将矩形框适当放大
void hugeRect(Point &a,Point &c,Mat img);   //如果比例缩小太大,直接将矩形巨大化
void pedDetection(Mat& img);//行人检测
void saveImg(Mat img);
void detectAndDraw( Mat& img,
	CascadeClassifier& cascade,
	double scale);


//String cascadeName = "./haarcascades/haarcascade_frontalface_alt2.xml";//人脸的训练数据
String cascadeName = "./cascades.xml";//高密度人头检测训练数据

char input_name[50];
char outFolder[50];
char countChar[10000];
char tmp[50];
int cnt=0;


//主函数
int main()
{
	//输入
	cout<<"please input the src video :"<<endl;
	cin>>input_name;
	cout<<"please input the output folder :"<<endl;
	cin>>outFolder;

	//可调参数
	//char* input_name = "0012.mp4";
	double fScale = 0.5;      //缩放倍数
	double learningRate=0.5;    // 控制背景累积学习的速率
	double area_threshold = 30;  //区域面积大小阈值
	int nThreshold=30; //二值化阈值



	CascadeClassifier cascade;//创建级联分类器对象
	Mat frame_ori;		//每一帧原图像,绝不处理
	Mat frame;		//每一帧图像处理
	Mat gray;		//frame转成的灰度图
	Mat frame_copy_8U;	//copy过来的8U图像
	Mat frame_copy;
	Mat img1;		//差分输出
	Mat outBinary; //二值图输出
	int lastRectHeight=0; //一般都是矩形的高度变化,存储上一个矩形高度


	//从指定的文件目录中加载级联分类器
	if( !cascade.load( cascadeName ) )
	{
		cerr << "ERROR: Could not load classifier cascade" << endl;
		return 0;
	}


	//从视频读入
	VideoCapture capture(input_name);

	if(capture.isOpened()/*capture*/)	//读取文件开关
	{
		//对每一帧做处理

		for(;;)
		{

			//单帧处理

			capture >> frame_ori;
			if(!frame_ori.empty())//如果捕捉到了
			{
				cout<<"\n\n***************New Start********************"<<endl;


				//将原图像缩放
				//resize(frame_ori,frame,Size(frame_ori.cols * fScale,frame_ori.rows * fScale),0,0,CV_INTER_LINEAR);
				frame=frame_ori;


				//送去行人检测
				//pedDetection(frame);

				//frame->gray 单通道灰度图
				cvtColor(frame, gray, CV_BGR2GRAY);

				//进行处理
				if (frame_copy.empty())
				{
					//记录第一帧 gray->frame_copy
					gray.convertTo(frame_copy, CV_32F);
				}

				frame_copy.convertTo(frame_copy_8U, CV_8U);
				//差分
				absdiff(frame_copy_8U, gray, img1);


				//二值化
				threshold(img1, outBinary, nThreshold, 255, THRESH_BINARY);

				accumulateWeighted(gray, frame_copy,learningRate,outBinary);


				//加一个中值滤波,会减少不少误差
				cv::medianBlur(outBinary, outBinary,5);


				//初始化边界极值点坐标
				Point A,C;
				A.x=0x7fffffff; A.y=0x7fffffff;
				C.x=0; C.y=0;



				//轮廓检测
				vector<vector<Point>> _contours;//储存所有轮廓
				vector<Vec4i>hierarchy;

				Mat imageROI;;
				cv::findContours( outBinary, _contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

				for(size_t i = 0; i< _contours.size(); ++i)
				{
					//遍历所有轮廓

					//计算轮廓面积
					double contArea =  fabs(contourArea(_contours[i]));

					//去除较小面积的轮廓
					if( contArea < area_threshold)
						continue;

					//获得外接矩形
					Rect r0 = boundingRect(Mat(_contours[i]));


					//找出最边界的点
					findBoundary(r0,A,C);


					//实时画出每个矩形
					rectangle(outBinary,r0,cvScalar(255,255,255),1,8,0);
				}

				biggerRect(A,C,frame);

				cout<<"A.x == "<<A.x<<endl;
				cout<<"A.y == "<<A.y<<endl;
				cout<<"C.x == "<<C.x<<endl;
				cout<<"C.y == "<<C.y<<endl;

				int a=A.x,b=A.y,c=C.x-A.x,d=C.y-A.y;

				//矩形框不存在,检测不了
				if (c<=0 || d<=0)
				{
					//cout<<"弹回去"<<endl;

					imshow("src", frame);
					imshow("outBinary", outBinary);

					cvWaitKey(1);
					continue;
				}

				if(d<lastRectHeight*0.7)
					hugeRect(A,C,frame);

				//得到要识别的矩形框
				Rect r=Rect(a,b,c,d);

				//画出一个大的框架
				rectangle(outBinary,r,cvScalar(255,255,255),1,8,0);
				rectangle(frame,r,cvScalar(255,255,255),1,8,0);

				/*cout<<"r.x "<<r.x<<endl;
				cout<<"r.y "<<r.y<<endl;
				cout<<"r.width "<<r.width<<endl;
				cout<<"r.height "<<r.height<<endl;
				cout<<"frame.cols "<<frame.cols<<endl;
				cout<<"frame.rows "<<frame.rows<<endl;*/

				//截取frame中的r矩形框大小
				Mat src=frame(r);

				//送去行人检测
				//pedDetection(src);

				//送去人脸检测			
				detectAndDraw(src,cascade, 1.3);

				imshow("src", frame);
				imshow("outBinary", outBinary);

				lastRectHeight=d;
			}

			else
			{ 
				printf(" --(!) No captured frame -- Break!");
				break;
			}

			//10ms中按任意键进入此if块
			if( cvWaitKey( 10 ) >= 0 )
				break;
		}
	}

	return 0;
}


//找一帧中所有矩形的边界四点
void findBoundary(Rect r,Point &a,Point &c)
{
	//a是矩形原点
	//c是原点对角线点

	//r.x还在a.x的左边
	if (r.x < a.x)
		a.x = r.x;

	//r.y 还在 a.y 上面
	if(r.y < a.y)
		a.y = r.y;

	//r.x+r.width 还在c.x的右边
	if ((r.x+r.width) > c.x)
		c.x = r.x+r.width;

	//(r.y+r.height) 还在 c.y 下面
	if((r.y+r.height) > c.y)
		c.y = r.y+r.height;
}


void biggerRect(Point &a,Point &c,Mat img)
{
	if (c.x-a.x<0 || c.y-a.y<0)
		return;

	a.x -= 30;
	a.y -= 100;
	c.x += 30;
	c.y += 100;

	if(a.x<0)
		a.x=0;

	if(a.y<0)
		a.y=0;

	if(c.x>img.cols)
		c.x=img.cols;

	if(c.y>img.rows)
		c.y=img.rows;
}


void hugeRect(Point &a,Point &c,Mat img)
{
	a.y = 0;
	c.y = img.rows;
}



//行人检测
void pedDetection(Mat& image)
{
	// 1. 定义HOG对象
	cv::HOGDescriptor hog; // 采用默认参数 64*128 (像素为单位)


	// 2. 设置SVM分类器
	hog.setSVMDetector(cv::HOGDescriptor::getDefaultPeopleDetector());   // 采用已经训练好的行人检测分类器

	// 3. 在测试图像上检测行人区域
	std::vector<cv::Rect> regions;
	hog.detectMultiScale(image, regions, 0, cv::Size(8,8), cv::Size(32,32), 1.05, 1);

	if(regions.size()>0)
	{
		printf("是一个人!!!!!!!!!!!!!!!!\n");
		printf("是一个人!!!!!!!!!!!!!!!!\n");
		printf("是一个人!!!!!!!!!!!!!!!!\n");
		printf("是一个人!!!!!!!!!!!!!!!!\n");
		printf("是一个人!!!!!!!!!!!!!!!!\n");
		printf("是一个人!!!!!!!!!!!!!!!!\n");
	}
	

	// 显示
	for (size_t i = 0; i < regions.size(); i++)
	{
		cv::rectangle(image, regions[i], cv::Scalar(0,0,255), 2);
	} 

	cv::imshow("hog", image);
}



//人脸检测并画出
void detectAndDraw( Mat& img,
	CascadeClassifier& cascade,
	double scale)
{

	int i = 0;
	double t = 0;
	vector<Rect> faces;
	const static Scalar colors[] =  { CV_RGB(0,0,255),
		CV_RGB(0,128,255),
		CV_RGB(0,255,255),
		CV_RGB(0,255,0),
		CV_RGB(255,128,0),
		CV_RGB(255,255,0),
		CV_RGB(255,0,0),
		CV_RGB(255,0,255)} ;//用不同的颜色表示不同的人脸

	Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );//将图片缩小,加快检测速度

	cvtColor( img, gray, CV_BGR2GRAY );//因为用的是类haar特征,所以都是基于灰度图像的,这里要转换成灰度图像
	resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );//将尺寸缩小到1/scale,用线性插值
	equalizeHist( smallImg, smallImg );//直方图均衡

	t = (double)cvGetTickCount();//用来计算算法执行时间


	//检测人脸
	//detectMultiScale函数中smallImg表示的是要检测的输入图像为smallImg,faces表示检测到的人脸目标序列,1.1表示
	//每次图像尺寸减小的比例为1.1,2表示每一个目标至少要被检测到3次才算是真的目标(因为周围的像素和不同的窗口大
	//小都可以检测到人脸),CV_HAAR_SCALE_IMAGE表示不是缩放分类器来检测,而是缩放图像,Size(30, 30)为目标的
	//最小最大尺寸
	cascade.detectMultiScale( smallImg, faces,
		1.1, 2, 0
		//|CV_HAAR_FIND_BIGGEST_OBJECT
		//|CV_HAAR_DO_ROUGH_SEARCH
		|CV_HAAR_SCALE_IMAGE
		,
		Size(30, 30) );

	t = (double)cvGetTickCount() - t;//相减为算法执行的时间
	printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) );

	for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
	{
		Mat smallImgROI;
		vector<Rect> nestedObjects;
		Point center;
		Scalar color = colors[i%8];
		int radius;
		center.x = cvRound((r->x + r->width*0.5)*scale);//还原成原来的大小
		center.y = cvRound((r->y + r->height*0.5)*scale);
		radius = cvRound((r->width + r->height)*0.25*scale);
		circle( img, center, radius, color, 3, 8, 0 );

		smallImgROI = smallImg(*r);

		saveImg(smallImgROI);
	}
}


void saveImg(Mat img)
{
	strcpy(countChar,outFolder);
	strcat(countChar,"\\");
	//cout<<countChar<<endl;
	cout<<"有了有了!!!!!!!!"<<endl;
	cnt++;
	itoa(cnt,tmp,10);
	strcat(tmp,".jpg");
	strcat(countChar,tmp);
	//cout<<countChar<<endl;
	imwrite(countChar,img);
}

改进后:

//opencv2.0风格

//本程序有几个可调值
//1.背景更新 学习率 learningRate
//2.去掉小面积阈值 area_threshold

#include "cv.h"
#include "highgui.h"

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>

#include <iostream>
#include <string>
#include <cstdio>

using namespace std;
using namespace cv;


//函数声明

void findBoundary(Rect r,Point &a,Point &c);//找到贴合矩形框
void biggerRect(Point &a,Point &c,Mat img);  //将矩形框适当放大
void hugeRect(Point &a,Point &c,Mat img);   //如果比例缩小太大,直接将矩形巨大化
void pedDetection(Mat& img);//行人检测
void saveImg(Mat img);
void detectAndDraw( Mat& img,
	CascadeClassifier& cascade,
	double scale);


//String cascadeName = "./haarcascades/haarcascade_frontalface_alt2.xml";//人脸的训练数据
String cascadeName = "./cascades.xml";//高密度人头检测训练数据

char input_name[50];
char outFolder[50];
char countChar[10000];
char tmp[50];
int cnt=0;


//主函数
int main()
{
	//输入
	cout<<"please input the src video :"<<endl;
	cin>>input_name;
	cout<<"please input the output folder :"<<endl;
	cin>>outFolder;

	//可调参数
	//char* input_name = "0012.mp4";
	double fScale = 0.5;      //缩放倍数
	double learningRate=0.5;    // 控制背景累积学习的速率
	double area_threshold = 30;  //区域面积大小阈值
	int nThreshold=30; //二值化阈值



	CascadeClassifier cascade;//创建级联分类器对象
	Mat frame_ori;		//每一帧原图像,绝不处理
	Mat frame;		//每一帧图像处理
	Mat gray;		//frame转成的灰度图
	Mat frame_copy_8U;	//copy过来的8U图像
	Mat frame_copy;
	Mat img1;		//差分输出
	Mat outBinary; //二值图输出
	int lastRectHeight=0; //一般都是矩形的高度变化,存储上一个矩形高度


	//从指定的文件目录中加载级联分类器
	if( !cascade.load( cascadeName ) )
	{
		cerr << "ERROR: Could not load classifier cascade" << endl;
		return 0;
	}


	//从视频读入
	VideoCapture capture(input_name);

	if(capture.isOpened()/*capture*/)	//读取文件开关
	{
		//对每一帧做处理

		for(;;)
		{

			//单帧处理

			capture >> frame_ori;
			if(!frame_ori.empty())//如果捕捉到了
			{
				cout<<"\n\n***************New Start********************"<<endl;


				//将原图像缩放
				//resize(frame_ori,frame,Size(frame_ori.cols * fScale,frame_ori.rows * fScale),0,0,CV_INTER_LINEAR);
				frame=frame_ori;


				//送去行人检测
				//pedDetection(frame);

				//frame->gray 单通道灰度图
				cvtColor(frame, gray, CV_BGR2GRAY);

				//进行处理
				if (frame_copy.empty())
				{
					//记录第一帧 gray->frame_copy
					gray.convertTo(frame_copy, CV_32F);
				}

				frame_copy.convertTo(frame_copy_8U, CV_8U);
				//差分
				absdiff(frame_copy_8U, gray, img1);


				//二值化
				threshold(img1, outBinary, nThreshold, 255, THRESH_BINARY);

				accumulateWeighted(gray, frame_copy,learningRate,outBinary);


				//加一个中值滤波,会减少不少误差
				cv::medianBlur(outBinary, outBinary,5);


				//初始化边界极值点坐标
				Point A,C;
				A.x=0x7fffffff; A.y=0x7fffffff;
				C.x=0; C.y=0;



				//轮廓检测
				vector<vector<Point>> _contours;//储存所有轮廓
				vector<Vec4i>hierarchy;

				Mat imageROI;;
				cv::findContours( outBinary, _contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

				for(size_t i = 0; i< _contours.size(); ++i)
				{
					//遍历所有轮廓

					//计算轮廓面积
					double contArea =  fabs(contourArea(_contours[i]));

					//去除较小面积的轮廓
					if( contArea < area_threshold)
						continue;

					//获得外接矩形
					Rect r0 = boundingRect(Mat(_contours[i]));


					//找出最边界的点
					findBoundary(r0,A,C);


					//实时画出每个矩形
					rectangle(outBinary,r0,cvScalar(255,255,255),1,8,0);
				}

				biggerRect(A,C,frame);

				cout<<"A.x == "<<A.x<<endl;
				cout<<"A.y == "<<A.y<<endl;
				cout<<"C.x == "<<C.x<<endl;
				cout<<"C.y == "<<C.y<<endl;

				int a=A.x,b=A.y,c=C.x-A.x,d=C.y-A.y;

				//矩形框不存在,检测不了
				if (c<=0 || d<=0)
				{
					//cout<<"弹回去"<<endl;

					imshow("src", frame);
					imshow("outBinary", outBinary);

					cvWaitKey(1);
					continue;
				}

				if(d<lastRectHeight*0.7)
					hugeRect(A,C,frame);

				//得到要识别的矩形框
				Rect r=Rect(a,b,c,d);

				//画出一个大的框架
				rectangle(outBinary,r,cvScalar(255,255,255),1,8,0);
				rectangle(frame,r,cvScalar(255,255,255),1,8,0);

				/*cout<<"r.x "<<r.x<<endl;
				cout<<"r.y "<<r.y<<endl;
				cout<<"r.width "<<r.width<<endl;
				cout<<"r.height "<<r.height<<endl;
				cout<<"frame.cols "<<frame.cols<<endl;
				cout<<"frame.rows "<<frame.rows<<endl;*/

				//截取frame中的r矩形框大小
				Mat src=frame(r);

				//送去行人检测
				//pedDetection(src);

				//送去人脸检测			
				detectAndDraw(src,cascade, 1.0);

				imshow("src", frame);
				imshow("outBinary", outBinary);

				lastRectHeight=d;
			}

			else
			{ 
				printf(" --(!) No captured frame -- Break!");
				break;
			}

			//10ms中按任意键进入此if块
			if( cvWaitKey( 10 ) >= 0 )
				break;
		}
	}

	return 0;
}


//找一帧中所有矩形的边界四点
void findBoundary(Rect r,Point &a,Point &c)
{
	//a是矩形原点
	//c是原点对角线点

	//r.x还在a.x的左边
	if (r.x < a.x)
		a.x = r.x;

	//r.y 还在 a.y 上面
	if(r.y < a.y)
		a.y = r.y;

	//r.x+r.width 还在c.x的右边
	if ((r.x+r.width) > c.x)
		c.x = r.x+r.width;

	//(r.y+r.height) 还在 c.y 下面
	if((r.y+r.height) > c.y)
		c.y = r.y+r.height;
}


void biggerRect(Point &a,Point &c,Mat img)
{
	if (c.x-a.x<0 || c.y-a.y<0)
		return;

	a.x -= 30;
	a.y -= 100;
	c.x += 30;
	c.y += 100;

	if(a.x<0)
		a.x=0;

	if(a.y<0)
		a.y=0;

	if(c.x>img.cols)
		c.x=img.cols;

	if(c.y>img.rows)
		c.y=img.rows;
}


void hugeRect(Point &a,Point &c,Mat img)
{
	a.y = 0;
	c.y = img.rows;
}



//行人检测
void pedDetection(Mat& image)
{
	// 1. 定义HOG对象
	cv::HOGDescriptor hog; // 采用默认参数 64*128 (像素为单位)


	// 2. 设置SVM分类器
	hog.setSVMDetector(cv::HOGDescriptor::getDefaultPeopleDetector());   // 采用已经训练好的行人检测分类器

	// 3. 在测试图像上检测行人区域
	std::vector<cv::Rect> regions;
	hog.detectMultiScale(image, regions, 0, cv::Size(8,8), cv::Size(32,32), 1.05, 1);

	if(regions.size()>0)
	{
		printf("是一个人!!!!!!!!!!!!!!!!\n");
		printf("是一个人!!!!!!!!!!!!!!!!\n");
		printf("是一个人!!!!!!!!!!!!!!!!\n");
		printf("是一个人!!!!!!!!!!!!!!!!\n");
		printf("是一个人!!!!!!!!!!!!!!!!\n");
		printf("是一个人!!!!!!!!!!!!!!!!\n");
	}
	

	// 显示
	for (size_t i = 0; i < regions.size(); i++)
	{
		cv::rectangle(image, regions[i], cv::Scalar(0,0,255), 2);
	} 

	cv::imshow("hog", image);
}



//人脸检测并画出
void detectAndDraw( Mat& img,
	CascadeClassifier& cascade,
	double scale)
{
	Mat img_ori=img.clone();

	int i = 0;
	double t = 0;
	vector<Rect> faces;
	const static Scalar colors[] =  { CV_RGB(0,0,255),
		CV_RGB(0,128,255),
		CV_RGB(0,255,255),
		CV_RGB(0,255,0),
		CV_RGB(255,128,0),
		CV_RGB(255,255,0),
		CV_RGB(255,0,0),
		CV_RGB(255,0,255)} ;//用不同的颜色表示不同的人脸

	Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );//将图片缩小,加快检测速度

	cvtColor( img, gray, CV_BGR2GRAY );//因为用的是类haar特征,所以都是基于灰度图像的,这里要转换成灰度图像
	resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );//将尺寸缩小到1/scale,用线性插值
	equalizeHist( smallImg, smallImg );//直方图均衡

	t = (double)cvGetTickCount();//用来计算算法执行时间


	//检测人脸
	//detectMultiScale函数中smallImg表示的是要检测的输入图像为smallImg,faces表示检测到的人脸目标序列,1.1表示
	//每次图像尺寸减小的比例为1.1,2表示每一个目标至少要被检测到3次才算是真的目标(因为周围的像素和不同的窗口大
	//小都可以检测到人脸),CV_HAAR_SCALE_IMAGE表示不是缩放分类器来检测,而是缩放图像,Size(30, 30)为目标的
	//最小最大尺寸
	cascade.detectMultiScale( smallImg, faces,
		1.1, 2, 0
		//|CV_HAAR_FIND_BIGGEST_OBJECT
		//|CV_HAAR_DO_ROUGH_SEARCH
		|CV_HAAR_SCALE_IMAGE
		,
		Size(30, 30) );

	t = (double)cvGetTickCount() - t;//相减为算法执行的时间
	printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) );

	for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
	{
		Mat smallImgROI;
		vector<Rect> nestedObjects;
		Point center;
		Scalar color = colors[i%8];
		int radius;
		center.x = cvRound((r->x + r->width*0.5)*scale);//还原成原来的大小
		center.y = cvRound((r->y + r->height*0.5)*scale);
		radius = cvRound((r->width + r->height)*0.25*scale);
		circle( img, center, radius, color, 3, 8, 0 );

		smallImgROI = img_ori(*r);

		saveImg(smallImgROI);
	}
}


void saveImg(Mat img)
{
	strcpy(countChar,outFolder);
	strcat(countChar,"\\");
	//cout<<countChar<<endl;
	cout<<"有了有了!!!!!!!!"<<endl;
	cnt++;
	itoa(cnt,tmp,10);
	strcat(tmp,".jpg");
	strcat(countChar,tmp);
	//cout<<countChar<<endl;
	imwrite(countChar,img);
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值