//识别验证
int MyClassOfTrain::recognize_object() {
cv::Mat src = cv::imread("./TrainData/测试集/1.bmp");
if (src.empty()) {
return -1;
}
time_t t_start = time(0);
char pic_name[64];
strftime(pic_name, sizeof(pic_name), "%Y-%m-%d %H-%M-%S", localtime(&t_start)); //年-月-日 时-分-秒
std::string temp_name = pic_name;
std::string picPath = "./TrainData/测试集/" + temp_name + ".jpg";
std::string picPathbmp = "./TrainData/测试集/" + temp_name + ".bmp";
cv::imwrite(picPathbmp, src);
remove("./TrainData/测试集/1.bmp");
//cv::namedWindow("src", cv::WINDOW_FREERATIO);
//cv::imshow("src", src);
//cv::Mat dst1;
//AutoGammaCorrection(src, dst1);
//cv::namedWindow("dst1", cv::WINDOW_FREERATIO);
//cv::imshow("dst1", dst1);
//cv::waitKey(0);
//dst1.copyTo(src);
//cv::namedWindow("2", cv::WINDOW_FREERATIO);
//cv::imshow("2", src);
//cv::waitKey(0);
cv::Ptr<cv::ml::SVM>model = cv::ml::SVM::create();
model = cv::Algorithm::load<cv::ml::SVM>("./TrainData/SVM_HOG.xml");
if (model->empty()) {
return -2;
}
cv::HOGDescriptor Myhog;
cv::Mat svecsmat = model->getSupportVectors();
int DescriptorDim = model->getVarCount();
int svdim = model->getVarCount();
int numofsv = svecsmat.rows;
cv::Mat alphamat = cv::Mat::zeros(numofsv, svdim, CV_32F);
cv::Mat svindex = cv::Mat::zeros(1, numofsv, CV_64F);
float rho = model->getDecisionFunction(0, alphamat, svindex);
cv::Mat Result;
alphamat.convertTo(alphamat, CV_32F);
Result = -1 * alphamat * svecsmat;
std::vector<float> vec;
for (int i = 0; i < svdim; ++i) {
vec.push_back(Result.at<float>(0, i));
}
vec.push_back(rho);//
Myhog.setSVMDetector(vec);
std::vector<cv::Rect> found, found_filtered;//矩形框数组
//Myhog.detectMultiScale(src, found, 0, cv::Size(8, 8), cv::Size(8, 8), 1.051, 30.0);//对图片进行多尺度检测 src, found, 0, cv::Size(16, 16), cv::Size(32, 32), 2.5, 20
Myhog.detectMultiScale(src, found, 0, cv::Size(16, 16), cv::Size(16, 16), 1.051, 3);//4相对3检测不到且变慢。变大3减少误分类。 5最终红色木块参数
//Myhog.detectMultiScale(src, found, 0, cv::Size(32, 32), cv::Size(32, 32), 1.05, 30);
if (found.size() == 0) {
//Myhog.detectMultiScale(src, found, 0, cv::Size(8, 8), cv::Size(8, 8), 1.05, 2);//检测不到木块cv::Size(8, 8)太小
Myhog.detectMultiScale(src, found, 0, cv::Size(8, 8), cv::Size(8, 8), 1.05, 2);//对图片进行多尺度检测 src, found, 0, cv::Size(8, 8), cv::Size(8, 8), 1.05, 2
}
//找出所有没有嵌套的矩形框r,并放入found_filtered中,如果有嵌套的话,则取外面最大的那个矩形框放入found_filtered中
for (int i = 0; i < found.size(); i++) {
if (0 > found[i].width || found[i].width > 4000)
continue;
cv::Rect r = found[i];
int j = 0;
for (; j < found.size(); j++)
if (j != i && (r & found[j]) == r)
break;
if (j == found.size())
found_filtered.push_back(r);
}
for (int i = 0; i < found_filtered.size(); i++) {
cv::Rect r = found_filtered[i];
rectangle(src, r.tl(), r.br(), cv::Scalar(255), 7);
}
//cv::imwrite("./TrainData/测试集/1.jpg", src);
cv::namedWindow("oriImg", cv::WINDOW_FREERATIO);
cv::imwrite(picPath, src);
cv::imshow("oriImg", src);
cv::waitKey(0);
cv::destroyAllWindows();
return 1;
}
构造函数:
cv::HOGDescriptor hog(cv::Size(576, 576), cv::Size(192, 192), cv::Size(96, 96), cv::Size(96, 96), 9);//HOG检测器,用来计算HOG描述子的,依次为检测窗口,块尺寸,块步长,cell尺寸,直方图个数
/**@brief Creates the HOG descriptor and detector with default params.
aqual to HOGDescriptor(Size(64,128), Size(16,16), Size(8,8), Size(8,8), 9 )
*/
CV_WRAP HOGDescriptor() : winSize(192,192), blockSize(64,64), blockStride(32,32),
cellSize(32,32), nbins(9), derivAperture(1), winSigma(-1),
histogramNormType(HOGDescriptor::L2Hys), L2HysThreshold(0.2), gammaCorrection(true),
free_coef(-1.f), nlevels(HOGDescriptor::DEFAULT_NLEVELS), signedGradient(false)
{}
/** @overload
@param _winSize sets winSize with given value.
@param _blockSize sets blockSize with given value.
@param _blockStride sets blockStride with given value.
@param _cellSize sets cellSize with given value.
@param _nbins sets nbins with given value.
@param _derivAperture sets derivAperture with given value.
@param _winSigma sets winSigma with given value.
@param _histogramNormType sets histogramNormType with given value.
@param _L2HysThreshold sets L2HysThreshold with given value.
@param _gammaCorrection sets gammaCorrection with given value.
@param _nlevels sets nlevels with given value.
@param _signedGradient sets signedGradient with given value.
*/
CV_WRAP HOGDescriptor(Size _winSize, Size _blockSize, Size _blockStride,
Size _cellSize, int _nbins, int _derivAperture=1, double _winSigma=-1,
HOGDescriptor::HistogramNormType _histogramNormType=HOGDescriptor::L2Hys,
double _L2HysThreshold=0.2, bool _gammaCorrection=false,
int _nlevels=HOGDescriptor::DEFAULT_NLEVELS, bool _signedGradient=false)
: winSize(_winSize), blockSize(_blockSize), blockStride(_blockStride), cellSize(_cellSize),
nbins(_nbins), derivAperture(_derivAperture), winSigma(_winSigma),
histogramNormType(_histogramNormType), L2HysThreshold(_L2HysThreshold),
gammaCorrection(_gammaCorrection), free_coef(-1.f), nlevels(_nlevels), signedGradient(_signedGradient)
{}
opencv——HOG详解_haoxiaodao的博客-优快云博客
HOGDescriptor::SetSVMDetector()有些限制
1. linear kernel only
2. imgsize == winsize
/** @brief Detects objects of different sizes in the input image. The detected objects are returned as a list
of rectangles.
@param img Matrix of the type CV_8U or CV_8UC3 containing an image where objects are detected.
@param foundLocations Vector of rectangles where each rectangle contains the detected object.
@param hitThreshold Threshold for the distance between features and SVM classifying plane.
Usually it is 0 and should be specified in the detector coefficients (as the last free coefficient).
But if the free coefficient is omitted (which is allowed), you can specify it manually here.
@param winStride Window stride. It must be a multiple of block stride.
@param padding Padding
@param scale Coefficient of the detection window increase.
@param finalThreshold Final threshold
@param useMeanshiftGrouping indicates grouping algorithm
*/
virtual void detectMultiScale(InputArray img, CV_OUT std::vector<Rect>& foundLocations,
double hitThreshold = 0, Size winStride = Size(),
Size padding = Size(), double scale = 1.05,
double finalThreshold = 2.0, bool useMeanshiftGrouping = false) const;
/** @brief 检测输入图像中不同大小的对象。 检测到的对象作为矩形列表返回。
@param img CV_8U 或 CV_8UC3 类型的矩阵,包含检测到对象的图像。
@param foundLocations 矩形向量,其中每个矩形都包含检测到的对象。
@param hitThreshold 特征和 SVM 分类平面之间距离的阈值。 通常为 0,应在检测器系数中指定(作为最后一个自由系数)。 但如果自由系数被省略(这是允许的),您可以在此处手动指定。
@param winStride 窗口步幅。 它必须是块步长的倍数。
@param padding 填充
@param scale 检测窗口增加的系数。
@param finalThreshold 最终阈值
@param useMeanshiftGrouping 表示分组算法
*/
常见的pad size 有(8, 8), (16, 16), (24, 24), (32, 32).
HOG detectMultiScale 参数分析 - klitech - 博客园 (cnblogs.com)
/**@example samples/cpp/train_HOG.cpp
*/
/** @brief Computes HOG descriptors of given image.
@param img Matrix of the type CV_8U containing an image where HOG features will be calculated.
@param descriptors Matrix of the type CV_32F
@param winStride Window stride. It must be a multiple of block stride.
@param padding Padding
@param locations Vector of Point
*/
CV_WRAP virtual void compute(InputArray img,
CV_OUT std::vector<float>& descriptors,
Size winStride = Size(), Size padding = Size(),
const std::vector<Point>& locations = std::vector<Point>()) const;
/**@example samples/cpp/train_HOG.cpp
*/
/** @brief 计算给定图像的 HOG(方向直方图梯度) 描述符。
@param img CV_8U 类型的矩阵,包含将计算 HOG 特征的图像。
@param descriptors CV_32F 类型的矩阵
@param winStride 窗口步幅。 它必须是块步长的倍数。
@param padding 填充
@param locations 点向量
*/
hog.compute(src, descriptors, cv::Size(16, 16));//计算HOG描述子,检测窗口移动步长(16,16)
//构造
cv::HOGDescriptor hog(cv::Size(576, 576), cv::Size(192, 192), cv::Size(96, 96), cv::Size(96, 96), 9); //HOG检测器,用来计算HOG描述子的,依次为检测窗口,块尺寸,块步长,cell尺寸,直方图个数
//计算
hog.compute(src, descriptors, cv::Size(16, 16));//计算HOG描述子,检测窗口移动步长(16,16)
//预测
Myhog.detectMultiScale(src, found, 0, cv::Size(16, 16), cv::Size(32, 32), 2.5, 20);//对图片进行多尺度检测 src, found, 0, cv::Size(16, 16), cv::Size(32, 32), 2.5, 20
HOG detectMultiScale 参数分析 - klitech - 博客园 (cnblogs.com)
SVM的类型(5种)
1、CvSVM::C_SVC : C类支撑向量分类机。 n类分组 (n≥2),容许用异常值处罚因子C进行不完全分类。
2、CvSVM::NU_SVC : 类支撑向量分类机。n类似然不完全分类的分类器。参数为庖代C(其值在区间【0,1】中,nu越大,决定计划鸿沟越腻滑)。
3、CvSVM::ONE_CLASS : 单分类器,所有的练习数据提取自同一个类里,然后SVM建树了一个分界线以分别该类在特点空间中所占区域和其它类在特点空间中所占区域。
4、CvSVM::EPS_SVR : 类支撑向量回归机。练习集中的特点向量和拟合出来的超平面的间隔须要小于p。异常值处罚因子C被采取。
5、CvSVM::NU_SVR : 类支撑向量回归机。 庖代了 p。
Opencv中的核函数定义:
CvSVM::LINEAR : 线性内核,没有任何向映射至高维空间,线性区分(或回归)在原始特点空间中被完成,这是最快的选择。
CvSVM::POLY : 多项式内核:
CvSVM::RBF : 基于径向的函数,对于大多半景象都是一个较好的选择:
CvSVM::SIGMOID : Sigmoid函数内核:
opencv——SVM参数详解_Ring__Rain的博客-优快云博客_opencv svm参数 .
setC(double c): 设置惩罚函数的参数C的大小,一般大于0,不允许是0;
setClassWeights(Mat & val):表示不同分类的权值,该值和C相乘后,实现了不同分类的不同的惩罚力度,值越大,该类别的惩罚力度就越大。一般在多分类中使用,mat的大小和分类的类别多少是一致的。
setCoef(double val):设置多项式核函数和sigmod核函数的参数P,
setCustomKernel ( const Ptr< Kernel > & _kernel ) ://这个基本没用过。。。。。应该是自定义核函数
setDegree ( double val ) :设置多项式核函数的Q;
setGamma ( double val ) :设置多项式核函数,高斯核函数,sigmod核函数的参数伽马
setKernel ( int kernelType ) :选用opencv自带的核函数,整个包含在一个枚举当中。包括:
setNu ( double val ) :表示NU-svc和NU-svr的参数Nu,在下面图片中有写道
setP ( double val ) :表示-P-SVR的参数P;
setTermCriteria ( const cv::TermCriteria & val ) :设置迭代终止条件
setType ( int val ) :选用类型:
机器学习(3),opencv4.0中SVM各个参数的意义,设置_邓文尧的博客-优快云博客
8. 机器学习 - 使用 SVM 进行手写数据识别 - 《OpenCV 中文文档 4.0.0》 - 书栈网 · BookStack
SVM 的核函数选择和调参
原创 Alice 机器学习X计划 2018-06-07 08:23
本文结构:
- 什么是核函数
- 都有哪些 & 如何选择
- 调参
1. 什么是核函数
核函数形式 K(x, y) = <f(x), f(y)>,
其中 x, y 为 n 维,f 为 n 维到 m 维的映射, <f(x), f(y)>表示内积。
在用SVM处理问题时,如果数据线性不可分,希望通过 将输入空间内线性不可分的数据 映射到 一个高维的特征空间内,使数据在特征空间内是线性可分的,这个映射记作 ϕ(x),
之后优化问题中就会有内积 ϕi⋅ϕj,
这个内积的计算维度会非常大,因此引入了核函数,
kernel 可以帮我们很快地做一些计算, 否则将需要在高维空间中进行计算。
2. 都有哪些 & 如何选择
下表列出了 9 种核函数以及它们的用处和公式,常用的为其中的前四个:linear,Polynomial,RBF,Sigmoid
其中 linear kernel 和 RBF kernel 在线性可分和不可分的对比可视化例子如下:
3. 调参
在 sklearn 中可以用 grid search 找到合适的 kernel,以及它们的 gamma,C 等参数,那么来看看各 kernel 主要调节的参数是哪些:
其中有两个重要的参数,即 C(惩罚系数) 和 gamma,
gamma 越大,支持向量越少,gamma 越小,支持向量越多。
而支持向量的个数影响训练和预测的速度。
C 越高,容易过拟合。C 越小,容易欠拟合。
学习资料:
https://data-flair.training/blogs/svm-kernel-functions/
https://www.quora.com/What-are-kernels-in-machine-learning-and-SVM-and-why-do-we-need-them
SVM的核函数如何选取? - 知乎https://www.quora.com/How-do-I-select-SVM-kernels