energy changed

This commit is contained in:
sun
2019-08-04 01:12:51 +08:00
parent 199feb3ba9
commit 977de37b14
10 changed files with 302 additions and 187 deletions

View File

@@ -132,6 +132,7 @@ private:
bool findFlowStrip(const cv::Mat src);//寻找图中的流动条 bool findFlowStrip(const cv::Mat src);//寻找图中的流动条
bool findCenterROI(const cv::Mat src);//框取中心R候选区 bool findCenterROI(const cv::Mat src);//框取中心R候选区
bool findFlowStripFan(const cv::Mat src);//寻找图中的流动条所在扇叶 bool findFlowStripFan(const cv::Mat src);//寻找图中的流动条所在扇叶
bool findFlowStripWeak(const cv::Mat src);//弱识别寻找图中的流动条
bool isValidFanContour(cv::Mat &src, const vector<cv::Point> &fan_contour);//扇叶矩形尺寸要求 bool isValidFanContour(cv::Mat &src, const vector<cv::Point> &fan_contour);//扇叶矩形尺寸要求
bool isValidArmorContour(const vector<cv::Point> &armor_contour);//装甲板矩形尺寸要求 bool isValidArmorContour(const vector<cv::Point> &armor_contour);//装甲板矩形尺寸要求
@@ -143,6 +144,7 @@ private:
void showArmors(std::string windows_name, const cv::Mat src);//显示装甲板 void showArmors(std::string windows_name, const cv::Mat src);//显示装甲板
void showBoth(std::string windows_name, const cv::Mat src);//显示扇叶和装甲板 void showBoth(std::string windows_name, const cv::Mat src);//显示扇叶和装甲板
void showCenterR(std::string windows_name, const cv::Mat src);//显示风车中心候选区R void showCenterR(std::string windows_name, const cv::Mat src);//显示风车中心候选区R
void showFlowStrip(std::string windows_name, const cv::Mat src);//显示流动条
void showFlowStripFan(std::string windows_name, const cv::Mat src);//显示流动条所在扇叶 void showFlowStripFan(std::string windows_name, const cv::Mat src);//显示流动条所在扇叶
void showGuessTarget(std::string windows_name, const cv::Mat src);//显示猜测点位 void showGuessTarget(std::string windows_name, const cv::Mat src);//显示猜测点位

View File

@@ -83,6 +83,9 @@ struct EnergyPartParam {
long TARGET_CHANGE_DISTANCE_MAX;//目标未更改时,目标装甲板中心与原目标装甲板中心的距离变化最大值 long TARGET_CHANGE_DISTANCE_MAX;//目标未更改时,目标装甲板中心与原目标装甲板中心的距离变化最大值
long TWIN_POINT_MAX;//两个点相同时距离最大值 long TWIN_POINT_MAX;//两个点相同时距离最大值
long STRIP_ARMOR_DISTANCE_MIN;//流动条中心和目标装甲板中心距离最小值
long STRIP_ARMOR_DISTANCE_MAX;//流动条中心和目标装甲板中心距离最大值
}; };

View File

@@ -71,7 +71,6 @@ void Energy::initEnergy() {
all_target_armor_centers.clear(); all_target_armor_centers.clear();
while(!recent_target_armor_centers.empty())recent_target_armor_centers.pop(); while(!recent_target_armor_centers.empty())recent_target_armor_centers.pop();
} }
@@ -81,7 +80,7 @@ void Energy::initEnergy() {
void Energy::initEnergyPartParam() { void Energy::initEnergyPartParam() {
// gimbal_energy_part_param_.GRAY_THRESH = 120;//home // gimbal_energy_part_param_.GRAY_THRESH = 120;//home
// gimbal_energy_part_param_.GRAY_THRESH = 200;//official // gimbal_energy_part_param_.GRAY_THRESH = 200;//official
gimbal_energy_part_param_.GRAY_THRESH = 180; gimbal_energy_part_param_.GRAY_THRESH = 180;//game
gimbal_energy_part_param_.SPLIT_GRAY_THRESH = 180; gimbal_energy_part_param_.SPLIT_GRAY_THRESH = 180;
gimbal_energy_part_param_.FAN_GRAY_THRESH = 75; gimbal_energy_part_param_.FAN_GRAY_THRESH = 75;
gimbal_energy_part_param_.ARMOR_GRAY_THRESH = 80; gimbal_energy_part_param_.ARMOR_GRAY_THRESH = 80;
@@ -100,8 +99,8 @@ void Energy::initEnergyPartParam() {
// gimbal_energy_part_param_.FAN_NON_ZERO_RATE_MAX = 0.3; // gimbal_energy_part_param_.FAN_NON_ZERO_RATE_MAX = 0.3;
// gimbal_energy_part_param_.FAN_NON_ZERO_RATE_MIN = 0.16; // gimbal_energy_part_param_.FAN_NON_ZERO_RATE_MIN = 0.16;
gimbal_energy_part_param_.ARMOR_CONTOUR_AREA_MAX = 100000; gimbal_energy_part_param_.ARMOR_CONTOUR_AREA_MAX = 500;
gimbal_energy_part_param_.ARMOR_CONTOUR_AREA_MIN = 0; gimbal_energy_part_param_.ARMOR_CONTOUR_AREA_MIN = 180;
gimbal_energy_part_param_.ARMOR_CONTOUR_LENGTH_MIN = 16; gimbal_energy_part_param_.ARMOR_CONTOUR_LENGTH_MIN = 16;
gimbal_energy_part_param_.ARMOR_CONTOUR_LENGTH_MAX = 32; gimbal_energy_part_param_.ARMOR_CONTOUR_LENGTH_MAX = 32;
gimbal_energy_part_param_.ARMOR_CONTOUR_WIDTH_MIN = 5; gimbal_energy_part_param_.ARMOR_CONTOUR_WIDTH_MIN = 5;
@@ -109,42 +108,41 @@ void Energy::initEnergyPartParam() {
gimbal_energy_part_param_.ARMOR_CONTOUR_HW_RATIO_MAX = 3; gimbal_energy_part_param_.ARMOR_CONTOUR_HW_RATIO_MAX = 3;
gimbal_energy_part_param_.ARMOR_CONTOUR_HW_RATIO_MIN = 1; gimbal_energy_part_param_.ARMOR_CONTOUR_HW_RATIO_MIN = 1;
gimbal_energy_part_param_.CENTER_R_CONTOUR_AREA_MAX = 100000; gimbal_energy_part_param_.CENTER_R_CONTOUR_AREA_MAX = 200;
gimbal_energy_part_param_.CENTER_R_CONTOUR_AREA_MIN = 0; gimbal_energy_part_param_.CENTER_R_CONTOUR_AREA_MIN = 40;
gimbal_energy_part_param_.CENTER_R_CONTOUR_LENGTH_MIN = 8; gimbal_energy_part_param_.CENTER_R_CONTOUR_LENGTH_MIN = 6;
gimbal_energy_part_param_.CENTER_R_CONTOUR_LENGTH_MAX = 45; gimbal_energy_part_param_.CENTER_R_CONTOUR_LENGTH_MAX = 20;
gimbal_energy_part_param_.CENTER_R_CONTOUR_WIDTH_MIN = 8; gimbal_energy_part_param_.CENTER_R_CONTOUR_WIDTH_MIN = 6;
gimbal_energy_part_param_.CENTER_R_CONTOUR_WIDTH_MAX = 45; gimbal_energy_part_param_.CENTER_R_CONTOUR_WIDTH_MAX = 20;
gimbal_energy_part_param_.CENTER_R_CONTOUR_HW_RATIO_MAX = 3; gimbal_energy_part_param_.CENTER_R_CONTOUR_HW_RATIO_MAX = 2;
gimbal_energy_part_param_.CENTER_R_CONTOUR_HW_RATIO_MIN = 1; gimbal_energy_part_param_.CENTER_R_CONTOUR_HW_RATIO_MIN = 1;
gimbal_energy_part_param_.CENTER_R_CONTOUR_AREA_RATIO_MIN = 0.3; gimbal_energy_part_param_.CENTER_R_CONTOUR_AREA_RATIO_MIN = 0.6;
gimbal_energy_part_param_.CENTER_R_CONTOUR_INTERSETION_AREA_MIN = 10; gimbal_energy_part_param_.CENTER_R_CONTOUR_INTERSETION_AREA_MIN = 10;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_MAX = 3000; gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_MAX = 2000;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_MIN = 1000; gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_MIN = 500;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_LENGTH_MIN = 60; gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_LENGTH_MIN = 60;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_LENGTH_MAX = 100; gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_LENGTH_MAX = 100;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MIN = 20; gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MIN = 20;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MAX = 52; gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MAX = 52;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MAX = 3; gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MAX = 2.8;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MIN = 1; gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MIN = 1.2;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_RATIO_MAX = 0.65; gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_RATIO_MAX = 0.58;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_RATIO_MIN = 0.34; gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_RATIO_MIN = 0.34;
gimbal_energy_part_param_.FLOW_STRIP_FAN_NON_ZERO_RATE_MAX = 0.65; gimbal_energy_part_param_.FLOW_STRIP_FAN_NON_ZERO_RATE_MAX = 0.58;
gimbal_energy_part_param_.FLOW_STRIP_FAN_NON_ZERO_RATE_MIN = 0.34; gimbal_energy_part_param_.FLOW_STRIP_FAN_NON_ZERO_RATE_MIN = 0.34;
// gimbal_energy_part_param_.FLOW_STRIP_FAN_NON_ZERO_RATE_MAX = 0.2; // gimbal_energy_part_param_.FLOW_STRIP_FAN_NON_ZERO_RATE_MAX = 0.2;
// gimbal_energy_part_param_.FLOW_STRIP_FAN_NON_ZERO_RATE_MIN = 0.08; // gimbal_energy_part_param_.FLOW_STRIP_FAN_NON_ZERO_RATE_MIN = 0.08;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_AREA_MAX = 100000; gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_AREA_MAX = 700;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_AREA_MIN = 0; gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_AREA_MIN = 100;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MIN = 30; gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MIN = 32;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MAX = 55; gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MAX = 55;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MIN = 4; gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MIN = 4;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MAX = 20; gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MAX = 20;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MAX = 12; gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MAX = 7;
// gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MIN = 4; gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MIN = 3;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MIN = 1.5; gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_AREA_RATIO_MIN = 0.6;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_AREA_RATIO_MIN = 0.5;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_INTERSETION_AREA_MIN = 100; gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_INTERSETION_AREA_MIN = 100;
gimbal_energy_part_param_.TWIN_ANGEL_MAX = 10; gimbal_energy_part_param_.TWIN_ANGEL_MAX = 10;
@@ -153,6 +151,9 @@ void Energy::initEnergyPartParam() {
gimbal_energy_part_param_.TARGET_CHANGE_DISTANCE_MAX = 20; gimbal_energy_part_param_.TARGET_CHANGE_DISTANCE_MAX = 20;
gimbal_energy_part_param_.TWIN_POINT_MAX = 20; gimbal_energy_part_param_.TWIN_POINT_MAX = 20;
gimbal_energy_part_param_.STRIP_ARMOR_DISTANCE_MIN = 28;
gimbal_energy_part_param_.STRIP_ARMOR_DISTANCE_MAX = 52;
chassis_energy_part_param_.GRAY_THRESH = 120;//home chassis_energy_part_param_.GRAY_THRESH = 120;//home

View File

@@ -77,40 +77,44 @@ int Energy::findArmors(const cv::Mat src) {
ArmorStruct(src_bin);//图像膨胀,防止图像断开并更方便寻找 ArmorStruct(src_bin);//图像膨胀,防止图像断开并更方便寻找
findContours(src_bin, armor_contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE); findContours(src_bin, armor_contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
if (show_process)imshow("armor struct", src_bin); if (show_process)imshow("armor struct", src_bin);
// findContours(src_bin, armor_contours_external, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
// for (int i = 0; i < armor_contours_external.size(); i++)//去除外轮廓 findContours(src_bin, armor_contours_external, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
// { for (int i = 0; i < armor_contours_external.size(); i++)//去除外轮廓
// unsigned long external_contour_size = armor_contours_external[i].size(); {
// for (int j = 0; j < armor_contours.size(); j++) { unsigned long external_contour_size = armor_contours_external[i].size();
// unsigned long all_size = armor_contours[j].size(); for (int j = 0; j < armor_contours.size(); j++) {
// if (external_contour_size == all_size) { unsigned long all_size = armor_contours[j].size();
// swap(armor_contours[j], armor_contours[armor_contours.size() - 1]); if (external_contour_size == all_size) {
// armor_contours.pop_back(); swap(armor_contours[j], armor_contours[armor_contours.size() - 1]);
// break; armor_contours.pop_back();
// } break;
// } }
// } }
}
for (auto &armor_contour : armor_contours) { for (auto &armor_contour : armor_contours) {
if (!isValidArmorContour(armor_contour)) { if (!isValidArmorContour(armor_contour)) {
continue; continue;
} }
armors.emplace_back(cv::minAreaRect(armor_contour)); armors.emplace_back(cv::minAreaRect(armor_contour));
// RotatedRect cur_rect = minAreaRect(armor_contour); // RotatedRect cur_rect = minAreaRect(armor_contour);
// Size2f cur_size = cur_rect.size; // Size2f cur_size = cur_rect.size;
// float length = cur_size.height > cur_size.width ? cur_size.height : cur_size.width; // float length = cur_size.height > cur_size.width ? cur_size.height : cur_size.width;
// float width = cur_size.height < cur_size.width ? cur_size.height : cur_size.width; // float width = cur_size.height < cur_size.width ? cur_size.height : cur_size.width;
// if (length > 5 && width > 5) { // double cur_contour_area = contourArea(armor_contour);
// armors.emplace_back(cv::minAreaRect(armor_contour)); // float length_width_ratio = length / width;
// cout << "armor area: " << length << '\t' << width << '\t' << cur_rect.center << endl; // cout << "area: " << cur_contour_area << '\t' << endl;
// } // cout << "length: " << length << '\t' << "width: " << width << '\t' << cur_rect.center << endl;
// cout << "HW: " << length_width_ratio << '\t' << cur_rect.center << endl;
// cout << "area ratio: " << cur_contour_area / cur_size.area() << '\t' << cur_rect.center << endl;
// cout<<endl;
} }
// cout<<armors.size()<<endl; if (show_info) {
// showArmors("armor",src);
// if (armors.size() < 1)cout << "no armors!" << endl; // if (armors.size() < 1)cout << "no armors!" << endl;
}
return static_cast<int>(armors.size()); return static_cast<int>(armors.size());
} }
@@ -147,18 +151,14 @@ bool Energy::findCenterR(const cv::Mat src) {
// Size2f cur_size = cur_rect.size; // Size2f cur_size = cur_rect.size;
// float length = cur_size.height > cur_size.width ? cur_size.height : cur_size.width; // float length = cur_size.height > cur_size.width ? cur_size.height : cur_size.width;
// float width = cur_size.height < cur_size.width ? cur_size.height : cur_size.width; // float width = cur_size.height < cur_size.width ? cur_size.height : cur_size.width;
// if (length < 10 || width < 5 || length>19) { // double cur_contour_area = contourArea(center_R_contour);
// continue; // float length_width_ratio = length / width;
// } // cout << "area: " << cur_contour_area << '\t' << endl;
// std::vector<cv::Point2f> intersection; // cout << "length: " << length << '\t' << "width: " << width << '\t' << cur_rect.center << endl;
// if (rotatedRectangleIntersection(cur_rect, center_ROI, intersection) != 0 && // cout << "HW: " << length_width_ratio << '\t' << cur_rect.center << endl;
// contourArea(intersection) > energy_part_param_.CENTER_R_CONTOUR_INTERSETION_AREA_MIN) { // cout << "area ratio: " << cur_contour_area / cur_size.area() << '\t' << cur_rect.center << endl;
// centerR = cv::minAreaRect(center_R_contour); // cout<<endl;
// cout << "center R area: " << length << '\t' << width << '\t' << cur_rect.center << endl;
// cout << "R intersection: " << contourArea(intersection) << endl;
// return true;
// }
// cout << cur_rect.center << endl;
return true; return true;
} }
if (show_info)cout << "find center R false!" << endl; if (show_info)cout << "find center R false!" << endl;
@@ -201,17 +201,16 @@ bool Energy::findFlowStripFan(const cv::Mat src) {
// float length = cur_size.height > cur_size.width ? cur_size.height : cur_size.width; // float length = cur_size.height > cur_size.width ? cur_size.height : cur_size.width;
// float width = cur_size.height < cur_size.width ? cur_size.height : cur_size.width; // float width = cur_size.height < cur_size.width ? cur_size.height : cur_size.width;
// double cur_contour_area = contourArea(flow_strip_fan_contour); // double cur_contour_area = contourArea(flow_strip_fan_contour);
// if (length > 40 && width > 30 && length < 110 && width < 100) { // float length_width_ratio = length / width;
// cout << cur_rect.center<<endl; // cout << "area: " << cur_contour_area << '\t' << endl;
// flow_strip_fan = cv::minAreaRect(flow_strip_fan_contour); // cout << "length: " << length << '\t' << "width: " << width << '\t' << cur_rect.center << endl;
// cout << "flow strip fan area: " << length << '\t' << width << endl; // cout << "HW: " << length_width_ratio << '\t' << cur_rect.center << endl;
// cout << "non zero: " << non_zero_rate << endl; // cout << "area ratio: " << cur_contour_area / cur_size.area() << '\t' << cur_rect.center << endl;
// cout<<cur_contour_area / cur_size.area()<<endl; // cout<<endl;
// }
} }
// cout << "flow_strip_fans_cnt: " << flow_strip_fans.size() << endl;
if (flow_strip_fans.empty()) { if (flow_strip_fans.empty()) {
if (show_info)cout << "flow strip fan false!" << endl; if (show_info)cout << "flow strip fan false!" << endl;\
// waitKey(0);
return false; return false;
} }
return true; return true;
@@ -274,25 +273,15 @@ bool Energy::findFlowStrip(const cv::Mat src) {
// Size2f cur_size = cur_rect.size; // Size2f cur_size = cur_rect.size;
// float length = cur_size.height > cur_size.width ? cur_size.height : cur_size.width; // float length = cur_size.height > cur_size.width ? cur_size.height : cur_size.width;
// float width = cur_size.height < cur_size.width ? cur_size.height : cur_size.width; // float width = cur_size.height < cur_size.width ? cur_size.height : cur_size.width;
// float length_width_ratio = length / width;//计算矩形长宽比
// double cur_contour_area = contourArea(flow_strip_contour); // double cur_contour_area = contourArea(flow_strip_contour);
// float length_width_ratio = length / width;
// cout << "area: " << cur_contour_area << '\t' << endl;
// cout << "length: " << length << '\t' << "width: " << width << '\t' << cur_rect.center << endl; // cout << "length: " << length << '\t' << "width: " << width << '\t' << cur_rect.center << endl;
// cout << "HW: " << length_width_ratio << '\t' << cur_rect.center << endl; // cout << "HW: " << length_width_ratio << '\t' << cur_rect.center << endl;
// cout << "area ratio: " << cur_contour_area / cur_size.area() << '\t' << cur_rect.center << endl; // cout << "area ratio: " << cur_contour_area / cur_size.area() << '\t' << cur_rect.center << endl;
// cout<<endl;
// RotatedRect cur_rect = minAreaRect(flow_strip_contour);
// Size2f cur_size = cur_rect.size;
// float length = cur_size.height > cur_size.width ? cur_size.height : cur_size.width;
// float width = cur_size.height < cur_size.width ? cur_size.height : cur_size.width;
// if (length / width > 2.5 && width > 7 && width<40) {
// cout << cur_rect.center << endl;
// flow_strip = cv::minAreaRect(flow_strip_contour);
// cout << "flow strip area: " << length << '\t' << width << endl;
// }
// cout << cur_rect.center << endl;
} }
} }
// cout << "flow strip cnt: " << flow_strips.size() << endl;
if (flow_strips.empty()) { if (flow_strips.empty()) {
if (show_info)cout << "flow strip false!" << endl; if (show_info)cout << "flow strip false!" << endl;
// waitKey(0); // waitKey(0);
@@ -327,6 +316,97 @@ bool Energy::findFlowStrip(const cv::Mat src) {
} }
//----------------------------------------------------------------------------------------------------------------------
// 此函数用于弱识别寻找流动条
// ---------------------------------------------------------------------------------------------------------------------
bool Energy::findFlowStripWeak(const cv::Mat src) {
if (src.empty()) {
if (show_info) cout << "empty!" << endl;
return false;
}
cv::Mat src_bin;
src_bin = src.clone();
if (src_bin.type() == CV_8UC1) // 黑白图像
{
cvtColor(src_bin, src_bin, COLOR_GRAY2RGB);
}
std::vector<cv::RotatedRect> candidate_armors = armors;
for (auto &candidate_armor: candidate_armors) {
Point2f vertices[4];
candidate_armor.size.height *= 1.3;
candidate_armor.size.width *= 1.3;
candidate_armor.points(vertices); //计算矩形的4个顶点
for (int i = 0; i < 4; i++) {
line(src_bin, vertices[i], vertices[(i + 1) % 4], Scalar(0, 0, 0), 20);
}
}
cvtColor(src_bin, src_bin, CV_BGR2GRAY);//若读取三通道视频文件,需转换为单通道
FlowStripStruct(src_bin);//图像膨胀,防止图像断开并更方便寻找
if (show_process)imshow("weak struct", src_bin);
// waitKey(0);
std::vector<vector<Point> > flow_strip_contours;
findContours(src_bin, flow_strip_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
for (auto &flow_strip_contour : flow_strip_contours) {
if (!isValidFlowStripContour(flow_strip_contour)) {
continue;
}
flow_strips.emplace_back(cv::minAreaRect(flow_strip_contour));
// RotatedRect cur_rect = minAreaRect(flow_strip_contour);
// Size2f cur_size = cur_rect.size;
// float length = cur_size.height > cur_size.width ? cur_size.height : cur_size.width;
// float width = cur_size.height < cur_size.width ? cur_size.height : cur_size.width;
// double cur_contour_area = contourArea(flow_strip_contour);
// float length_width_ratio = length / width;
// cout << "area: " << cur_contour_area << '\t' << endl;
// cout << "length: " << length << '\t' << "width: " << width << '\t' << cur_rect.center << endl;
// cout << "HW: " << length_width_ratio << '\t' << cur_rect.center << endl;
// cout << "area ratio: " << cur_contour_area / cur_size.area() << '\t' << cur_rect.center << endl;
// cout << endl;
}
// cout << "size: " << flow_strips.size() << endl;
if (flow_strips.empty()) {
if (show_info)cout << "weak flow strip false!" << endl;
// waitKey(0);
return false;
} else {
for (const auto &candidate_flow_strip: flow_strips) {
for (const auto &candidate_armor: armors) {
if (pointDistance(candidate_flow_strip.center, candidate_armor.center) <
energy_part_param_.STRIP_ARMOR_DISTANCE_MIN ||
pointDistance(candidate_flow_strip.center, candidate_armor.center) >
energy_part_param_.STRIP_ARMOR_DISTANCE_MAX) {
continue;
}
float angle_armor = candidate_armor.size.width > candidate_armor.size.height ? candidate_armor.angle :
candidate_armor.angle - 90;
float angle_strip = candidate_flow_strip.size.width > candidate_flow_strip.size.height ?
candidate_flow_strip.angle: candidate_flow_strip.angle - 90;
if (abs(angle_armor - angle_strip) < 60 || abs(angle_armor - angle_strip) > 120) {
continue;
}
target_armor = candidate_armor;
target_point = candidate_armor.center;
flow_strip = candidate_flow_strip;
return true;
}
}
if (show_info)cout << "weak flow strip false!" << endl;
// waitKey(0);
return false;
}
}
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数用于框取中心R的寻找范围 // 此函数用于框取中心R的寻找范围
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------

View File

@@ -100,8 +100,8 @@ bool Energy::isValidArmorContour(const vector<cv::Point> &armor_contour) {
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
bool Energy::isValidCenterRContour(const vector<cv::Point> &center_R_contour) { bool Energy::isValidCenterRContour(const vector<cv::Point> &center_R_contour) {
double cur_contour_area = contourArea(center_R_contour); double cur_contour_area = contourArea(center_R_contour);
if (cur_contour_area > energy_part_param_.ARMOR_CONTOUR_AREA_MAX || if (cur_contour_area > energy_part_param_.CENTER_R_CONTOUR_AREA_MAX ||
cur_contour_area < energy_part_param_.ARMOR_CONTOUR_AREA_MIN) { cur_contour_area < energy_part_param_.CENTER_R_CONTOUR_AREA_MIN) {
//cout<<cur_contour_area<<" "<<energy_fan_param_.CONTOUR_AREA_MIN<<" "<<energy_fan_param_.CONTOUR_AREA_MAX<<endl; //cout<<cur_contour_area<<" "<<energy_fan_param_.CONTOUR_AREA_MIN<<" "<<energy_fan_param_.CONTOUR_AREA_MAX<<endl;
//cout<<"area fail."<<endl; //cout<<"area fail."<<endl;
return false; return false;

View File

@@ -78,11 +78,15 @@ void Energy::runBig(cv::Mat &gimbal_src) {
if (show_process)imshow("bin", gimbal_src); if (show_process)imshow("bin", gimbal_src);
if (findArmors(gimbal_src) < 1)return; if (findArmors(gimbal_src) < 1)return;
if (show_energy)showArmors("armor", gimbal_src); if (show_energy)showArmors("armor", gimbal_src);
if (!findFlowStripFan(gimbal_src))return; if (!findFlowStripFan(gimbal_src)) {
if (!findFlowStripWeak(gimbal_src))return;
} else {
if (show_energy)showFlowStripFan("strip fan", gimbal_src);
if (!findTargetInFlowStripFan()) return; if (!findTargetInFlowStripFan()) return;
if (!findFlowStrip(gimbal_src))return; if (!findFlowStrip(gimbal_src))return;
}
if (!findCenterROI(gimbal_src))return; if (!findCenterROI(gimbal_src))return;
if (show_energy)showFlowStripFan("strip", gimbal_src); if (show_energy)showFlowStrip("strip", gimbal_src);
if (!findCenterR(gimbal_src))return; if (!findCenterR(gimbal_src))return;
if (show_energy)showCenterR("R", gimbal_src); if (show_energy)showCenterR("R", gimbal_src);

View File

@@ -19,28 +19,23 @@ void Energy::sendEnergy() {
sum_yaw += yaw_rotation; sum_yaw += yaw_rotation;
sum_pitch += pitch_rotation; sum_pitch += pitch_rotation;
MINMAX(sum_yaw, -100, 100); MINMAX(sum_yaw, -100, 100);
MINMAX(sum_pitch, -100, 100); MINMAX(sum_pitch, -100, 100);\
// float KP = 4.5; yaw_rotation = BIG_YAW_AIM_KP * yaw_rotation + BIG_YAW_AIM_KI * sum_yaw + BIG_YAW_AIM_KD * (yaw_rotation - last_yaw);
// if(abs(yaw_rotation)<0.3)KP=0.1; pitch_rotation = BIG_PITCH_AIM_KP * pitch_rotation + BIG_PITCH_AIM_KI * sum_pitch +
// else if(abs(yaw_rotation)<0.5)KP=0.1; BIG_PITCH_AIM_KD * (pitch_rotation - last_pitch);
// else KP = 0.1; " << yaw_rotation << '\t' << "pitch: " << pitch_rotation << endl;
yaw_rotation = YAW_AIM_KP * yaw_rotation + YAW_AIM_KI * sum_yaw + YAW_AIM_KD * (yaw_rotation - last_yaw);
pitch_rotation = PITCH_AIM_KP * pitch_rotation + PITCH_AIM_KI * sum_pitch +
PITCH_AIM_KD * (pitch_rotation - last_pitch);
} else if (is_chassis) { } else if (is_chassis) {
sum_yaw += yaw_rotation - mcuData.curr_yaw; sum_yaw += yaw_rotation - mcuData.curr_yaw;
sum_pitch += pitch_rotation - mcuData.curr_pitch; sum_pitch += pitch_rotation - mcuData.curr_pitch;
yaw_rotation = YAW_AIM_KP * (yaw_rotation - mcuData.curr_yaw) + YAW_AIM_KI * sum_yaw; yaw_rotation = BIG_YAW_AIM_KP * (yaw_rotation - mcuData.curr_yaw) + BIG_YAW_AIM_KI * sum_yaw;
pitch_rotation = PITCH_AIM_KP * (pitch_rotation - mcuData.curr_pitch) + PITCH_AIM_KI * sum_pitch; pitch_rotation = BIG_PITCH_AIM_KP * (pitch_rotation - mcuData.curr_pitch) + BIG_PITCH_AIM_KI * sum_pitch;
} }
} else if (is_small){ } else if (is_small){
sum_yaw += yaw_rotation; sum_yaw += yaw_rotation;
sum_pitch += pitch_rotation; sum_pitch += pitch_rotation;
MINMAX(sum_yaw, -100, 100); MINMAX(sum_yaw, -100, 100);
MINMAX(sum_pitch, -100, 100); MINMAX(sum_pitch, -100, 100);
yaw_rotation = 2.5 * yaw_rotation + 0.08 * sum_yaw + 1.5 * (yaw_rotation - last_yaw); yaw_rotation = SMALL_YAW_AIM_KP * yaw_rotation + SMALL_YAW_AIM_KD * (yaw_rotation - last_yaw);
pitch_rotation = 2.4 * pitch_rotation + 0.07 * sum_pitch + pitch_rotation = SMALL_PITCH_AIM_KP * pitch_rotation + SMALL_PITCH_AIM_KD * (pitch_rotation - last_pitch);
1.3 * (pitch_rotation - last_pitch);
} }
if (change_target) { if (change_target) {

View File

@@ -126,7 +126,7 @@ void Energy::showCenterR(std::string windows_name, const cv::Mat src) {
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数用于显示图像中所有流动条 // 此函数用于显示图像中流动条扇叶
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
void Energy::showFlowStripFan(std::string windows_name, const cv::Mat src) { void Energy::showFlowStripFan(std::string windows_name, const cv::Mat src) {
if (src.empty())return; if (src.empty())return;
@@ -145,7 +145,23 @@ void Energy::showFlowStripFan(std::string windows_name, const cv::Mat src) {
flow_strip_fan.points(strip_fan_vertices); //计算矩形的4个顶点for (int i = 0; i < 4; i++) flow_strip_fan.points(strip_fan_vertices); //计算矩形的4个顶点for (int i = 0; i < 4; i++)
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
line(image2show, strip_fan_vertices[i], strip_fan_vertices[(i + 1) % 4], Scalar(127, 127, 255), 2); line(image2show, strip_fan_vertices[i], strip_fan_vertices[(i + 1) % 4], Scalar(127, 127, 255), 2);
}
//----------------------------------------------------------------------------------------------------------------------
// 此函数用于显示图像中流动条扇叶
// ---------------------------------------------------------------------------------------------------------------------
void Energy::showFlowStrip(std::string windows_name, const cv::Mat src) {
if (src.empty())return;
static Mat image2show;
if (src.type() == CV_8UC1) // 黑白图像
{
cvtColor(src, image2show, COLOR_GRAY2RGB);
} else if (src.type() == CV_8UC3) //RGB 彩色
{
image2show = src.clone();
}
Point2f strip_vertices[4]; //定义矩形的4个顶点 Point2f strip_vertices[4]; //定义矩形的4个顶点
flow_strip.points(strip_vertices); //计算矩形的4个顶点 flow_strip.points(strip_vertices); //计算矩形的4个顶点

View File

@@ -124,6 +124,7 @@ int main(int argc, char *argv[]) {
if (show_origin) showOrigin(gimbal_src, chassis_src);//显示原始图像 if (show_origin) showOrigin(gimbal_src, chassis_src);//显示原始图像
// energy.runBig(gimbal_src, chassis_src); // energy.runBig(gimbal_src, chassis_src);
energy.runBig(gimbal_src); energy.runBig(gimbal_src);
if (show_energy || show_process) waitKey(1);
} else if (mcuData.state == SMALL_ENERGY_STATE) { } else if (mcuData.state == SMALL_ENERGY_STATE) {
if (last_state != SMALL_ENERGY_STATE) { if (last_state != SMALL_ENERGY_STATE) {
LOGM(STR_CTR(WORD_GREEN, "Start Small Energy!")); LOGM(STR_CTR(WORD_GREEN, "Start Small Energy!"));
@@ -148,6 +149,7 @@ int main(int argc, char *argv[]) {
if (save_video) saveVideos(gimbal_src);//保存视频 if (save_video) saveVideos(gimbal_src);//保存视频
if (show_origin) showOrigin(gimbal_src);//显示原始图像 if (show_origin) showOrigin(gimbal_src);//显示原始图像
energy.runSmall(gimbal_src); energy.runSmall(gimbal_src);
if (show_energy || show_process) waitKey(1);
} else { // 自瞄模式 } else { // 自瞄模式
if (last_state != ARMOR_STATE) { if (last_state != ARMOR_STATE) {
LOGM(STR_CTR(WORD_RED, "Start Armor!")); LOGM(STR_CTR(WORD_RED, "Start Armor!"));

View File

@@ -29,25 +29,37 @@
#define ARMOR_CAMERA_GAIN (30) #define ARMOR_CAMERA_GAIN (30)
#endif #endif
#ifndef ENERGY_CAMERA_GAIN #ifndef ENERGY_CAMERA_GAIN
#define ENERGY_CAMERA_GAIN (30) #define ENERGY_CAMERA_GAIN (20)
#endif #endif
#ifndef YAW_AIM_KD #ifndef SMALL_YAW_AIM_KD
#define YAW_AIM_KD (0) #define SMALL_YAW_AIM_KD (1.5)
#endif #endif
#ifndef YAW_AIM_KP #ifndef SMALL_YAW_AIM_KP
#define YAW_AIM_KP (6) #define SMALL_YAW_AIM_KP (2.5)
#endif #endif
#ifndef YAW_AIM_KI #ifndef SMALL_PITCH_AIM_KD
#define YAW_AIM_KI (0.1) #define SMALL_PITCH_AIM_KD (1.3)
#endif #endif
#ifndef PITCH_AIM_KD #ifndef SMALL_PITCH_AIM_KP
#define PITCH_AIM_KD (0) #define SMALL_PITCH_AIM_KP (2.4)
#endif #endif
#ifndef PITCH_AIM_KP #ifndef BIG_YAW_AIM_KD
#define PITCH_AIM_KP (6) #define BIG_YAW_AIM_KD (0.7)
#endif #endif
#ifndef PITCH_AIM_KI #ifndef BIG_YAW_AIM_KP
#define PITCH_AIM_KI (0.1) #define BIG_YAW_AIM_KP (4.5)
#endif
#ifndef BIG_YAW_AIM_KI
#define BIG_YAW_AIM_KI (0.1)
#endif
#ifndef BIG_PITCH_AIM_KD
#define BIG_PITCH_AIM_KD (0.7)
#endif
#ifndef BIG_PITCH_AIM_KP
#define BIG_PITCH_AIM_KP (4.5)
#endif
#ifndef BIG_PITCH_AIM_KI
#define BIG_PITCH_AIM_KI (0.1)
#endif #endif
#ifndef COMPENSATE_YAW #ifndef COMPENSATE_YAW
#define COMPENSATE_YAW (5) #define COMPENSATE_YAW (5)