#include <iostream>
#include <thread>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/ml.hpp>
using namespace std::chrono_literals;
static int wait_time = 1;
static int collect_num = 2000;
static cv::Mat frame;
static std::vector<rm::group::ptr> groups;
static cv::Mat armor_samples;
static cv::Mat armor_responses;
{
for (int idx = 0; idx < collect_num; ++idx)
{
capture->read(frame);
if (frame.empty())
const auto &combos = info.combos;
if (combos.size() != 1)
{
if (combos.size() > 1)
WARNING_(
"Size of the combos is greater than 1, size = %zu", combos.size());
idx--;
}
else
{
armor_samples.at<float>(begin_idx + idx, 0) = p_armor->getComboRatio();
armor_samples.at<float>(begin_idx + idx, 1) = p_armor->getWidthRatio();
armor_samples.at<float>(begin_idx + idx, 2) = p_armor->getLengthRatio();
const auto &corners = p_armor->corners();
for (int i = 0; i < 4; ++i)
line(frame, corners[i], corners[(i + 1) % 4], cv::Scalar(0, 255, 0), 2);
}
putText(frame, std::to_string(idx), cv::Point(20, 50), cv::FONT_HERSHEY_COMPLEX, 1.0, cv::Scalar(255, 255, 255), 1);
imshow("信息收集", frame);
int ch = cv::waitKey(wait_time);
if (ch == 27)
cv::waitKey(0);
else if (ch == 113)
exit(0);
}
}
constexpr const char *keys = "{ ? h help | | 帮助信息 }"
"{ m model | | 模型路径,这将跳过训练直接进行测试 }"
"{ n num |2000 | 每种装甲板收集的数量 }"
"{ w waitkey |1 | cv::cv::waitKey(?) }"
"{ c color |0 | 识别装甲板颜色 '\033[33m0\033[0m': 识别蓝色,"
"'\033[33m1\033[0m': 识别红色 }";
constexpr const char *help = " \033[34;1m使用说明\033[0m\n"
"程序会收集大小装甲板数据各 'num' 张(默认为 2000 张),通过采集\n1) "
"装甲板长宽比 combo_ratio\n2) 灯条宽度比 width_ratio\n3) 灯条长度比 "
"length_ratio\n5) 共 3 个指标特征,进行 SVM 二分类,分类后的结果将自"
"动\n导出至 \033[33mout_armor_size.xml\033[0m 中";
int main(int argc, char *argv[])
{
cv::CommandLineParser parser(argc, argv, keys);
if (parser.has("help"))
{
parser.printMessage();
printf("%s\n", help);
exit(0);
}
std::string model;
if (parser.has("model"))
model = parser.get<std::string>("model");
collect_num = parser.get<int>("num");
wait_time = parser.get<int>("waitkey");
armor_samples = cv::Mat::zeros(collect_num * 2, 3, CV_32FC1);
armor_responses = cv::Mat::zeros(collect_num * 2, 1, CV_32SC1);
if (!capture->isOpened())
{
printf("相机打开失败\n");
return -1;
}
int exposure = 3000;
int gain = 8;
int r_gain = 1500;
int g_gain = 1500;
int b_gain = 1500;
cv::FileStorage fs_mv_set("out_para.yml", cv::FileStorage::READ);
if (fs_mv_set.isOpened())
{
fs_mv_set["exposure"].isNone() ? void(0) : (fs_mv_set["exposure"] >> exposure);
fs_mv_set["gain"].isNone() ? void(0) : (fs_mv_set["gain"] >> gain);
fs_mv_set["r_gain"].isNone() ? void(0) : (fs_mv_set["r_gain"] >> r_gain);
fs_mv_set["g_gain"].isNone() ? void(0) : (fs_mv_set["g_gain"] >> g_gain);
fs_mv_set["b_gain"].isNone() ? void(0) : (fs_mv_set["b_gain"] >> b_gain);
}
cv::Ptr<cv::ml::SVM> p_svm = nullptr;
if (model.empty())
{
printf("=======================================\n");
std::string key_str;
printf("\033[32m小装甲板\033[0m信息收集即将开始...\n");
printf("输入 \033[33;1mok\033[0m 来开始收集 >>> ");
std::cin >> key_str;
if (key_str != "ok")
return 0;
cv::destroyAllWindows();
std::this_thread::sleep_for(10ms);
printf("\033[32m大装甲板\033[0m信息收集即将开始...\n");
printf("输入 \033[33;1mok\033[0m 来开始收集 >>> ");
std::cin >> key_str;
if (key_str != "ok")
return 0;
cv::destroyAllWindows();
std::this_thread::sleep_for(10ms);
p_svm = cv::ml::SVM::create();
p_svm->setType(cv::ml::SVM::C_SVC);
p_svm->setKernel(cv::ml::SVM::RBF);
if (p_svm->train(armor_samples, cv::ml::ROW_SAMPLE, armor_responses))
p_svm->save("out_armor_size.xml");
else
printf("想要进行测试吗?\n");
printf("输入 \033[33;1mok\033[0m 来进行测试 >>> ");
std::cin >> key_str;
if (key_str != "ok")
return 0;
}
else
{
p_svm = cv::ml::SVM::load(model);
}
printf("在键盘上按下一次 \033[33mEsc\033[0m 来暂停,按下两次 \033[33mEsc\033[0m 来退出测试\n");
while (capture->read(frame))
{
const auto &combos = info.combos;
if (!combos.empty())
{
if (combos.size() > 1)
WARNING_(
"Size of the combos is greater than 1, size = %zu", combos.size());
cv::Matx13f test_sample;
test_sample(0) = p_armor->getComboRatio();
test_sample(1) = p_armor->getWidthRatio();
test_sample(2) = p_armor->getLengthRatio();
float result = p_svm->predict(test_sample);
putText(frame, result == 1 ? "SMALL" : "BIG", cv::Point(20, 50),
cv::FONT_HERSHEY_COMPLEX, 1.0, cv::Scalar(255, 255, 255), 2);
const auto &corners = p_armor->corners();
for (int i = 0; i < 4; ++i)
line(frame, corners[i], corners[(i + 1) % 4], cv::Scalar(0, 255, 0), 2);
}
imshow("模型测试", frame);
if (cv::waitKey(wait_time) == 27)
if (cv::waitKey(0) == 27)
break;
}
return 0;
}
static auto make_detector()
构建 ArmorDetector
定义 armor_detector.h:55
static ptr cast(combo::ptr p_combo)
定义 armor.h:66
static std::unique_ptr< HikCamera > make_capture(CameraConfig cfg, std::string_view info="")
构建 HikCamera 对象
定义 hik_camera.h:63
std::unique_ptr< HikCamera > ptr
定义 hik_camera.h:39
static double now()
返回从构造初期到现在经过的时间(单位:s)
定义 timer.hpp:46
PixChannel
像素通道枚举
定义 pretreat.hpp:36
@ RED
红色通道
定义 pretreat.hpp:39
@ BLUE
蓝色通道
定义 pretreat.hpp:37
@ OpenCV
使用 OpenCV 的 'cvtColor' 进行处理
@ CAMERA_WB_BGAIN
白平衡蓝色分量
定义 camutils.hpp:108
@ CAMERA_WB_GGAIN
白平衡绿色分量
定义 camutils.hpp:107
@ CAMERA_MANUAL_EXPOSURE
手动曝光
定义 camutils.hpp:99
@ CAMERA_EXPOSURE
曝光值
定义 camutils.hpp:103
@ CAMERA_MANUAL_WB
手动白平衡
定义 camutils.hpp:102
@ CAMERA_WB_RGAIN
白平衡红色分量
定义 camutils.hpp:106
@ CAMERA_GAIN
模拟增益
定义 camutils.hpp:104
#define WARNING_(...)
定义 util.hpp:36
#define RMVL_Error(code, msg)
调用错误处理程序
定义 util.hpp:209
@ RMVL_StsBadSize
数组大小不正确 Incorrect size of the array
定义 util.hpp:86
@ RMVL_StsError
未指定(未知)错误 Unspecified (Unknown) error
定义 util.hpp:83
ArmorSizeType
装甲板大小类型
定义 types.hpp:26
static CameraConfig create(Args &&...modes)
创建相机初始化配置模式
定义 camutils.hpp:72