Merge branch 'master' of /home/sjturm/Desktop/RM_auto-aim with conflicts.

This commit is contained in:
xinyang
2019-08-04 08:17:38 +08:00
parent a68a051ce7
commit cbadab7f83
5 changed files with 558 additions and 512 deletions

View File

@@ -13,7 +13,7 @@ static double boxDistance(const cv::Rect2d &a, const cv::Rect2d &b) {
return sqrt(dist.x * dist.x + dist.y * dist.y); return sqrt(dist.x * dist.x + dist.y * dist.y);
} }
template <int length> template<int length>
static double mean(RoundQueue<double, length> &vec) { static double mean(RoundQueue<double, length> &vec) {
double sum = 0; double sum = 0;
for (int i = 0; i < vec.size(); i++) { for (int i = 0; i < vec.size(); i++) {
@@ -33,13 +33,14 @@ ArmorFinder::BoxRatioChangeType ArmorFinder::getRatioChangeType(RoundQueue<doubl
} }
} }
/*
void ArmorFinder::antiTop() { void ArmorFinder::antiTop() {
if (armor_box.rect == cv::Rect2d()) return; if (target_box.rect == cv::Rect2d()) return;
uint16_t shoot_delay = 0; uint16_t shoot_delay = 0;
auto interval = getTimeIntervalms(frame_time, last_front_time); auto interval = getTimeIntervalms(frame_time, last_front_time);
box_ratioes.push(armor_box.rect.width / armor_box.rect.height); box_ratioes.push(target_box.rect.width / target_box.rect.height);
auto change_type = getRatioChangeType(box_ratioes); auto change_type = getRatioChangeType(box_ratioes);
auto orientation = armor_box.getOrientation(); auto orientation = target_box.getOrientation();
if (interval > 700) { if (interval > 700) {
anti_top_cnt = 0; anti_top_cnt = 0;
if (anti_top_state == ANTI_TOP) { if (anti_top_state == ANTI_TOP) {
@@ -76,4 +77,42 @@ void ArmorFinder::antiTop() {
sendBoxPosition(shoot_delay); sendBoxPosition(shoot_delay);
} }
} }
*/
void ArmorFinder::antiTop() {
if (target_box.rect == cv::Rect2d()) return;
uint16_t shoot_delay = 0;
auto interval = getTimeIntervalms(frame_time, last_front_time);
if (anti_top_state == ANTI_TOP && interval > 500) {
anti_top_state = NORMAL;
LOGM(STR_CTR(WORD_YELLOW, "switch to normal"));
}
if (last_box.rect != cv::Rect2d() &&
getPointLength(last_box.getCenter() - target_box.getCenter()) > last_box.rect.height * 1.0) {
LOGM("switch! %lf", getPointLength(last_box.getCenter() - target_box.getCenter()) / last_box.rect.height);
if (150 < interval && interval < 500) {
if (anti_top_state == ANTI_TOP) {
top_periodms.push(interval);
LOGM(STR_CTR(WORD_LIGHT_GREEN, "top period: %.1lf ms"), interval);
systime curr_time;
getsystime(curr_time);
auto calculate_time = getTimeIntervalms(curr_time, frame_time);
shoot_delay = mean(top_periodms) - calculate_time;
sendBoxPosition(shoot_delay);
} else {
if (++anti_top_cnt > 4) {
anti_top_state = ANTI_TOP;
LOGM(STR_CTR(WORD_CYAN, "switch to anti-top"));
}
}
}
last_front_time = frame_time;
}
if (anti_top_state == NORMAL) {
sendBoxPosition(0);
} else if (interval < top_periodms[-1] * 0.10) {
sendBoxPosition(0);
}
last_box = target_box;
}

View File

@@ -324,9 +324,9 @@ int Classifier::operator()(const cv::Mat &image) {
// cout << result << "==============" <<endl; // cout << result << "==============" <<endl;
MatrixXd::Index minRow, minCol; MatrixXd::Index minRow, minCol;
result.maxCoeff(&minRow, &minCol); result.maxCoeff(&minRow, &minCol);
if(result(minRow, minCol) > 0.90){ if(result(minRow, minCol) > 0.50){
return minRow; return minRow;
}else{ }else{
return 0; return 0;
} }
} }

View File

@@ -53,9 +53,9 @@ void Energy::ArmorStruct(cv::Mat &src) {
// imshow("dilate_1", src); // imshow("dilate_1", src);
erode(src,src, element_erode_1); erode(src,src, element_erode_1);
// imshow("erode_1", src); // imshow("erode_1", src);
erode(src,src, element_erode_2); // erode(src,src, element_erode_2);
// imshow("erode_2", src); // imshow("erode_2", src);
erode(src,src, element_erode_3); // erode(src,src, element_erode_3);
// imshow("erode_3", src); // imshow("erode_3", src);
// dilate(src, src, element_dilate_2); // dilate(src, src, element_dilate_2);

View File

@@ -1,426 +1,426 @@
// //
// Created by xixiliadorabarry on 1/24/19. // Created by xixiliadorabarry on 1/24/19.
// //
#include "energy/energy.h" #include "energy/energy.h"
#include "log.h" #include "log.h"
using namespace cv; using namespace cv;
using std::cout; using std::cout;
using std::endl; using std::endl;
using std::vector; using std::vector;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数用于寻找图像内所有的大风车扇叶 // 此函数用于寻找图像内所有的大风车扇叶
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
int Energy::findFans(const cv::Mat src) { int Energy::findFans(const cv::Mat src) {
if (src.empty()) { if (src.empty()) {
if (show_info) cout << "empty!" << endl; if (show_info) cout << "empty!" << endl;
return 0; return 0;
} }
static Mat src_bin; static Mat src_bin;
src_bin = src.clone(); src_bin = src.clone();
if (src.type() == CV_8UC3) { if (src.type() == CV_8UC3) {
cvtColor(src_bin, src_bin, CV_BGR2GRAY);//若读取三通道视频文件,需转换为单通道 cvtColor(src_bin, src_bin, CV_BGR2GRAY);//若读取三通道视频文件,需转换为单通道
} }
std::vector<vector<Point> > fan_contours; std::vector<vector<Point> > fan_contours;
FanStruct(src_bin);//图像膨胀,防止图像断开并更方便寻找 FanStruct(src_bin);//图像膨胀,防止图像断开并更方便寻找
if (show_process)imshow("fan struct", src_bin); if (show_process)imshow("fan struct", src_bin);
findContours(src_bin, fan_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); findContours(src_bin, fan_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
for (auto &fan_contour : fan_contours) { for (auto &fan_contour : fan_contours) {
if (!isValidFanContour(src_bin, fan_contour)) { if (!isValidFanContour(src_bin, fan_contour)) {
continue; continue;
} }
fans.emplace_back(cv::minAreaRect(fan_contour)); fans.emplace_back(cv::minAreaRect(fan_contour));
// RotatedRect cur_rect = minAreaRect(fan_contour); // RotatedRect cur_rect = minAreaRect(fan_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;
// double cur_contour_area = contourArea(fan_contour); // double cur_contour_area = contourArea(fan_contour);
// double non_zero_rate = nonZeroRateOfRotateRect(src_bin, cur_rect); // double non_zero_rate = nonZeroRateOfRotateRect(src_bin, cur_rect);
// if (length > 60 && width > 20) { // if (length > 60 && width > 20) {
// fans.emplace_back(cv::minAreaRect(fan_contour)); // fans.emplace_back(cv::minAreaRect(fan_contour));
// cout << cur_rect.center << endl; // cout << cur_rect.center << endl;
// cout << "fan area: " << length << '\t' << width << endl; // cout << "fan area: " << length << '\t' << width << endl;
// cout << "non zero: " << nonZeroRateOfRotateRect(src_bin, cur_rect) << endl; // cout << "non zero: " << nonZeroRateOfRotateRect(src_bin, cur_rect) << endl;
// cout << "rate: " << cur_contour_area / cur_size.area() << endl; // cout << "rate: " << cur_contour_area / cur_size.area() << endl;
// } // }
} }
// showFans("fan", src_bin); // showFans("fan", src_bin);
if (fans.size() < last_fans_cnt) { if (fans.size() < last_fans_cnt) {
last_fans_cnt = static_cast<int>(fans.size()); last_fans_cnt = static_cast<int>(fans.size());
return -1;//寻找到的扇叶比上一帧少,说明该帧有误,返回-1 return -1;//寻找到的扇叶比上一帧少,说明该帧有误,返回-1
} }
last_fans_cnt = static_cast<int>(fans.size()); last_fans_cnt = static_cast<int>(fans.size());
return static_cast<int>(fans.size()); return static_cast<int>(fans.size());
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数用于寻找图像内所有的大风车装甲板模块 // 此函数用于寻找图像内所有的大风车装甲板模块
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
int Energy::findArmors(const cv::Mat src) { int Energy::findArmors(const cv::Mat src) {
if (src.empty()) { if (src.empty()) {
if (show_info) cout << "empty!" << endl; if (show_info) cout << "empty!" << endl;
return 0; return 0;
} }
static Mat src_bin; static Mat src_bin;
src_bin = src.clone(); src_bin = src.clone();
if (src.type() == CV_8UC3) { if (src.type() == CV_8UC3) {
cvtColor(src_bin, src_bin, CV_BGR2GRAY);//若读取三通道视频文件,需转换为单通道 cvtColor(src_bin, src_bin, CV_BGR2GRAY);//若读取三通道视频文件,需转换为单通道
} }
std::vector<vector<Point> > armor_contours; std::vector<vector<Point> > armor_contours;
std::vector<vector<Point> > armor_contours_external;//用总轮廓减去外轮廓,只保留内轮廓,除去流动条的影响。 std::vector<vector<Point> > armor_contours_external;//用总轮廓减去外轮廓,只保留内轮廓,除去流动条的影响。
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); findContours(src_bin, armor_contours_external, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
for (int i = 0; i < armor_contours_external.size(); i++)//去除外轮廓 for (int i = 0; i < armor_contours_external.size(); i++)//去除外轮廓
{ {
unsigned long external_contour_size = armor_contours_external[i].size(); unsigned long external_contour_size = armor_contours_external[i].size();
for (int j = 0; j < armor_contours.size(); j++) { for (int j = 0; j < armor_contours.size(); j++) {
unsigned long all_size = armor_contours[j].size(); unsigned long all_size = armor_contours[j].size();
if (external_contour_size == all_size) { if (external_contour_size == all_size) {
swap(armor_contours[j], armor_contours[armor_contours.size() - 1]); swap(armor_contours[j], armor_contours[armor_contours.size() - 1]);
armor_contours.pop_back(); armor_contours.pop_back();
break; 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;
// double cur_contour_area = contourArea(armor_contour); // double cur_contour_area = contourArea(armor_contour);
// float length_width_ratio = length / width; // float length_width_ratio = length / width;
// cout << "area: " << cur_contour_area << '\t' << endl; // 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; // cout<<endl;
} }
if (show_info) { if (show_info) {
// 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());
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数用于寻找图像内大风车中心字母“R” // 此函数用于寻找图像内大风车中心字母“R”
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
bool Energy::findCenterR(const cv::Mat src) { bool Energy::findCenterR(const cv::Mat src) {
if (src.empty()) { if (src.empty()) {
if (show_info) cout << "empty!" << endl; if (show_info) cout << "empty!" << endl;
return false; return false;
} }
static Mat src_bin; static Mat src_bin;
src_bin = src.clone(); src_bin = src.clone();
if (src.type() == CV_8UC3) { if (src.type() == CV_8UC3) {
cvtColor(src_bin, src_bin, CV_BGR2GRAY); cvtColor(src_bin, src_bin, CV_BGR2GRAY);
} }
std::vector<vector<Point> > center_R_contours; std::vector<vector<Point> > center_R_contours;
CenterRStruct(src_bin); CenterRStruct(src_bin);
if (show_process)imshow("R struct", src_bin); if (show_process)imshow("R struct", src_bin);
findContours(src_bin, center_R_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); findContours(src_bin, center_R_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
for (auto &center_R_contour : center_R_contours) { for (auto &center_R_contour : center_R_contours) {
if (!isValidCenterRContour(center_R_contour)) { if (!isValidCenterRContour(center_R_contour)) {
continue; continue;
} }
centerR = cv::minAreaRect(center_R_contour); centerR = cv::minAreaRect(center_R_contour);
float target_length = float target_length =
target_armor.size.height > target_armor.size.width ? target_armor.size.height : target_armor.size.width; target_armor.size.height > target_armor.size.width ? target_armor.size.height : target_armor.size.width;
circle_center_point = centerR.center; circle_center_point = centerR.center;
circle_center_point.y += target_length / 7.5;//实际最小二乘得到的中心在R的下方 circle_center_point.y += target_length / 7.5;//实际最小二乘得到的中心在R的下方
// RotatedRect cur_rect = minAreaRect(center_R_contour); // RotatedRect cur_rect = minAreaRect(center_R_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;
// double cur_contour_area = contourArea(center_R_contour); // double cur_contour_area = contourArea(center_R_contour);
// float length_width_ratio = length / width; // float length_width_ratio = length / width;
// cout << "area: " << cur_contour_area << '\t' << endl; // 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; // cout<<endl;
return true; return true;
} }
if (show_info)cout << "find center R false!" << endl; if (show_info)cout << "find center R false!" << endl;
// cv::waitKey(0); // cv::waitKey(0);
return false; return false;
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数用于判断找到的矩形候选区是否为含流动条的扇叶 // 此函数用于判断找到的矩形候选区是否为含流动条的扇叶
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
bool Energy::findFlowStripFan(const cv::Mat src) { bool Energy::findFlowStripFan(const cv::Mat src) {
if (src.empty()) { if (src.empty()) {
if (show_info) cout << "empty!" << endl; if (show_info) cout << "empty!" << endl;
return false; return false;
} }
static Mat src_bin; static Mat src_bin;
static Mat src_copy; static Mat src_copy;
src_bin = src.clone(); src_bin = src.clone();
src_copy = src.clone(); src_copy = src.clone();
if (src.type() == CV_8UC3) { if (src.type() == CV_8UC3) {
cvtColor(src_bin, src_bin, CV_BGR2GRAY);//若读取三通道视频文件,需转换为单通道 cvtColor(src_bin, src_bin, CV_BGR2GRAY);//若读取三通道视频文件,需转换为单通道
} }
std::vector<vector<Point> > flow_strip_fan_contours; std::vector<vector<Point> > flow_strip_fan_contours;
FlowStripFanStruct(src_bin);//图像膨胀,防止图像断开并更方便寻找 FlowStripFanStruct(src_bin);//图像膨胀,防止图像断开并更方便寻找
if (show_process)imshow("flow strip fan struct", src_bin); if (show_process)imshow("flow strip fan struct", src_bin);
findContours(src_bin, flow_strip_fan_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); findContours(src_bin, flow_strip_fan_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
std::vector<cv::RotatedRect> candidate_flow_strip_fans; std::vector<cv::RotatedRect> candidate_flow_strip_fans;
for (auto &flow_strip_fan_contour : flow_strip_fan_contours) { for (auto &flow_strip_fan_contour : flow_strip_fan_contours) {
if (!isValidFlowStripFanContour(src_bin, flow_strip_fan_contour)) { if (!isValidFlowStripFanContour(src_bin, flow_strip_fan_contour)) {
continue; continue;
} }
flow_strip_fans.emplace_back(cv::minAreaRect(flow_strip_fan_contour)); flow_strip_fans.emplace_back(cv::minAreaRect(flow_strip_fan_contour));
// RotatedRect cur_rect = minAreaRect(flow_strip_fan_contour); // RotatedRect cur_rect = minAreaRect(flow_strip_fan_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;
// double cur_contour_area = contourArea(flow_strip_fan_contour); // double cur_contour_area = contourArea(flow_strip_fan_contour);
// float length_width_ratio = length / width; // float length_width_ratio = length / width;
// cout << "area: " << cur_contour_area << '\t' << endl; // 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; // cout<<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); // waitKey(0);
return false; return false;
} }
return true; return true;
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数用于寻找流动条 // 此函数用于寻找流动条
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
bool Energy::findFlowStrip(const cv::Mat src) { bool Energy::findFlowStrip(const cv::Mat src) {
if (src.empty()) { if (src.empty()) {
if (show_info) cout << "empty!" << endl; if (show_info) cout << "empty!" << endl;
return false; return false;
} }
cv::Mat src_bin; cv::Mat src_bin;
src_bin = src.clone(); src_bin = src.clone();
if (src_bin.type() == CV_8UC1) // 黑白图像 if (src_bin.type() == CV_8UC1) // 黑白图像
{ {
cvtColor(src_bin, src_bin, COLOR_GRAY2RGB); cvtColor(src_bin, src_bin, COLOR_GRAY2RGB);
} }
std::vector<cv::RotatedRect> candidate_target_armors = target_armors; std::vector<cv::RotatedRect> candidate_target_armors = target_armors;
for (auto &candidate_target_armor: candidate_target_armors) { for (auto &candidate_target_armor: candidate_target_armors) {
Point2f vertices[4]; Point2f vertices[4];
candidate_target_armor.size.height *= 1.3; candidate_target_armor.size.height *= 1.3;
candidate_target_armor.size.width *= 1.3; candidate_target_armor.size.width *= 1.3;
candidate_target_armor.points(vertices); //计算矩形的4个顶点 candidate_target_armor.points(vertices); //计算矩形的4个顶点
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
line(src_bin, vertices[i], vertices[(i + 1) % 4], Scalar(0, 0, 0), 20); line(src_bin, vertices[i], vertices[(i + 1) % 4], Scalar(0, 0, 0), 20);
} }
} }
cvtColor(src_bin, src_bin, CV_BGR2GRAY);//若读取三通道视频文件,需转换为单通道 cvtColor(src_bin, src_bin, CV_BGR2GRAY);//若读取三通道视频文件,需转换为单通道
FlowStripStruct(src_bin);//图像膨胀,防止图像断开并更方便寻找 FlowStripStruct(src_bin);//图像膨胀,防止图像断开并更方便寻找
if (show_process)imshow("flow strip struct", src_bin); if (show_process)imshow("flow strip struct", src_bin);
std::vector<vector<Point> > flow_strip_contours; std::vector<vector<Point> > flow_strip_contours;
findContours(src_bin, flow_strip_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); findContours(src_bin, flow_strip_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
for (auto candidate_flow_strip_fan: flow_strip_fans) { for (auto candidate_flow_strip_fan: flow_strip_fans) {
for (auto &flow_strip_contour : flow_strip_contours) { for (auto &flow_strip_contour : flow_strip_contours) {
if (!isValidFlowStripContour(flow_strip_contour)) { if (!isValidFlowStripContour(flow_strip_contour)) {
continue; continue;
} }
std::vector<cv::Point2f> intersection; std::vector<cv::Point2f> intersection;
RotatedRect cur_rect = minAreaRect(flow_strip_contour); RotatedRect cur_rect = minAreaRect(flow_strip_contour);
if (rotatedRectangleIntersection(cur_rect, candidate_flow_strip_fan, intersection) == 0) { if (rotatedRectangleIntersection(cur_rect, candidate_flow_strip_fan, intersection) == 0) {
continue; continue;
} else if (contourArea(intersection) > energy_part_param_.FLOW_STRIP_CONTOUR_INTERSETION_AREA_MIN) { } else if (contourArea(intersection) > energy_part_param_.FLOW_STRIP_CONTOUR_INTERSETION_AREA_MIN) {
flow_strips.emplace_back(cv::minAreaRect(flow_strip_contour)); flow_strips.emplace_back(cv::minAreaRect(flow_strip_contour));
// cout << "intersection: " << contourArea(intersection) << '\t' << cur_rect.center << endl; // cout << "intersection: " << contourArea(intersection) << '\t' << cur_rect.center << endl;
} else { } else {
continue; continue;
} }
// 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;
// double cur_contour_area = contourArea(flow_strip_contour); // double cur_contour_area = contourArea(flow_strip_contour);
// float length_width_ratio = length / width; // float length_width_ratio = length / width;
// cout << "area: " << cur_contour_area << '\t' << endl; // 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; // cout<<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);
return false; return false;
} else if (flow_strips.size() > 1) { } else if (flow_strips.size() > 1) {
if (show_info)cout << "Too many flow strips!" << endl; if (show_info)cout << "Too many flow strips!" << endl;
// waitKey(0); // waitKey(0);
return false; return false;
} else { } else {
flow_strip = flow_strips.at(0); flow_strip = flow_strips.at(0);
for (auto &candidate_flow_strip_fan: flow_strip_fans) { for (auto &candidate_flow_strip_fan: flow_strip_fans) {
std::vector<cv::Point2f> intersection; std::vector<cv::Point2f> intersection;
if (rotatedRectangleIntersection(flow_strip, candidate_flow_strip_fan, intersection) == 0) { if (rotatedRectangleIntersection(flow_strip, candidate_flow_strip_fan, intersection) == 0) {
continue; continue;
} else if (contourArea(intersection) > energy_part_param_.FLOW_STRIP_CONTOUR_INTERSETION_AREA_MIN) { } else if (contourArea(intersection) > energy_part_param_.FLOW_STRIP_CONTOUR_INTERSETION_AREA_MIN) {
flow_strip_fan = candidate_flow_strip_fan; flow_strip_fan = candidate_flow_strip_fan;
} }
} }
int i = 0; int i = 0;
for (i = 0; i < target_armors.size(); ++i) { for (i = 0; i < target_armors.size(); ++i) {
std::vector<cv::Point2f> intersection; std::vector<cv::Point2f> intersection;
if (rotatedRectangleIntersection(target_armors.at(i), flow_strip_fan, intersection) == 0) if (rotatedRectangleIntersection(target_armors.at(i), flow_strip_fan, intersection) == 0)
continue;//返回0表示没有重合面积 continue;//返回0表示没有重合面积
double cur_contour_area = contourArea(intersection); double cur_contour_area = contourArea(intersection);
if (cur_contour_area > energy_part_param_.TARGET_INTERSETION_CONTOUR_AREA_MIN) { if (cur_contour_area > energy_part_param_.TARGET_INTERSETION_CONTOUR_AREA_MIN) {
target_armor = target_armors.at(i); target_armor = target_armors.at(i);
target_point = target_armor.center; target_point = target_armor.center;
} }
} }
} }
return true; return true;
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数用于弱识别寻找流动条 // 此函数用于弱识别寻找流动条
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
bool Energy::findFlowStripWeak(const cv::Mat src) { bool Energy::findFlowStripWeak(const cv::Mat src) {
if (src.empty()) { if (src.empty()) {
if (show_info) cout << "empty!" << endl; if (show_info) cout << "empty!" << endl;
return false; return false;
} }
cv::Mat src_bin; cv::Mat src_bin;
src_bin = src.clone(); src_bin = src.clone();
if (src_bin.type() == CV_8UC1) // 黑白图像 if (src_bin.type() == CV_8UC1) // 黑白图像
{ {
cvtColor(src_bin, src_bin, COLOR_GRAY2RGB); cvtColor(src_bin, src_bin, COLOR_GRAY2RGB);
} }
std::vector<cv::RotatedRect> candidate_armors = armors; std::vector<cv::RotatedRect> candidate_armors = armors;
for (auto &candidate_armor: candidate_armors) { for (auto &candidate_armor: candidate_armors) {
Point2f vertices[4]; Point2f vertices[4];
candidate_armor.size.height *= 1.3; candidate_armor.size.height *= 1.3;
candidate_armor.size.width *= 1.3; candidate_armor.size.width *= 1.3;
candidate_armor.points(vertices); //计算矩形的4个顶点 candidate_armor.points(vertices); //计算矩形的4个顶点
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
line(src_bin, vertices[i], vertices[(i + 1) % 4], Scalar(0, 0, 0), 20); line(src_bin, vertices[i], vertices[(i + 1) % 4], Scalar(0, 0, 0), 20);
} }
} }
cvtColor(src_bin, src_bin, CV_BGR2GRAY);//若读取三通道视频文件,需转换为单通道 cvtColor(src_bin, src_bin, CV_BGR2GRAY);//若读取三通道视频文件,需转换为单通道
FlowStripStruct(src_bin);//图像膨胀,防止图像断开并更方便寻找 FlowStripStruct(src_bin);//图像膨胀,防止图像断开并更方便寻找
if (show_process)imshow("weak struct", src_bin); if (show_process)imshow("weak struct", src_bin);
// waitKey(0); // waitKey(0);
std::vector<vector<Point> > flow_strip_contours; std::vector<vector<Point> > flow_strip_contours;
findContours(src_bin, flow_strip_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); findContours(src_bin, flow_strip_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
for (auto &flow_strip_contour : flow_strip_contours) { for (auto &flow_strip_contour : flow_strip_contours) {
if (!isValidFlowStripContour(flow_strip_contour)) { if (!isValidFlowStripContour(flow_strip_contour)) {
continue; continue;
} }
flow_strips.emplace_back(cv::minAreaRect(flow_strip_contour)); flow_strips.emplace_back(cv::minAreaRect(flow_strip_contour));
// RotatedRect cur_rect = minAreaRect(flow_strip_contour); // RotatedRect cur_rect = minAreaRect(flow_strip_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;
// double cur_contour_area = contourArea(flow_strip_contour); // double cur_contour_area = contourArea(flow_strip_contour);
// float length_width_ratio = length / width; // float length_width_ratio = length / width;
// cout << "area: " << cur_contour_area << '\t' << endl; // 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; // cout << endl;
} }
// cout << "size: " << flow_strips.size() << endl; // cout << "size: " << flow_strips.size() << endl;
if (flow_strips.empty()) { if (flow_strips.empty()) {
if (show_info)cout << "weak flow strip false!" << endl; if (show_info)cout << "weak flow strip false!" << endl;
// waitKey(0); // waitKey(0);
return false; return false;
} else { } else {
for (const auto &candidate_flow_strip: flow_strips) { for (const auto &candidate_flow_strip: flow_strips) {
for (const auto &candidate_armor: armors) { for (const auto &candidate_armor: armors) {
if (pointDistance(candidate_flow_strip.center, candidate_armor.center) < if (pointDistance(candidate_flow_strip.center, candidate_armor.center) <
energy_part_param_.STRIP_ARMOR_DISTANCE_MIN || energy_part_param_.STRIP_ARMOR_DISTANCE_MIN ||
pointDistance(candidate_flow_strip.center, candidate_armor.center) > pointDistance(candidate_flow_strip.center, candidate_armor.center) >
energy_part_param_.STRIP_ARMOR_DISTANCE_MAX) { energy_part_param_.STRIP_ARMOR_DISTANCE_MAX) {
continue; continue;
} }
float angle_armor = candidate_armor.size.width > candidate_armor.size.height ? candidate_armor.angle : float angle_armor = candidate_armor.size.width > candidate_armor.size.height ? candidate_armor.angle :
candidate_armor.angle - 90; candidate_armor.angle - 90;
float angle_strip = candidate_flow_strip.size.width > candidate_flow_strip.size.height ? float angle_strip = candidate_flow_strip.size.width > candidate_flow_strip.size.height ?
candidate_flow_strip.angle: candidate_flow_strip.angle - 90; candidate_flow_strip.angle: candidate_flow_strip.angle - 90;
if (abs(angle_armor - angle_strip) < 60 || abs(angle_armor - angle_strip) > 120) { if (abs(angle_armor - angle_strip) < 60 || abs(angle_armor - angle_strip) > 120) {
continue; continue;
} }
target_armor = candidate_armor; target_armor = candidate_armor;
target_point = candidate_armor.center; target_point = candidate_armor.center;
flow_strip = candidate_flow_strip; flow_strip = candidate_flow_strip;
return true; return true;
} }
} }
if (show_info)cout << "weak flow strip false!" << endl; if (show_info)cout << "weak flow strip false!" << endl;
// waitKey(0); // waitKey(0);
return false; return false;
} }
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数用于框取中心R的寻找范围 // 此函数用于框取中心R的寻找范围
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
bool Energy::findCenterROI(const cv::Mat src) { bool Energy::findCenterROI(const cv::Mat src) {
float length = target_armor.size.height > target_armor.size.width ? float length = target_armor.size.height > target_armor.size.width ?
target_armor.size.height : target_armor.size.width; target_armor.size.height : target_armor.size.width;
Point2f p2p(flow_strip.center.x - target_point.x, Point2f p2p(flow_strip.center.x - target_point.x,
flow_strip.center.y - target_point.y); flow_strip.center.y - target_point.y);
p2p = p2p / pointDistance(flow_strip.center, target_point);//单位化 p2p = p2p / pointDistance(flow_strip.center, target_point);//单位化
center_ROI = cv::RotatedRect(cv::Point2f(flow_strip.center + p2p * length * 1.7), center_ROI = cv::RotatedRect(cv::Point2f(flow_strip.center + p2p * length * 1.7),
Size2f(length * 1.4, length * 1.4), -90); Size2f(length * 1.4, length * 1.4), -90);
return true; return true;
} }

View File

@@ -1,79 +1,86 @@
// //
// Created by xixiliadorabarry on 1/24/19. // Created by xixiliadorabarry on 1/24/19.
// //
#include "energy/energy.h" #include "energy/energy.h"
#include "log.h" #include "log.h"
using namespace cv; using namespace cv;
using std::cout; using std::cout;
using std::endl; using std::endl;
using std::vector; using std::vector;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数根据矩形重合面积匹配扇叶与装甲板 // 此函数根据矩形重合面积匹配扇叶与装甲板
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
void Energy::findTargetByIntersection() { void Energy::findTargetByIntersection() {
if (fans.size() >= armors.size()) return;//扇叶多于装甲板,识别错误 if (fans.size() >= armors.size()) return;//扇叶多于装甲板,识别错误
for (const auto &fan : fans) { for (const auto &fan : fans) {
for (const auto &armor : armors) { for (const auto &armor : armors) {
} }
} }
/* if (fans.empty()) { /* if (fans.empty()) {
target_point = armors.at(0).rect.center; target_point = armors.at(0).rect.center;
return; return;
} }
int i = 0, j = 0; int i = 0, j = 0;
while (i < armors.size()) { while (i < armors.size()) {
for (j = 0; j < fans.size(); ++j) { for (j = 0; j < fans.size(); ++j) {
std::vector<cv::Point2f> intersection; std::vector<cv::Point2f> intersection;
if (rotatedRectangleIntersection(armors.at(i).rect, fans.at(j).rect, intersection) == 0)//返回0表示没有重合面积 if (rotatedRectangleIntersection(armors.at(i).rect, fans.at(j).rect, intersection) == 0)//返回0表示没有重合面积
continue; continue;
else else
rotatedRectangleIntersection(armors.at(i).rect, fans.at(j).rect, intersection); rotatedRectangleIntersection(armors.at(i).rect, fans.at(j).rect, intersection);
double cur_contour_area = contourArea(intersection); double cur_contour_area = contourArea(intersection);
if (cur_contour_area > energy_part_param_.INTERSETION_CONTOUR_AREA_MIN) { if (cur_contour_area > energy_part_param_.INTERSETION_CONTOUR_AREA_MIN) {
// cout << endl; // cout << endl;
// cout << "NO. " << i << " armor and No. " << j << "fans are matched, the intersection area is" // cout << "NO. " << i << " armor and No. " << j << "fans are matched, the intersection area is"
// << cur_contour_area << endl; // << cur_contour_area << endl;
break; break;
} }
} }
if (j == fans.size()) { if (j == fans.size()) {
target_point = armors.at(i).rect.center; target_point = armors.at(i).rect.center;
break; break;
} }
i++; i++;
}*/ }*/
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数在流动条区域内寻找装甲板 // 此函数在流动条区域内寻找装甲板
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
bool Energy::findTargetInFlowStripFan() { bool Energy::findTargetInFlowStripFan() {
for (auto &candidate_flow_strip_fan: flow_strip_fans) { // Mat draw(480,640,CV_8UC3,Scalar(0,0,0));
int i = 0; for (auto &candidate_flow_strip_fan: flow_strip_fans) {
for (i = 0; i < armors.size(); ++i) { // Point2f vertices[4]; //定义矩形的4个顶点
std::vector<cv::Point2f> intersection; // candidate_flow_strip_fan.points(vertices); //计算矩形的4个顶点
if (rotatedRectangleIntersection(armors.at(i), candidate_flow_strip_fan, intersection) == 0) // for (int i = 0; i < 4; i++)
continue;//返回0表示没有重合面积 // line(draw, vertices[i], vertices[(i + 1) % 4], Scalar(0, 0, 255), 2);
double cur_contour_area = contourArea(intersection); int i = 0;
// cout<<cur_contour_area<<endl; for (i = 0; i < armors.size(); ++i) {
if (cur_contour_area > energy_part_param_.TARGET_INTERSETION_CONTOUR_AREA_MIN) { std::vector<cv::Point2f> intersection;
target_armors.emplace_back(armors.at(i)); if (rotatedRectangleIntersection(armors.at(i), candidate_flow_strip_fan, intersection) == 0)
} continue;//返回0表示没有重合面积
} double cur_contour_area = contourArea(intersection);
} // cout<<cur_contour_area<<endl;
// cout << "target armor cnt: " << target_armors.size() << endl; if (cur_contour_area > energy_part_param_.TARGET_INTERSETION_CONTOUR_AREA_MIN) {
if (target_armors.empty()) { target_armors.emplace_back(armors.at(i));
if (show_info)cout << "find target armor false" << endl; }
return false; }
} else { }
return true; // imshow("draw",draw);
} // waitKey();
// cout << "target armor cnt: " << target_armors.size() << endl;
if (target_armors.empty()) {
if (show_info)cout << "t6find target armor false" << endl;
return false;
} else {
return true;
}
} }