在这种方式下,就可以为各种窗口大小执行快速的可变窗块相关计算。
// main.cpp // HaarFeature // Created by qianxin_dh on 14-9-13. // Copyright (c) 2014年 qianxin_dh. All rights reserved. #include "stdafx.h" #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include "HaarFeature.h" using namespace cv; using namespace std; const int featureNUM=192; int main() { Mat image=imread("lena.bmp"); //cvtColor(image,image,CV_RGB2GRAY); if (image.empty()) { cout<<"Load the image error!"<<endl; return -1; } vector<HaarFeature> m_features; //用于生成特征模板 float x[] = {0.2f, 0.4f, 0.6f, 0.8f}; float y[] = {0.2f, 0.4f, 0.6f, 0.8f}; float s[] = {0.2f, 0.4f}; for (int iy = 0; iy < 4; ++iy) { for (int ix = 0; ix < 4; ++ix) { for (int is = 0; is < 2; ++is) { FloatRect r(x[ix]-s[is]/2, y[iy]-s[is]/2, s[is], s[is]); //32种尺寸 for (int it = 0; it < 6; ++it) //这里主要实现6种hair特征,32*6=192种特征模板 { m_features.push_back(HaarFeature(r, it)); } } } } float m_feat; FloatRect rect(10,10,100,50); for(int i=0;i<featureNUM;i++){ m_feat= m_features[i].caluHf(image,rect); cout<<m_feat<<" "<<endl; } return 0; }
#include <opencv2/opencv.hpp> #include <vector> #include "RECT.h" using namespace cv; class HaarFeature { public: HaarFeature(FloatRect& bb, int type); ~HaarFeature(); float caluHf(Mat& _image,FloatRect& _rect); //计算haar特征值 private: float sum(Mat& _image,IntRect& _rect); private: FloatRect m_box; std::vector<FloatRect> m_rects; std::vector<float> m_weights; float m_factor; Mat _imageIntegral; };
#include "HaarFeature.h" #include <iostream> using namespace std; HaarFeature::HaarFeature(FloatRect& bb, int type) : m_box(bb) { assert(type < 6); //分别实现六种haar特征,可以参照文章开头时引用的图片进行对应 switch (type) { case 0: { m_rects.push_back(FloatRect(bb.XMin(), bb.YMin(), bb.Width(), bb.Height()/2)); m_rects.push_back(FloatRect(bb.XMin(), bb.YMin()+bb.Height()/2, bb.Width(), bb.Height()/2)); m_weights.push_back(1.f); m_weights.push_back(-1.f); m_factor = 255*1.f/2; break; } case 1: { m_rects.push_back(FloatRect(bb.XMin(), bb.YMin(), bb.Width()/2, bb.Height())); m_rects.push_back(FloatRect(bb.XMin()+bb.Width()/2, bb.YMin(), bb.Width()/2, bb.Height())); m_weights.push_back(1.f); m_weights.push_back(-1.f); m_factor = 255*1.f/2; break; } case 2: { m_rects.push_back(FloatRect(bb.XMin(), bb.YMin(), bb.Width()/3, bb.Height())); m_rects.push_back(FloatRect(bb.XMin()+bb.Width()/3, bb.YMin(), bb.Width()/3, bb.Height())); m_rects.push_back(FloatRect(bb.XMin()+2*bb.Width()/3, bb.YMin(), bb.Width()/3, bb.Height())); m_weights.push_back(1.f); m_weights.push_back(-2.f); m_weights.push_back(1.f); m_factor = 255*2.f/3; break; } case 3: { m_rects.push_back(FloatRect(bb.XMin(), bb.YMin(), bb.Width(), bb.Height()/3)); m_rects.push_back(FloatRect(bb.XMin(), bb.YMin()+bb.Height()/3, bb.Width(), bb.Height()/3)); m_rects.push_back(FloatRect(bb.XMin(), bb.YMin()+2*bb.Height()/3, bb.Width(), bb.Height()/3)); m_weights.push_back(1.f); m_weights.push_back(-2.f); m_weights.push_back(1.f); m_factor = 255*2.f/3; break; } case 4: { m_rects.push_back(FloatRect(bb.XMin(), bb.YMin(), bb.Width()/2, bb.Height()/2)); m_rects.push_back(FloatRect(bb.XMin()+bb.Width()/2, bb.YMin()+bb.Height()/2, bb.Width()/2, bb.Height()/2)); m_rects.push_back(FloatRect(bb.XMin(), bb.YMin()+bb.Height()/2, bb.Width()/2, bb.Height()/2)); m_rects.push_back(FloatRect(bb.XMin()+bb.Width()/2, bb.YMin(), bb.Width()/2, bb.Height()/2)); m_weights.push_back(1.f); m_weights.push_back(1.f); m_weights.push_back(-1.f); m_weights.push_back(-1.f); m_factor = 255*1.f/2; break; } case 5: { m_rects.push_back(FloatRect(bb.XMin(), bb.YMin(), bb.Width(), bb.Height())); m_rects.push_back(FloatRect(bb.XMin()+bb.Width()/4, bb.YMin()+bb.Height()/4, bb.Width()/2, bb.Height()/2)); m_weights.push_back(1.f); m_weights.push_back(-4.f); m_factor = 255*3.f/4; break; } } } HaarFeature::~HaarFeature() { } float HaarFeature::sum(Mat& _image,IntRect& _rect) { int xMin=_rect.XMin(); int yMin=_rect.YMin(); int xMax=_rect.XMin()+_rect.Width(); int yMax=_rect.YMin()+_rect.Height(); int tempValue=0; tempValue += _imageIntegral.at<int>(yMin, xMin) + _imageIntegral.at<int>(yMax, xMax) - _imageIntegral.at<int>(yMin, xMax) - _imageIntegral.at<int>(yMax, xMin); //cout<<weight<<endl; //cout<<tempValue<<endl; return tempValue; } float HaarFeature::caluHf(Mat& _image,FloatRect& _rect) { int value = 0; integral(_image, _imageIntegral, CV_32F); //cout<<_imageIntegral<<" "<<endl; for (int i = 0; i < (int)m_rects.size(); ++i) //m_rects.size()=2; { FloatRect& r = m_rects[i]; IntRect sampleRect((int)(_rect.XMin()+r.XMin()*_rect.Width()+0.5f), (int)(_rect.YMin()+r.YMin()*_rect.Height()+0.5f), (int)(r.Width()*_rect.Width()), (int)(r.Height()*_rect.Height())); value +=m_weights[i]*sum(_image,sampleRect); //sum函数返回的是积分图像对应的数值 } return value / (m_factor*(_rect.Area())*(m_box.Area())); }
#pragma once #include <iostream> #include <algorithm> template <typename T> class Rect { public: Rect() : m_xMin(0), m_yMin(0), m_width(0), m_height(0) { } Rect(T xMin, T yMin, T width, T height) : m_xMin(xMin), m_yMin(yMin), m_width(width), m_height(height) { } template <typename T2> Rect(const Rect<T2>& rOther) : m_xMin((T)rOther.XMin()), m_yMin((T)rOther.YMin()), m_width((T)rOther.Width()), m_height((T)rOther.Height()) { } inline T XMin() const { return m_xMin; } inline T YMin() const { return m_yMin; } inline T Width() const { return m_width; } inline T Height() const { return m_height; } inline T Area() const { return m_width * m_height; } private: T m_xMin; T m_yMin; T m_width; T m_height; }; typedef Rect<int> IntRect; typedef Rect<float> FloatRect;