当前位置:   article > 正文

利用SVM进行图像目标检测和分类_基于svm的图像检测

基于svm的图像检测
  1. #include <iostream>
  2. #include <opencv2/opencv.hpp>
  3. #include <opencv2/core/core.hpp>
  4. #include <opencv2/highgui/highgui.hpp>
  5. #include <opencv2/imgproc/imgproc.hpp>
  6. #include<opencv2/ml/ml.hpp>
  7. using namespace cv;
  8. using namespace std;
  9. Mat img, image;
  10. Mat targetData, backData;
  11. bool flag = true;
  12. string wdname = "image";
  13. void on_mouse(int event, int x, int y, int flags, void* ustc); //鼠标取样本点
  14. void getTrainData(Mat &train_data, Mat &train_label); //生成训练数据
  15. void svm(); //svm分类
  16. int main(int argc, char** argv)
  17. {
  18. string path = "1.png";
  19. img = imread(path);
  20. img.copyTo(image);
  21. if (img.empty())
  22. {
  23. cout << "Image load error";
  24. return 0;
  25. }
  26. namedWindow(wdname);
  27. setMouseCallback(wdname, on_mouse, 0);
  28. for (;;)
  29. {
  30. imshow("image", img);
  31. int c = waitKey(0);
  32. if ((c & 255) == 27)
  33. {
  34. cout << "Exiting ...\n";
  35. break;
  36. }
  37. if ((char)c == 'c')
  38. {
  39. flag = false;
  40. }
  41. if ((char)c == 'q')
  42. {
  43. destroyAllWindows();
  44. break;
  45. }
  46. }
  47. svm();
  48. return 0;
  49. }
  50. //鼠标在图像上取样本点,按q键退出
  51. void on_mouse(int event, int x, int y, int flags, void* ustc)
  52. {
  53. if (event == CV_EVENT_LBUTTONDOWN)
  54. {
  55. Point pt = Point(x, y);
  56. Vec3b point = img.at<Vec3b>(y, x); //取出该坐标处的像素值,注意x,y的顺序
  57. Mat tmp = (Mat_<float>(1, 3) << point[0], point[1], point[2]);
  58. if (flag)
  59. {
  60. targetData.push_back(tmp); //加入正样本矩阵
  61. circle(img, pt, 2, Scalar(0, 255, 255), -1, 8); //画出点击的点
  62. }
  63. else
  64. {
  65. backData.push_back(tmp); //加入负样本矩阵
  66. circle(img, pt, 2, Scalar(255, 0, 0), -1, 8);
  67. }
  68. imshow(wdname, img);
  69. }
  70. }
  71. void getTrainData(Mat &train_data, Mat &train_label)
  72. {
  73. int m = targetData.rows;
  74. int n = backData.rows;
  75. cout << "正样本数::" << m << endl;
  76. cout << "负样本数:" << n << endl;
  77. vconcat(targetData, backData, train_data); //合并所有的样本点,作为训练数据
  78. train_label = Mat(m + n, 1, CV_32S, Scalar::all(1)); //初始化标注
  79. for (int i = m; i < m + n; i++)
  80. train_label.at<int>(i, 0) = -1;
  81. }
  82. void svm()
  83. {
  84. Mat train_data, train_label;
  85. getTrainData(train_data, train_label); //获取鼠标选择的样本训练数据
  86. CvSVMParams params;
  87. params.svm_type = CvSVM::C_SVC;
  88. params.kernel_type = CvSVM::LINEAR;
  89. params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
  90. // 对SVM进行训练
  91. CvSVM SVM;
  92. SVM.train(train_data, train_label, Mat(), Mat(), params);
  93. Vec3b color(0, 0, 0);
  94. // Show the decision regions given by the SVM
  95. for (int i = 0; i < image.rows; ++i)
  96. for (int j = 0; j < image.cols; ++j)
  97. {
  98. Vec3b point = img.at<Vec3b>(i, j); //取出该坐标处的像素值
  99. Mat sampleMat = (Mat_<float>(1, 3) << point[0], point[1], point[2]);
  100. float response = SVM.predict(sampleMat); //进行预测,返回1或-1,返回类型为float
  101. if ((int)response != 1)
  102. image.at<Vec3b>(i, j) = color; //将背景设置为黑色
  103. }
  104. imshow("SVM Simple Example", image);
  105. waitKey(0);
  106. }


代码如上:

1.首先输入图像,调用setMouseCallback函数进行鼠标取点

2.用鼠标在图像上点击,取出当前点的红绿蓝像素值进行训练。先选择任意个目标样本,然后按"c“键后选择任意个背景样本。样本数可以自己随意决定。样本选择完后,按”q"键完成样本选择。

3.将正负样本矩阵,用vconcat合并成一个矩阵,用作训练分类器,并对相应的样本进行标注。最后将识别出的目标保留,将背景部分调成黑色。

原图:


效果图:


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/385327?site
推荐阅读
相关标签
  

闽ICP备14008679号