energy changed

This commit is contained in:
sun
2019-07-09 21:04:01 +08:00
parent cdef78ddde
commit 0f6ede086d
9 changed files with 353 additions and 202 deletions

View File

@@ -2,7 +2,7 @@
PROJECT(SJTU-RM-CV) PROJECT(SJTU-RM-CV)
SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD 11)
SET(CMAKE_BUILD_TYPE RELEASE) SET(CMAKE_BUILD_TYPE DEBUG)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPATH=\"\\\"${PROJECT_SOURCE_DIR}\\\"\"") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPATH=\"\\\"${PROJECT_SOURCE_DIR}\\\"\"")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D${CMAKE_SYSTEM_NAME}") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D${CMAKE_SYSTEM_NAME}")

View File

@@ -42,10 +42,12 @@ private:
int fans_cnt;//图像中的扇叶个数 int fans_cnt;//图像中的扇叶个数
int armors_cnt;//图像中的装甲板个数 int armors_cnt;//图像中的装甲板个数
int centerRs_cnt;//图像中可能的风车中心字母R选区个数 int centerRs_cnt;//图像中可能的风车中心字母R选区个数
int flow_strip_fans_cnt;//图像中的含流动条扇叶个数
int flow_strips_cnt;//图像中的流动条个数 int flow_strips_cnt;//图像中的流动条个数
int last_fans_cnt;//上一帧的扇叶个数 int last_fans_cnt;//上一帧的扇叶个数
int last_armors_cnt;//上一帧的装甲板个数 int last_armors_cnt;//上一帧的装甲板个数
int last_flow_strips_cnt;// int last_flow_strip_fans_cnt;//上一帧的含流动条扇叶个数
int last_flow_strips_cnt;//上一帧的流动条个数
int gimble_cnt; //经过的帧数 int gimble_cnt; //经过的帧数
double radius;//大风车半径 double radius;//大风车半径
float target_polar_angle;//待击打装甲板的极坐标角度 float target_polar_angle;//待击打装甲板的极坐标角度
@@ -71,6 +73,9 @@ private:
std::vector<EnergyPart> armors;//图像中所有装甲板 std::vector<EnergyPart> armors;//图像中所有装甲板
std::vector<EnergyPart> centerRs;//风车中心字母R的可能候选区 std::vector<EnergyPart> centerRs;//风车中心字母R的可能候选区
std::vector<EnergyPart> flow_strips;//图像中所有流动条(理论上只有一个) std::vector<EnergyPart> flow_strips;//图像中所有流动条(理论上只有一个)
std::vector<EnergyPart> flow_strip_fans;//图像中所有流动条所在扇叶(理论上只有一个)
std::vector<EnergyPart> center_ROI;//风车中心候选区
std::vector<EnergyPart> target_armor;//目标装甲板(理论上仅一个)
cv::Point circle_center_point;//风车圆心坐标 cv::Point circle_center_point;//风车圆心坐标
cv::Point target_point;//目标装甲板中心坐标 cv::Point target_point;//目标装甲板中心坐标
@@ -89,18 +94,21 @@ private:
int findFan(const cv::Mat src, int &last_fans_cnt);//寻找图中所有扇叶 int findFan(const cv::Mat src, int &last_fans_cnt);//寻找图中所有扇叶
int findArmor(const cv::Mat src, int &last_armors_cnt);//寻找图中所有装甲板 int findArmor(const cv::Mat src, int &last_armors_cnt);//寻找图中所有装甲板
int findCenterR(const cv::Mat src);//寻找图中可能的风车中心字母R int findCenterR(const cv::Mat src);//寻找图中可能的风车中心字母R
int findFlowStrip(const cv::Mat src, int &last_flow_strips_cnt);//寻找图中所有流动条 int findFlowStrip(const cv::Mat src, int &last_flow_strips_cnt);//寻找图中流动条
void findCenterROI(const cv::Mat src);//框取中心R候选区
int findFlowStripFan(const cv::Mat src, int &last_flow_strip_fans_cnt);//寻找图中的流动条所在扇叶
bool isValidFanContour(const vector<cv::Point> fan_contour);//扇叶矩形尺寸要求 bool isValidFanContour(const vector<cv::Point> &fan_contour);//扇叶矩形尺寸要求
bool isValidArmorContour(const vector<cv::Point> armor_contour);//装甲板矩形尺寸要求 bool isValidArmorContour(const vector<cv::Point> &armor_contour);//装甲板矩形尺寸要求
bool isValidCenterRContour(const vector<cv::Point> center_R_contour);//风车中心选区尺寸要求 bool isValidCenterRContour(const vector<cv::Point> &center_R_contour);//风车中心选区尺寸要求
bool isValidFlowStripContour(const vector<cv::Point> flow_strip_contour);//流动条矩形尺寸要求 bool isValidFlowStripContour(const vector<cv::Point> &flow_strip_contour);//流动条扇叶矩形尺寸要求
bool isValidFlowStripFanContour(const vector<cv::Point> &flow_strip_fan_contour);//流动条扇叶矩形尺寸要求
void showFanContours(std::string windows_name, const cv::Mat src);//显示扇叶 void showFanContours(std::string windows_name, const cv::Mat src);//显示扇叶
void showArmorContours(std::string windows_name, const cv::Mat src);//显示装甲板 void showArmorContours(std::string windows_name, const cv::Mat src);//显示装甲板
void showBothContours(std::string windows_name, const cv::Mat src);//显示扇叶和装甲板 void showBothContours(std::string windows_name, const cv::Mat src);//显示扇叶和装甲板
void showCenterRContours(std::string windows_name, const cv::Mat src);//显示风车中心候选区R void showCenterRContours(std::string windows_name, const cv::Mat src);//显示风车中心候选区R
void showFlowStripContours(std::string windows_name, const cv::Mat src);//显示流动条 void showFlowStripFanContours(std::string windows_name, const cv::Mat src);//显示流动条所在扇叶
void getFanPolarAngle();//获取扇叶极坐标角度 void getFanPolarAngle();//获取扇叶极坐标角度
void getArmorPolarAngle();//获取装甲板极坐标角度 void getArmorPolarAngle();//获取装甲板极坐标角度
@@ -110,7 +118,7 @@ private:
void findTargetByPolar();//通过极坐标角度匹配获取目标装甲板的极坐标角度和装甲板中心坐标 void findTargetByPolar();//通过极坐标角度匹配获取目标装甲板的极坐标角度和装甲板中心坐标
void findTargetByIntersection();//通过面积重合度匹配获取目标装甲板的极坐标角度和装甲板中心坐标 void findTargetByIntersection();//通过面积重合度匹配获取目标装甲板的极坐标角度和装甲板中心坐标
bool findTargetInFlowStrip();//在已发现的流动条区域中寻找待击打装甲板 bool findTargetInFlowStripFan();//在已发现的流动条区域中寻找待击打装甲板
void rotate();//获取预测点位 void rotate();//获取预测点位
void stretch(cv::Point point_1, cv::Point2f &point_2);//将像素差转换为实际距离差 void stretch(cv::Point point_1, cv::Point2f &point_2);//将像素差转换为实际距离差

View File

@@ -24,6 +24,8 @@ struct EnergyPart {
rect = cv::minAreaRect(c); rect = cv::minAreaRect(c);
angle = cv::minAreaRect(c).angle; angle = cv::minAreaRect(c).angle;
}; };
EnergyPart(cv::RotatedRect rect=cv::RotatedRect(), float angle=0, vector<cv::Point> contour=vector<cv::Point>()):rect(rect),angle(angle),contour(contour){};
}; };
@@ -66,17 +68,29 @@ struct EnergyPartParam {
float CENTER_R_CONTOUR_HW_RATIO_MAX;//风车中心R长宽比最大值 float CENTER_R_CONTOUR_HW_RATIO_MAX;//风车中心R长宽比最大值
float CENTER_R_CONTOUR_HW_RATIO_MIN;//风车中心R长宽比最小值 float CENTER_R_CONTOUR_HW_RATIO_MIN;//风车中心R长宽比最小值
float CENTER_R_CONTOUR_AREA_RATIO_MIN;//装甲板轮廓占旋转矩形面积比最小值 float CENTER_R_CONTOUR_AREA_RATIO_MIN;//装甲板轮廓占旋转矩形面积比最小值
float CENTER_R_CONTOUR_INTERSETION_AREA_MIN;//中心R占ROI区的面积最小值
long FLOW_STRIP_FAN_CONTOUR_AREA_MAX;//流动条扇叶(待击打)面积最大值
long FLOW_STRIP_FAN_CONTOUR_AREA_MIN;//流动条扇叶(待击打)面积最小值
long FLOW_STRIP_FAN_CONTOUR_LENGTH_MIN;//流动条扇叶(待击打)长边长度最小值
long FLOW_STRIP_FAN_CONTOUR_WIDTH_MIN;//流动条扇叶(待击打)宽边长度最小值
long FLOW_STRIP_FAN_CONTOUR_LENGTH_MAX;//流动条扇叶(待击打)长边长度最大值
long FLOW_STRIP_FAN_CONTOUR_WIDTH_MAX;//流动条扇叶(待击打)宽边长度最大值
float FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MAX;//流动条扇叶(待击打)长宽比最大值
float FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MIN;//流动条扇叶(待击打)长宽比最小值
float FLOW_STRIP_FAN_CONTOUR_AREA_RATIO_MAX;//装甲板轮廓占旋转矩形面积比最小值
float FLOW_STRIP_FAN_CONTOUR_AREA_RATIO_MIN;//装甲板轮廓占旋转矩形面积比最小值
long FLOW_STRIP_CONTOUR_AREA_MAX;//流动条(待击打)面积最大值 long FLOW_STRIP_CONTOUR_AREA_MAX;//流动条(待击打)面积最大值
long FLOW_STRIP_CONTOUR_AREA_MIN;//流动条(待击打)面积最小值 long FLOW_STRIP_CONTOUR_AREA_MIN;//流动条(待击打)面积最小值
long FLOW_STRIP_CONTOUR_LENGTH_MIN;//流动条(待击打)长边长度最小值 long FLOW_STRIP_CONTOUR_LENGTH_MIN;//流动条(待击打)长边长度最小值
long FLOW_STRIP_CONTOUR_WIDTH_MIN;//流动条(待击打)边长度最 long FLOW_STRIP_CONTOUR_WIDTH_MIN;//流动条(待击打)边长度最
long FLOW_STRIP_CONTOUR_LENGTH_MAX;//流动条(待击打)边长度最 long FLOW_STRIP_CONTOUR_LENGTH_MAX;//流动条(待击打)边长度最
long FLOW_STRIP_CONTOUR_WIDTH_MAX;//流动条(待击打)宽边长度最大值 long FLOW_STRIP_CONTOUR_WIDTH_MAX;//流动条(待击打)宽边长度最大值
float FLOW_STRIP_CONTOUR_HW_RATIO_MAX;//流动条(待击打)长宽比最大值 float FLOW_STRIP_CONTOUR_HW_RATIO_MAX;//流动条(待击打)长宽比最大值
float FLOW_STRIP_CONTOUR_HW_RATIO_MIN;//流动条(待击打)长宽比最小值 float FLOW_STRIP_CONTOUR_HW_RATIO_MIN;//流动条(待击打)长宽比最小值
float FLOW_STRIP_CONTOUR_AREA_RATIO_MAX;//装甲板轮廓占旋转矩形面积比最小值
float FLOW_STRIP_CONTOUR_AREA_RATIO_MIN;//装甲板轮廓占旋转矩形面积比最小值 float FLOW_STRIP_CONTOUR_AREA_RATIO_MIN;//装甲板轮廓占旋转矩形面积比最小值
float FLOW_STRIP_CONTOUR_INTERSETION_AREA_MIN;//流动条占旋转矩形面积比最小值
float TWIN_ANGEL_MAX;//扇叶和装甲板匹配时极坐标角度差的最大值 float TWIN_ANGEL_MAX;//扇叶和装甲板匹配时极坐标角度差的最大值
long INTERSETION_CONTOUR_AREA_MIN;//扇叶与装甲板匹配时的最小重合面积 long INTERSETION_CONTOUR_AREA_MIN;//扇叶与装甲板匹配时的最小重合面积

View File

@@ -21,6 +21,7 @@ void Energy::initEnergy() {
armors_cnt = 0; armors_cnt = 0;
centerRs_cnt = 0; centerRs_cnt = 0;
flow_strips_cnt = 0; flow_strips_cnt = 0;
flow_strip_fans_cnt = 0;
gimble_cnt = 0; gimble_cnt = 0;
circle_center_point = Point(0, 0); circle_center_point = Point(0, 0);
target_point = Point(0, 0); target_point = Point(0, 0);
@@ -35,6 +36,7 @@ void Energy::initEnergy() {
last_fans_cnt = 0; last_fans_cnt = 0;
last_armors_cnt = 0; last_armors_cnt = 0;
last_flow_strips_cnt = 0; last_flow_strips_cnt = 0;
last_flow_strip_fans_cnt = 0;
send_cnt = 0; send_cnt = 0;
yaw_rotation = 0; yaw_rotation = 0;
pitch_rotation = 0; pitch_rotation = 0;
@@ -54,6 +56,9 @@ void Energy::initEnergy() {
armors.clear(); armors.clear();
centerRs.clear(); centerRs.clear();
flow_strips.clear(); flow_strips.clear();
flow_strip_fans.clear();
center_ROI.clear();
target_armor.clear();
fan_polar_angle.clear(); fan_polar_angle.clear();
armor_polar_angle.clear(); armor_polar_angle.clear();
@@ -122,17 +127,29 @@ void Energy::initEnergyPartParam() {
energy_part_param_.CENTER_R_CONTOUR_HW_RATIO_MAX = 3; energy_part_param_.CENTER_R_CONTOUR_HW_RATIO_MAX = 3;
energy_part_param_.CENTER_R_CONTOUR_HW_RATIO_MIN = 1; energy_part_param_.CENTER_R_CONTOUR_HW_RATIO_MIN = 1;
energy_part_param_.CENTER_R_CONTOUR_AREA_RATIO_MIN = 0.7; energy_part_param_.CENTER_R_CONTOUR_AREA_RATIO_MIN = 0.7;
energy_part_param_.CENTER_R_CONTOUR_INTERSETION_AREA_MIN = 10;
energy_part_param_.FLOW_STRIP_CONTOUR_AREA_MAX = 17000; energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_MAX = 17000;
energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_MIN = 0;
energy_part_param_.FLOW_STRIP_FAN_CONTOUR_LENGTH_MIN = 90;
energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MIN = 35;
energy_part_param_.FLOW_STRIP_FAN_CONTOUR_LENGTH_MAX = 140;
energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MAX = 60;
energy_part_param_.FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MAX = 3;
energy_part_param_.FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MIN = 1;
energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_RATIO_MAX = 0.55;
energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_RATIO_MIN = 0.25;
energy_part_param_.FLOW_STRIP_CONTOUR_AREA_MAX = 100000;
energy_part_param_.FLOW_STRIP_CONTOUR_AREA_MIN = 0; energy_part_param_.FLOW_STRIP_CONTOUR_AREA_MIN = 0;
energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MIN = 90; energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MIN = 50;
energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MIN = 35; energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MIN = 3;
energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MAX = 140; energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MAX = 90;
energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MAX = 60; energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MAX = 20;
energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MAX = 3; energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MAX = 12;
energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MIN = 1; energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MIN = 4;
energy_part_param_.FLOW_STRIP_CONTOUR_AREA_RATIO_MAX = 0.55; energy_part_param_.FLOW_STRIP_CONTOUR_AREA_RATIO_MIN = 0.5;
energy_part_param_.FLOW_STRIP_CONTOUR_AREA_RATIO_MIN = 0.25; energy_part_param_.FLOW_STRIP_CONTOUR_INTERSETION_AREA_MIN = 300;
energy_part_param_.TWIN_ANGEL_MAX = 10; energy_part_param_.TWIN_ANGEL_MAX = 10;
energy_part_param_.INTERSETION_CONTOUR_AREA_MIN = 60; energy_part_param_.INTERSETION_CONTOUR_AREA_MIN = 60;

View File

@@ -9,7 +9,6 @@ using std::endl;
using std::vector; using std::vector;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数用于寻找图像内所有的大风车扇叶 // 此函数用于寻找图像内所有的大风车扇叶
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
@@ -18,18 +17,18 @@ int Energy::findFan(const cv::Mat src, int &last_fans_cnt) {
static Mat src_bin; static Mat src_bin;
src_bin = src.clone(); src_bin = src.clone();
// threshold(src, src_bin, energy_part_param_.FAN_GRAY_THRESH, 255, THRESH_BINARY); // threshold(src, src_bin, energy_part_param_.FAN_GRAY_THRESH, 255, THRESH_BINARY);
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;
StructingElementClose(src_bin,6,6);//图像膨胀,防止图像断开并更方便寻找 StructingElementClose(src_bin, 6, 6);//图像膨胀,防止图像断开并更方便寻找
// imshow("fan struct",src_bin); // 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(fan_contour)) { if (!isValidFanContour(fan_contour)) {
continue; continue;
} }
fans.emplace_back(fan_contour); fans.emplace_back(fan_contour);
// RotatedRect cur_rect = minAreaRect(fan_contour); // RotatedRect cur_rect = minAreaRect(fan_contour);
@@ -41,46 +40,42 @@ int Energy::findFan(const cv::Mat src, int &last_fans_cnt) {
// fans.emplace_back(fan_contour); // fans.emplace_back(fan_contour);
// cout<<"fan area: "<<length<<'\t'<<width<<endl; // cout<<"fan area: "<<length<<'\t'<<width<<endl;
// } // }
} }
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::findArmor(const cv::Mat src, int &last_armors_cnt) { int Energy::findArmor(const cv::Mat src, int &last_armors_cnt) {
if (src.empty())return 0; if (src.empty())return 0;
static Mat src_bin; static Mat src_bin;
src_bin = src.clone(); src_bin = src.clone();
// threshold(src, src_bin, energy_part_param_.ARMOR_GRAY_THRESH, 255, THRESH_BINARY); // threshold(src, src_bin, energy_part_param_.ARMOR_GRAY_THRESH, 255, THRESH_BINARY);
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;//用总轮廓减去外轮廓,只保留内轮廓,除去流动条的影响。
StructingElementErodeDilate(src_bin);//图像膨胀,防止图像断开并更方便寻找 StructingElementErodeDilate(src_bin);//图像膨胀,防止图像断开并更方便寻找
imshow("armor struct",src_bin); imshow("armor struct", 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);
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;
@@ -88,10 +83,9 @@ int Energy::findArmor(const cv::Mat src, int &last_armors_cnt) {
} }
} }
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(armor_contour); armors.emplace_back(armor_contour);
// RotatedRect cur_rect = minAreaRect(armor_contour); // RotatedRect cur_rect = minAreaRect(armor_contour);
@@ -103,19 +97,16 @@ int Energy::findArmor(const cv::Mat src, int &last_armors_cnt) {
// cout<<"armor area: "<<length<<'\t'<<width<<'\t'<<cur_rect.center<<endl; // cout<<"armor area: "<<length<<'\t'<<width<<'\t'<<cur_rect.center<<endl;
// } // }
} }
if(armors.size() < last_armors_cnt){ if (armors.size() < last_armors_cnt) {
last_armors_cnt = static_cast<int>(armors.size()); last_armors_cnt = static_cast<int>(armors.size());
return -1;//寻找到的装甲板比上一帧少,说明该帧有误,返回-1 return -1;//寻找到的装甲板比上一帧少,说明该帧有误,返回-1
} }
last_armors_cnt = static_cast<int>(armors.size()); last_armors_cnt = static_cast<int>(armors.size());
return static_cast<int>(armors.size()); return static_cast<int>(armors.size());
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数用于寻找图像内大风车中心字母“R” // 此函数用于寻找图像内大风车中心字母“R”
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
@@ -124,54 +115,93 @@ int Energy::findCenterR(const cv::Mat src) {
static Mat src_bin; static Mat src_bin;
src_bin = src.clone(); src_bin = src.clone();
// threshold(src, src_bin, energy_part_param_.ARMOR_GRAY_THRESH, 255, THRESH_BINARY); // threshold(src, src_bin, energy_part_param_.ARMOR_GRAY_THRESH, 255, THRESH_BINARY);
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;
StructingElementErodeDilate(src_bin); StructingElementErodeDilate(src_bin);
// imshow("R struct",src_bin); // 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;
} }
centerRs.emplace_back(center_R_contour); centerRs.emplace_back(center_R_contour);
/*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;
// if(length>10 && width>5){
if(length>10 && width>5){ // centerRs.emplace_back(center_R_contour);
centerRs.emplace_back(center_R_contour); // cout<<"center R area: "<<length<<'\t'<<width<<'\t'<<cur_rect.center<<endl;
cout<<"center R area: "<<length<<'\t'<<width<<'\t'<<cur_rect.center<<endl; // }
} // cout<<"armor area: "<<length<<'\t'<<width<<endl;
cout<<"armor area: "<<length<<'\t'<<width<<endl;*/
} }
if(centerRs.size() == 0) return -1;//未找到合适的中心候选区,说明该帧有误,返回-1 if (centerRs.size() == 0) return -1;//未找到合适的中心候选区,说明该帧有误,返回-1
return static_cast<int>(centerRs.size()); return static_cast<int>(centerRs.size());
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数用于判断找到的矩形候选区是否为扇叶 // 此函数用于判断找到的矩形候选区是否为含流动条的扇叶
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
int Energy::findFlowStripFan(const cv::Mat src, int &last_flow_strip_fans_cnt) {
int Energy::findFlowStrip(const cv::Mat src, int &last_flow_strips_cnt){
if (src.empty())return 0; if (src.empty())return 0;
static Mat src_bin; static Mat src_bin;
src_bin = src.clone(); src_bin = src.clone();
// threshold(src, src_bin, energy_part_param_.FAN_GRAY_THRESH, 255, THRESH_BINARY); // threshold(src, src_bin, energy_part_param_.FAN_GRAY_THRESH, 255, THRESH_BINARY);
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_contours; std::vector<vector<Point> > flow_strip_fan_contours;
StructingElementClose(src_bin,6,6);//图像膨胀,防止图像断开并更方便寻找 StructingElementClose(src_bin, 6, 6);//图像膨胀,防止图像断开并更方便寻找
imshow("flow_strip struct",src_bin); // imshow("flow strip fan struct", src_bin);
findContours(src_bin, flow_strip_fan_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
for (auto &flow_strip_fan_contour : flow_strip_fan_contours) {
if (!isValidFlowStripFanContour(flow_strip_fan_contour)) {
continue;
}
flow_strip_fans.emplace_back(flow_strip_fan_contour);
// RotatedRect cur_rect = minAreaRect(flow_strip_fan_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>20&&width>20){
// cout<<cur_rect.center;
// flow_strip_fans.emplace_back(flow_strip_fan_contour);
// cout<<"flow strip fan area: "<<length<<'\t'<<width<<endl;
// }
}
if (flow_strip_fans.size() < last_flow_strip_fans_cnt) {
last_flow_strip_fans_cnt = static_cast<int>(flow_strip_fans.size());
return -1;//寻找到的流动条扇叶比上一帧少,说明该帧有误,返回-1
}
last_flow_strip_fans_cnt = static_cast<int>(flow_strip_fans.size());
return static_cast<int>(flow_strip_fans.size());
}
//----------------------------------------------------------------------------------------------------------------------
// 此函数用于寻找流动条
// ---------------------------------------------------------------------------------------------------------------------
int Energy::findFlowStrip(const cv::Mat src, int &last_flow_strips_cnt) {
if (src.empty())return 0;
cv::Mat src_bin;
src_bin = src.clone();
if (src.type() == CV_8UC3) {
cvtColor(src_bin, src_bin, CV_BGR2GRAY);//若读取三通道视频文件,需转换为单通道
}
StructingElementClose(src_bin, 6, 6);//图像膨胀,防止图像断开并更方便寻找
imshow("flow strip struct", src_bin);
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) {
@@ -179,156 +209,217 @@ int Energy::findFlowStrip(const cv::Mat src, int &last_flow_strips_cnt){
continue; continue;
} }
flow_strips.emplace_back(flow_strip_contour); flow_strips.emplace_back(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;
// if(length>20&&width>20){ // if(length>40&&width>5){
// cout<<cur_rect.center; // cout<<cur_rect.center<<endl;
// flow_strips.emplace_back(flow_strip_contour); // flow_strips.emplace_back(flow_strip_contour);
// cout<<"flow_strip area: "<<length<<'\t'<<width<<endl; // cout<<"flow strip fan area: "<<length<<'\t'<<width<<endl;
// } // }
} }
if(flow_strips.size() < last_flow_strips_cnt){ if (flow_strips.size() < last_flow_strips_cnt) {
last_flow_strips_cnt = static_cast<int>(flow_strips.size()); last_flow_strips_cnt = static_cast<int>(flow_strips.size());
return -1;//寻找到的流动条比上一帧少,说明该帧有误,返回-1 return -1;//寻找到的流动条比上一帧少,说明该帧有误,返回-1
} }
last_flow_strips_cnt = static_cast<int>(flow_strips.size()); last_flow_strips_cnt = static_cast<int>(flow_strips.size());
return static_cast<int>(flow_strips.size()); return static_cast<int>(flow_strips.size());
}
//----------------------------------------------------------------------------------------------------------------------
// 此函数用于框取中心R的寻找范围
// ---------------------------------------------------------------------------------------------------------------------
void Energy::findCenterROI(const cv::Mat src) {
cv::Mat src_mask = src.clone();
target_armor.at(0).rect.size.height *= 1.3;
target_armor.at(0).rect.size.width *= 1.3;
Point2f vertices[4];
vector<Point2f> mask_rect;
target_armor.at(0).rect.points(vertices); //计算矩形的4个顶点
for (int i = 0; i < 4; i++)
line(src_mask, vertices[i], vertices[(i + 1) % 4], Scalar(0, 0, 0), 15);
imshow("fill", src_mask);
flow_strips_cnt = findFlowStrip(src_mask, last_flow_strips_cnt);
float length = target_armor.at(0).rect.size.height > target_armor.at(0).rect.size.width ?
target_armor.at(0).rect.size.height : target_armor.at(0).rect.size.width;
if (flow_strips_cnt > 0 && target_armor.size() > 0) {
for (auto flow_strip: flow_strips) {
Point2f p2p(flow_strip.rect.center.x - target_point.x,
flow_strip.rect.center.y - target_point.y);
p2p = p2p / pointDistance(flow_strip.rect.center, target_point);//单位化
center_ROI.emplace_back(
EnergyPart(cv::RotatedRect(cv::Point2f(flow_strip.rect.center + p2p * length * 1.5),
Size2f(length, length), -90)));
}
}
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数用于判断找到的矩形候选区是否为扇叶 // 此函数用于判断找到的矩形候选区是否为扇叶
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
bool Energy::isValidFanContour(const vector<cv::Point> fan_contour) { bool Energy::isValidFanContour(const vector<cv::Point> &fan_contour) {
double cur_contour_area = contourArea(fan_contour); double cur_contour_area = contourArea(fan_contour);
if (cur_contour_area > energy_part_param_.FAN_CONTOUR_AREA_MAX || if (cur_contour_area > energy_part_param_.FAN_CONTOUR_AREA_MAX ||
cur_contour_area < energy_part_param_.FAN_CONTOUR_AREA_MIN) cur_contour_area < energy_part_param_.FAN_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; //选区面积大小不合适
//选区面积大小不合适 }
} 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;//将矩形的短边设置为宽 if (length < energy_part_param_.FAN_CONTOUR_LENGTH_MIN || width < energy_part_param_.FAN_CONTOUR_WIDTH_MIN ||
if (length < energy_part_param_.FAN_CONTOUR_LENGTH_MIN || width < energy_part_param_.FAN_CONTOUR_WIDTH_MIN || length > energy_part_param_.FAN_CONTOUR_LENGTH_MAX || width > energy_part_param_.FAN_CONTOUR_WIDTH_MAX) {
length > energy_part_param_.FAN_CONTOUR_LENGTH_MAX || width > energy_part_param_.FAN_CONTOUR_WIDTH_MAX) //cout<<"length width fail."<<endl;
{ return false;
//cout<<"length width fail."<<endl; //矩形边长不合适
return false; }
//矩形边长不合适 float length_width_ratio = length / width;//计算矩形长宽比
} if (length_width_ratio > energy_part_param_.FAN_CONTOUR_HW_RATIO_MAX ||
float length_width_ratio = length / width;//计算矩形长宽比 length_width_ratio < energy_part_param_.FAN_CONTOUR_HW_RATIO_MIN) {
if (length_width_ratio > energy_part_param_.FAN_CONTOUR_HW_RATIO_MAX || //cout<<"length width ratio fail."<<endl;
length_width_ratio < energy_part_param_.FAN_CONTOUR_HW_RATIO_MIN) return false;
{ //长宽比不合适
//cout<<"length width ratio fail."<<endl; }
return false; if (cur_contour_area / cur_size.area() < energy_part_param_.FAN_CONTOUR_AREA_RATIO_MIN)
//长宽比不合适 return false;//轮廓对矩形的面积占有率不合适
} return true;
if (cur_contour_area / cur_size.area() < energy_part_param_.FAN_CONTOUR_AREA_RATIO_MIN) return false;//轮廓对矩形的面积占有率不合适
return true;
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数用于判断找到的矩形候选区是否为装甲板 // 此函数用于判断找到的矩形候选区是否为装甲板
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
bool Energy::isValidArmorContour(const vector<cv::Point> armor_contour) { bool Energy::isValidArmorContour(const vector<cv::Point> &armor_contour) {
double cur_contour_area = contourArea(armor_contour); double cur_contour_area = contourArea(armor_contour);
if (cur_contour_area > energy_part_param_.ARMOR_CONTOUR_AREA_MAX || if (cur_contour_area > energy_part_param_.ARMOR_CONTOUR_AREA_MAX ||
cur_contour_area < energy_part_param_.ARMOR_CONTOUR_AREA_MIN) cur_contour_area < energy_part_param_.ARMOR_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; //选区面积大小不合适
//选区面积大小不合适 }
} 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 < energy_part_param_.ARMOR_CONTOUR_LENGTH_MIN || width < energy_part_param_.ARMOR_CONTOUR_WIDTH_MIN ||
if (length < energy_part_param_.ARMOR_CONTOUR_LENGTH_MIN || width < energy_part_param_.ARMOR_CONTOUR_WIDTH_MIN || length > energy_part_param_.ARMOR_CONTOUR_LENGTH_MAX || width > energy_part_param_.ARMOR_CONTOUR_WIDTH_MAX) {
length > energy_part_param_.ARMOR_CONTOUR_LENGTH_MAX||width>energy_part_param_.ARMOR_CONTOUR_WIDTH_MAX) //cout<<"length width fail."<<endl;
{ return false;
//cout<<"length width fail."<<endl;
return false;
//矩形边长不合适 //矩形边长不合适
} }
float length_width_ratio = length / width;//计算矩形长宽比 float length_width_ratio = length / width;//计算矩形长宽比
if (length_width_ratio > energy_part_param_.ARMOR_CONTOUR_HW_RATIO_MAX || if (length_width_ratio > energy_part_param_.ARMOR_CONTOUR_HW_RATIO_MAX ||
length_width_ratio < energy_part_param_.ARMOR_CONTOUR_HW_RATIO_MIN) length_width_ratio < energy_part_param_.ARMOR_CONTOUR_HW_RATIO_MIN) {
{ //cout<<"length width ratio fail."<<endl;
//cout<<"length width ratio fail."<<endl; return false;
return false;
//长宽比不合适 //长宽比不合适
} }
if (cur_contour_area / cur_size.area() < energy_part_param_.ARMOR_CONTOUR_AREA_RATIO_MIN) return false;//轮廓对矩形的面积占有率不合适 if (cur_contour_area / cur_size.area() < energy_part_param_.ARMOR_CONTOUR_AREA_RATIO_MIN)
return true; return false;//轮廓对矩形的面积占有率不合适
return true;
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数用于判断找到的矩形候选区是否为可能的风车中心R候选区 // 此函数用于判断找到的矩形候选区是否为可能的风车中心R候选区
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
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_.ARMOR_CONTOUR_AREA_MAX ||
cur_contour_area < energy_part_param_.ARMOR_CONTOUR_AREA_MIN) cur_contour_area < energy_part_param_.ARMOR_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;
//选区面积大小不合适 //选区面积大小不合适
} }
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;//将矩形的短边设置为宽
if (length < energy_part_param_.CENTER_R_CONTOUR_LENGTH_MIN || width < energy_part_param_.CENTER_R_CONTOUR_WIDTH_MIN if (length < energy_part_param_.CENTER_R_CONTOUR_LENGTH_MIN || width < energy_part_param_.CENTER_R_CONTOUR_WIDTH_MIN
||length > energy_part_param_.CENTER_R_CONTOUR_LENGTH_MAX ||width>energy_part_param_.CENTER_R_CONTOUR_WIDTH_MAX) || length > energy_part_param_.CENTER_R_CONTOUR_LENGTH_MAX ||
{ width > energy_part_param_.CENTER_R_CONTOUR_WIDTH_MAX) {
//cout<<"length width fail."<<endl; //cout<<"length width fail."<<endl;
return false; return false;
//矩形边长不合适 //矩形边长不合适
} }
float length_width_ratio = length / width;//计算矩形长宽比 float length_width_ratio = length / width;//计算矩形长宽比
if (length_width_ratio > energy_part_param_.CENTER_R_CONTOUR_HW_RATIO_MAX || if (length_width_ratio > energy_part_param_.CENTER_R_CONTOUR_HW_RATIO_MAX ||
length_width_ratio < energy_part_param_.CENTER_R_CONTOUR_HW_RATIO_MIN) length_width_ratio < energy_part_param_.CENTER_R_CONTOUR_HW_RATIO_MIN) {
{
//cout<<"length width ratio fail."<<endl; //cout<<"length width ratio fail."<<endl;
return false; return false;
//长宽比不合适 //长宽比不合适
} }
if (cur_contour_area / cur_size.area() < energy_part_param_.CENTER_R_CONTOUR_AREA_RATIO_MIN) return false;//轮廓对矩形的面积占有率不合适 if (cur_contour_area / cur_size.area() < energy_part_param_.CENTER_R_CONTOUR_AREA_RATIO_MIN)
return false;//轮廓对矩形的面积占有率不合适
std::vector<cv::Point2f> intersection;
if (center_ROI.empty() || rotatedRectangleIntersection(cur_rect, center_ROI.at(0).rect, intersection) == 0 ||
contourArea(intersection) < energy_part_param_.CENTER_R_CONTOUR_INTERSETION_AREA_MIN) {
return false;
}
return true; return true;
} }
//----------------------------------------------------------------------------------------------------------------------
// 此函数用于判断找到的矩形候选区是否为流动条扇叶
// ---------------------------------------------------------------------------------------------------------------------
bool Energy::isValidFlowStripFanContour(const vector<cv::Point> &flow_strip_fan_contour) {
double cur_contour_area = contourArea(flow_strip_fan_contour);
if (cur_contour_area > energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_MAX ||
cur_contour_area < energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_MIN) {
//cout<<cur_contour_area<<" "<<energy_fan_param_.CONTOUR_AREA_MIN<<" "<<energy_fan_param_.CONTOUR_AREA_MAX<<endl;
//cout<<"area fail."<<endl;
return false;
//选区面积大小不合适
}
RotatedRect cur_rect = minAreaRect(flow_strip_fan_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 < energy_part_param_.FLOW_STRIP_FAN_CONTOUR_LENGTH_MIN
|| width < energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MIN
|| length > energy_part_param_.FLOW_STRIP_FAN_CONTOUR_LENGTH_MAX
|| width > energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MAX) {
//cout<<"length width fail."<<endl;
return false;
//矩形边长不合适
}
float length_width_ratio = length / width;//计算矩形长宽比
if (length_width_ratio > energy_part_param_.FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MAX ||
length_width_ratio < energy_part_param_.FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MIN) {
//cout<<"length width ratio fail."<<endl;
return false;
//长宽比不合适
}
if (cur_contour_area / cur_size.area() < energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_RATIO_MIN
|| cur_contour_area / cur_size.area() > energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_RATIO_MAX)
//如果ROI为空、或者选区与ROI无重合面积、或者有重合面积但重合面积太小
return false;
//轮廓对矩形的面积占有率不合适
return true;
}
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数用于判断找到的矩形候选区是否为流动条 // 此函数用于判断找到的矩形候选区是否为流动条
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
bool Energy::isValidFlowStripContour(const vector<cv::Point> flow_strip_contour) { bool Energy::isValidFlowStripContour(const vector<cv::Point> &flow_strip_contour) {
double cur_contour_area = contourArea(flow_strip_contour); double cur_contour_area = contourArea(flow_strip_contour);
if (cur_contour_area > energy_part_param_.FLOW_STRIP_CONTOUR_AREA_MAX || if (cur_contour_area > energy_part_param_.FLOW_STRIP_CONTOUR_AREA_MAX ||
cur_contour_area < energy_part_param_.FLOW_STRIP_CONTOUR_AREA_MIN) cur_contour_area < energy_part_param_.FLOW_STRIP_CONTOUR_AREA_MIN) {
{ // cout<<"area fail."<<endl;
//cout<<cur_contour_area<<" "<<energy_fan_param_.CONTOUR_AREA_MIN<<" "<<energy_fan_param_.CONTOUR_AREA_MAX<<endl;
//cout<<"area fail."<<endl;
return false; return false;
//选区面积大小不合适 //选区面积大小不合适
} }
@@ -336,26 +427,29 @@ bool Energy::isValidFlowStripContour(const vector<cv::Point> 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;//将矩形的短边设置为宽
if (length < energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MIN if (length < energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MIN ||
|| width < energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MIN width < energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MIN ||
||length > energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MAX length > energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MAX ||
||width > energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MAX) width > energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MAX) {
{ // cout<<"length width fail."<<endl;
//cout<<"length width fail."<<endl;
return false; return false;
//矩形边长不合适 //矩形边长不合适
} }
float length_width_ratio = length / width;//计算矩形长宽比 float length_width_ratio = length / width;//计算矩形长宽比
if (length_width_ratio > energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MAX || if (length_width_ratio > energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MAX ||
length_width_ratio < energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MIN) length_width_ratio < energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MIN) {
{ // cout<<"hw fail."<<endl;
//cout<<"length width ratio fail."<<endl;
return false; return false;
//长宽比不合适 //长宽比不合适
} }
if (cur_contour_area / cur_size.area() < energy_part_param_.FLOW_STRIP_CONTOUR_AREA_RATIO_MIN if (cur_contour_area / cur_size.area() < energy_part_param_.FLOW_STRIP_CONTOUR_AREA_RATIO_MIN)
|| cur_contour_area / cur_size.area() > energy_part_param_.FLOW_STRIP_CONTOUR_AREA_RATIO_MAX) return false; return false;//轮廓对矩形的面积占有率不合适
//轮廓对矩形的面积占有率不合适 std::vector<cv::Point2f> intersection;
if (flow_strip_fans.size() > 0 &&
rotatedRectangleIntersection(cur_rect, flow_strip_fans.at(0).rect, intersection) != 0) {
if (contourArea(intersection) < energy_part_param_.FLOW_STRIP_CONTOUR_INTERSETION_AREA_MIN) {
return false;
}
}
return true; return true;
} }

View File

@@ -98,16 +98,17 @@ void Energy::findTargetByIntersection() {
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数在流动条区域内寻找装甲板 // 此函数在流动条区域内寻找装甲板
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
bool Energy::findTargetInFlowStrip(){ bool Energy::findTargetInFlowStripFan(){
int i = 0; int i = 0;
for(i=0; i<armors.size(); ++i){ for(i=0; i<armors.size(); ++i){
std::vector<cv::Point2f> intersection; std::vector<cv::Point2f> intersection;
if(rotatedRectangleIntersection(armors.at(i).rect, flow_strips.at(0).rect, intersection)==0) if(rotatedRectangleIntersection(armors.at(i).rect, flow_strip_fans.at(0).rect, 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_.INTERSETION_CONTOUR_AREA_MIN) if(cur_contour_area < energy_part_param_.INTERSETION_CONTOUR_AREA_MIN)
continue; continue;
else{ else{
target_armor.emplace_back(armors.at(i));
target_point = armors.at(i).rect.center; target_point = armors.at(i).rect.center;
return true; return true;
} }

View File

@@ -77,7 +77,10 @@ int Energy::runBig(cv::Mat &gimble_src){
fans.clear(); fans.clear();
armors.clear(); armors.clear();
centerRs.clear(); centerRs.clear();
flow_strip_fans.clear();
flow_strips.clear(); flow_strips.clear();
center_ROI.clear();
target_armor.clear();
fan_polar_angle.clear(); fan_polar_angle.clear();
armor_polar_angle.clear(); armor_polar_angle.clear();
@@ -98,9 +101,10 @@ int Energy::runBig(cv::Mat &gimble_src){
getAllArmorCenters(); getAllArmorCenters();
circleLeastFit(); circleLeastFit();
flow_strips_cnt = findFlowStrip(gimble_src, last_flow_strips_cnt); flow_strip_fans_cnt = findFlowStripFan(gimble_src, last_flow_strip_fans_cnt);
if(flow_strips_cnt == 1 && findTargetInFlowStrip()){ if(flow_strip_fans_cnt == 1 && findTargetInFlowStripFan()){
showFlowStripContours("strip", gimble_src); findCenterROI(gimble_src);
showFlowStripFanContours("strip", gimble_src);
}else{ }else{
fans_cnt = findFan(gimble_src, last_fans_cnt); fans_cnt = findFan(gimble_src, last_fans_cnt);
if(fans_cnt==-1) return 0;//滤去漏判的帧 if(fans_cnt==-1) return 0;//滤去漏判的帧
@@ -114,7 +118,7 @@ int Energy::runBig(cv::Mat &gimble_src){
} }
centerRs_cnt = findCenterR(gimble_src); centerRs_cnt = findCenterR(gimble_src);
// if(centerRs_cnt>0)showCenterRContours("R", gimble_src); if(centerRs_cnt>0)showCenterRContours("R", gimble_src);
writeDownMark(); writeDownMark();

View File

@@ -139,7 +139,7 @@ void Energy::showCenterRContours(std::string windows_name, const cv::Mat src) {
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// 此函数用于显示图像中所有流动条 // 此函数用于显示图像中所有流动条
// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
void Energy::showFlowStripContours(std::string windows_name, const cv::Mat src) { void Energy::showFlowStripFanContours(std::string windows_name, const cv::Mat src) {
if (src.empty())return; if (src.empty())return;
static Mat image2show; static Mat image2show;
@@ -151,23 +151,36 @@ void Energy::showFlowStripContours(std::string windows_name, const cv::Mat src)
{ {
image2show = src.clone(); image2show = src.clone();
} }
for (const auto &flow_strip_fan : flow_strip_fans)
{
Point2f vertices[4]; //定义矩形的4个顶点
flow_strip_fan.rect.points(vertices); //计算矩形的4个顶点
for (int i = 0; i < 4; i++)
line(image2show, vertices[i], vertices[(i + 1) % 4], Scalar(127, 127, 255), 2);
}
for (const auto &flow_strip : flow_strips) for (const auto &flow_strip : flow_strips)
{ {
Point2f vertices[4]; //定义矩形的4个顶点 Point2f vertices[4]; //定义矩形的4个顶点
flow_strip.rect.points(vertices); //计算矩形的4个顶点 flow_strip.rect.points(vertices); //计算矩形的4个顶点
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
line(image2show, vertices[i], vertices[(i + 1) % 4], Scalar(127, 127, 255), 2); line(image2show, vertices[i], vertices[(i + 1) % 4], Scalar(0, 255, 0), 2);
} }
for (const auto &armor : armors) for (const auto &armor : armors){
{
if(pointDistance(armor.rect.center, target_point) < energy_part_param_.TWIN_POINT_MAX){ if(pointDistance(armor.rect.center, target_point) < energy_part_param_.TWIN_POINT_MAX){
Point2f vertices[4]; //定义矩形的4个顶点 Point2f vertices[4]; //定义矩形的4个顶点
armor.rect.points(vertices); //计算矩形的4个顶点 armor.rect.points(vertices); //计算矩形的4个顶点
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
line(image2show, vertices[i], vertices[(i + 1) % 4], Scalar(255, 255, 0), 2); line(image2show, vertices[i], vertices[(i + 1) % 4], Scalar(255, 255, 0), 2);
} }
} }
Point2f vertices[4]; //定义矩形的4个顶点
if(center_ROI.size() > 0){
center_ROI.at(0).rect.points(vertices); //计算矩形的4个顶点
for (int i = 0; i < 4; i++)
line(image2show, vertices[i], vertices[(i + 1) % 4], Scalar(0, 0, 255), 2);
}
imshow(windows_name, image2show); imshow(windows_name, image2show);
} }

View File

@@ -21,7 +21,7 @@ using namespace std;
mcu_data mcuData = { // 单片机端回传结构体 mcu_data mcuData = { // 单片机端回传结构体
0, // 当前云台yaw角 0, // 当前云台yaw角
0, // 当前云台pitch角 0, // 当前云台pitch角
ARMOR_STATE, // 当前状态,自瞄-大符-小符 SMALL_ENERGY_STATE, // 当前状态,自瞄-大符-小符
0, // 云台角度标记位 0, // 云台角度标记位
1, // 是否启用数字识别 1, // 是否启用数字识别
ENEMY_RED, // 敌方颜色 ENEMY_RED, // 敌方颜色
@@ -53,7 +53,7 @@ int main(int argc, char *argv[]) {
video_gimble = new CameraWrapper(0/*, "armor"*/); video_gimble = new CameraWrapper(0/*, "armor"*/);
video_chassis = new CameraWrapper(1/*, "energy"*/); video_chassis = new CameraWrapper(1/*, "energy"*/);
} else { } else {
video_gimble = new VideoWrapper("/home/sun/项目/energy_video/official_r_l.mp4"); video_gimble = new VideoWrapper("/home/sun/项目/energy_video/energy_test.avi");
video_chassis = new VideoWrapper("/home/sun/项目/energy_video/energy_test.avi"); video_chassis = new VideoWrapper("/home/sun/项目/energy_video/energy_test.avi");
} }
if (video_gimble->init()) { if (video_gimble->init()) {
@@ -114,9 +114,9 @@ int main(int argc, char *argv[]) {
energy.runBig(gimble_src); energy.runBig(gimble_src);
} }
} }
// cv::waitKey(3);
}); });
} while (ok); } while (ok);
delete video_gimble; delete video_gimble;
video_gimble = nullptr; video_gimble = nullptr;
delete video_chassis; delete video_chassis;