简介
1.准备训练样本图片,包括正例及反例样本
2.生成样本描述文件
3.训练样本
4.目标识别
生成了xml接下来,开始识别了!!!
目标识别,也即利用前面训练出来的分类器文件(.xml文件)对图片中的物体进行识别,并在图中框出在该物体。由于逻辑比较简单,这里直接上代码:
// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <opencv2\opencv.hpp>
using namespace std;
using namespace cv;
void detect_and_draw(IplImage* img);
CvHaarClassifierCascade* cascade;
CvMemStorage* storage;
//CascadeClassifier cascade;与CvHaarClassifierCascade* 区别?
int _tmain(int argc, _TCHAR* argv[])
{
char* cascade_name = "F:\\objectmarker\\haarcascade_plate.xml"; //上文最终生成的xml文件命名为"haarcascade_plate.xml"
cascade = (CvHaarClassifierCascade*)cvLoad(cascade_name, 0, 0, 0); //加载xml文件
if (!cascade)
{
fprintf(stderr, "ERROR: Could not load classifier cascade\n");
system("pause");
return -1;
}
storage = cvCreateMemStorage(0);
cvNamedWindow("result", 1);
const char* filename = "test04.jpg";
IplImage* image = cvLoadImage(filename, 1);
if (image)
{
detect_and_draw(image); //函数见下方
cvWaitKey(0);
cvReleaseImage(&image);//因为使用了IplImage,所以要释放资源
}
cvDestroyWindow("result");
return 0;
}
void detect_and_draw(IplImage* img)
{
double scale = 1.2;
static CvScalar colors[] = {
{ { 0, 0, 255 } }, { { 0, 128, 255 } }, { { 0, 255, 255 } }, { { 0, 255, 0 } },
{ { 255, 128, 0 } }, { { 255, 255, 0 } }, { { 255, 0, 0 } }, { { 255, 0, 255 } }
};//Just some pretty colors to draw with
//Image Preparation
//
IplImage* gray = cvCreateImage(cvSize(img->width, img->height), 8, 1);
IplImage* small_img = cvCreateImage(cvSize(cvRound(img->width / scale), cvRound(img->height / scale)), 8, 1);
cvCvtColor(img, gray, CV_BGR2GRAY);
cvResize(gray, small_img, CV_INTER_LINEAR);
cvEqualizeHist(small_img, small_img); //直方图均衡
//Detect objects if any
//
cvClearMemStorage(storage);
double t = (double)cvGetTickCount();//计时开始
CvSeq* objects = cvHaarDetectObjects(small_img,
cascade,
storage,
1.1,
2,
0/*CV_HAAR_DO_CANNY_PRUNING*/,
cvSize(40, 20));
t = (double)cvGetTickCount() - t;//计时结束
printf("detection time = %gms\n", t / ((double)cvGetTickFrequency()*1000.));
//Loop through found objects and draw boxes around them
for (int i = 0; i<(objects ? objects->total : 0); ++i)
{
CvRect* r = (CvRect*)cvGetSeqElem(objects, i);//draw Rectangle
cvRectangle(img, cvPoint(r->x*scale, r->y*scale), cvPoint((r->x + r->width)*scale, (r->y + r->height)*scale), colors[i % 8]);//choose color
}
for (int i = 0; i < (objects ? objects->total : 0); i++)
{
CvRect* r = (CvRect*)cvGetSeqElem(objects, i);//draw radius
CvPoint center;
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);
cvCircle(img, center, radius, colors[i % 8], 3, 8, 0);
}
cvShowImage("result", img);
cvReleaseImage(&gray);
cvReleaseImage(&small_img);
}
OpenCV2圆形detection:
#include "stdafx.h"
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\objdetect\objdetect.hpp>
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
void detectAndDisplay(Mat frame);
//--------------------------------【全局变量声明】----------------------------------------------
// 描述:声明全局变量
//-------------------------------------------------------------------------------------------------
//注意,需要把"F:\\objectmarker\\haarcascade_plate.xml"这个文件复制到工程路径下
String face_cascade_name = "F:\\objectmarker\\haarcascade_plate.xml";
CascadeClassifier face_cascade;
string window_name = "Capture - Plate detection";
RNG rng(12345);
//--------------------------------【help( )函数】----------------------------------------------
// 描述:输出帮助信息
//-------------------------------------------------------------------------------------------------
static void ShowHelpText()
{
//输出欢迎信息和OpenCV版本
cout << "\n\n\t\t\t非常感谢购买《OpenCV3编程入门》一书!\n"
<< "\n\n\t\t\t此为本书OpenCV2版的第11个配套示例程序\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; };
//-- 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(1);
if ((char)c == 'c') { break; }
}
}
return 0;
}
void detectAndDisplay(Mat frame)
{
std::vector<Rect> faces;
Mat frame_gray;
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
equalizeHist(frame_gray, frame_gray);
//-- 车牌检测
face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(40, 20));
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]);
}
//-- 显示最终效果图
imshow(window_name, frame);
}
OpenCV2方形detection:
#include "stdafx.h"
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\objdetect\objdetect.hpp>
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
void detectAndDisplay(Mat frame);
//--------------------------------【全局变量声明】----------------------------------------------
// 描述:声明全局变量
//-------------------------------------------------------------------------------------------------
//注意,需要把"F:\\objectmarker\\haarcascade_plate.xml"这个文件复制到工程路径下
String face_cascade_name = "F:\\objectmarker\\haarcascade_plate.xml";
CascadeClassifier face_cascade;
string window_name = "Capture - Plate detection";
RNG rng(12345);
//--------------------------------【help( )函数】----------------------------------------------
// 描述:输出帮助信息
//-------------------------------------------------------------------------------------------------
static void ShowHelpText()
{
//输出欢迎信息和OpenCV版本
cout << "\n\n\t\t\t非常感谢购买《OpenCV3编程入门》一书!\n"
<< "\n\n\t\t\t此为本书OpenCV2版的第11个配套示例程序\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; };
//-- 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(1);
if ((char)c == 'c') { break; }
}
}
return 0;
}
void detectAndDisplay(Mat frame)
{
std::vector<Rect> faces;
Mat frame_gray;
Rect select;//声明矩形
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
equalizeHist(frame_gray, frame_gray);
//-- 车牌检测
face_cascade.detectMultiScale(frame_gray, faces, 2.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(40, 20));
for (size_t i = 0; i < faces.size(); i++)
{
select.x = faces[i].x;
select.y = faces[i].y;
select.width = faces[i].width;
select.height = faces[i].height;
rectangle(frame, select, Scalar(255, 0, 255), 2, 8, 0);//用矩形画矩形窗
Mat faceROI = frame_gray(faces[i]);
}
//-- 显示最终效果图
imshow(window_name, frame);
}
参考
【1】对OpenCV中Haar特征CvHaarClassifierCascade等结构理解 - PAK FA T-50 - 博客园
http://www.cnblogs.com/pakfahome/p/3611303.html
【2】训练自己haar-like特征分类器并识别物体(2) - 罗索实验室
http://www.rosoo.net/a/201504/17273.html
【3】如何利用OpenCV自带的haar training程序训练分类器 - 计算机视觉小菜鸟的专栏 - 优快云博客
http://blog.youkuaiyun.com/carson2005/article/details/8171571
【4】使用Adaboost训练手掌检测器 - xbcReal的博客 - 优快云博客
http://blog.youkuaiyun.com/xbcreal/article/details/77994719