反陀螺v1.0完成。

This commit is contained in:
xinyang
2019-07-18 11:54:36 +08:00
parent d9bfdbb2eb
commit 6a0020ce81
11 changed files with 164 additions and 65 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

@@ -6,6 +6,7 @@
#define _ARMOR_FINDER_H_ #define _ARMOR_FINDER_H_
#include <map> #include <map>
#include <sys/time.h>
#include <constants.h> #include <constants.h>
#include <opencv2/core.hpp> #include <opencv2/core.hpp>
#include <opencv2/tracking.hpp> #include <opencv2/tracking.hpp>
@@ -22,6 +23,21 @@
#define DISTANCE_HEIGHT_5MM (113.0) // 单位: m*pixel #define DISTANCE_HEIGHT_5MM (113.0) // 单位: m*pixel
#define DISTANCE_HEIGHT DISTANCE_HEIGHT_5MM #define DISTANCE_HEIGHT DISTANCE_HEIGHT_5MM
#define B1 1
#define B2 2
#define B3 3
#define B4 4
#define B5 5
#define B7 6
#define B8 7
#define R1 8
#define R2 9
#define R3 10
#define R4 11
#define R5 12
#define R7 13
#define R8 14
extern std::map<int, string> id2name; //装甲板id到名称的map extern std::map<int, string> id2name; //装甲板id到名称的map
extern std::map<string, int> name2id; //装甲板名称到id的map extern std::map<string, int> name2id; //装甲板名称到id的map
@@ -45,6 +61,10 @@ typedef std::vector<LightBlob> LightBlobs;
/******************* 装甲板类定义 **********************/ /******************* 装甲板类定义 **********************/
class ArmorBox{ class ArmorBox{
public: public:
typedef enum{
FRONT, SIDE, UNKNOWN
} BoxOrientation;
cv::Rect2d rect; cv::Rect2d rect;
LightBlobs light_blobs; LightBlobs light_blobs;
uint8_t box_color; uint8_t box_color;
@@ -55,6 +75,8 @@ public:
double blobsDistance() const; double blobsDistance() const;
double lengthRatio() const; double lengthRatio() const;
double lengthDistanceRatio() const; double lengthDistanceRatio() const;
double getDistance() const;
BoxOrientation getOrientation() const;
}; };
typedef std::vector<ArmorBox> ArmorBoxes; typedef std::vector<ArmorBox> ArmorBoxes;
@@ -72,6 +94,10 @@ private:
SEARCHING_STATE, TRACKING_STATE, STANDBY_STATE SEARCHING_STATE, TRACKING_STATE, STANDBY_STATE
} State; // 自瞄状态枚举定义 } State; // 自瞄状态枚举定义
typedef enum{
NORMAL, ANTI_TOP
} AntiTopState;
const uint8_t &enemy_color; // 敌方颜色,引用外部变量,自动变化 const uint8_t &enemy_color; // 敌方颜色,引用外部变量,自动变化
State state; // 自瞄状态对象实例 State state; // 自瞄状态对象实例
ArmorBox armor_box; // 当前目标装甲板 ArmorBox armor_box; // 当前目标装甲板
@@ -81,6 +107,10 @@ private:
int tracking_cnt; // 记录追踪帧数,用于定时退出追踪 int tracking_cnt; // 记录追踪帧数,用于定时退出追踪
Serial &serial; // 串口对象,引用外部变量,用于和能量机关共享同一个变量 Serial &serial; // 串口对象,引用外部变量,用于和能量机关共享同一个变量
const uint8_t &use_classifier; // 标记是否启用CNN分类器引用外部变量自动变化 const uint8_t &use_classifier; // 标记是否启用CNN分类器引用外部变量自动变化
ArmorBox::BoxOrientation last_orient; // 上一帧目标装甲板方向,用于反陀螺
timeval last_switch_time; // 上一次发生装甲板方向切换的时间
int anti_top_cnt; // 满足条件的装甲板方向切换持续次数,用于反陀螺
AntiTopState anti_top_state; // 当前是否识别到陀螺
bool findLightBlobs(const cv::Mat &src, LightBlobs &light_blobs); bool findLightBlobs(const cv::Mat &src, LightBlobs &light_blobs);
bool findArmorBox(const cv::Mat &src, ArmorBox &box); bool findArmorBox(const cv::Mat &src, ArmorBox &box);
@@ -89,7 +119,7 @@ private:
bool stateTrackingTarget(cv::Mat &src); // tracking state主函数 bool stateTrackingTarget(cv::Mat &src); // tracking state主函数
bool stateStandBy(); // stand by state主函数已弃用 bool stateStandBy(); // stand by state主函数已弃用
void anti_top(); // 反小陀螺 void antiTop(); // 反小陀螺
public: public:
void run(cv::Mat &src); // 自瞄主函数 void run(cv::Mat &src); // 自瞄主函数

View File

@@ -4,49 +4,56 @@
#include <armor_finder/armor_finder.h> #include <armor_finder/armor_finder.h>
#define B1 1 static double getTimeIntervalms(const timeval& now, const timeval &last){
#define B2 2 return (now.tv_sec-last.tv_sec)*1000.0 + (now.tv_usec-last.tv_usec)/1000.0;
#define B3 3 }
#define B4 4
#define B5 5 void ArmorFinder::antiTop() {
#define B7 6 if(anti_top_state == ANTI_TOP){
#define B8 7 cout << "anti top" << endl;
#define R1 8 }else if(anti_top_state == NORMAL){
#define R2 9 cout << "Normal" << endl;
#define R3 10 }
#define R4 11 ArmorBox::BoxOrientation orientation = armor_box.getOrientation();
#define R5 12 if(orientation == ArmorBox::UNKNOWN){
#define R7 13 if(anti_top_state == NORMAL){
#define R8 14 sendBoxPosition();
return;
}else{
void ArmorFinder::anti_top() { return;
// switch (armor_box.id) { }
// case R1: }
// case R7: if(orientation!=last_orient){
// case B1: timeval curr_time;
// case B7: gettimeofday(&curr_time, nullptr);
// if (armor_box.rect != cv::Rect2d()) { auto interval = getTimeIntervalms(curr_time, last_switch_time);
// sendBoxPosition(); cout << interval << endl;
// } if(50 < interval && interval < 700){
// case R2: anti_top_cnt++;
// case R3: }else{
// case R4: anti_top_cnt = 0;
// case R5: }
// case B2: last_switch_time = curr_time;
// case B3: }else{
// case B4: timeval curr_time;
// case B5: gettimeofday(&curr_time, nullptr);
// if (armor_box.rect != cv::Rect2d()) { if(getTimeIntervalms(curr_time, last_switch_time) > 700) {
// sendBoxPosition(); anti_top_state = NORMAL;
// } }
// default: }
// if (armor_box.rect != cv::Rect2d()) { if(anti_top_cnt > 4){
// sendBoxPosition(); anti_top_state = ANTI_TOP;
// } }
// }
if (armor_box.rect != cv::Rect2d()) { if(anti_top_state == ANTI_TOP){
sendBoxPosition(); if(orientation == ArmorBox::FRONT){
} sendBoxPosition();
}
}else if(anti_top_state == NORMAL){
sendBoxPosition();
}
last_orient = orientation;
} }

View File

@@ -36,3 +36,44 @@ double ArmorBox::lengthDistanceRatio() const {
return 100; return 100;
} }
} }
double ArmorBox::getDistance() const{
if(light_blobs.size() == 2 ){
return DISTANCE_HEIGHT / 2 / max(light_blobs[0].length, light_blobs[1].length);
} else {
return DISTANCE_HEIGHT / rect.height;
}
}
ArmorBox::BoxOrientation ArmorBox::getOrientation() const{
// cout << lengthDistanceRatio() << endl;
if(light_blobs.size() != 2){
return UNKNOWN;
}
switch (id) {
case R1:
case R7:
case B1:
case B7:
if(lengthDistanceRatio() < 0.3){
return FRONT;
}else{
return SIDE;
}
case R2:
case R3:
case R4:
case R5:
case B2:
case B3:
case B4:
case B5:
if (lengthDistanceRatio() < 0.43) {
return FRONT;
}else{
return SIDE;
}
default:
return UNKNOWN;
}
}

View File

@@ -78,7 +78,7 @@ void ArmorFinder::run(cv::Mat &src) {
stateStandBy(); stateStandBy();
} }
anti_top(); antiTop();
if (show_armor_box) { // 根据条件显示当前目标装甲板 if (show_armor_box) { // 根据条件显示当前目标装甲板
showArmorBox("box", src, armor_box); showArmorBox("box", src, armor_box);

View File

@@ -72,20 +72,11 @@ static bool boxAngleJudge(const LightBlob &light_blob_i, const LightBlob &light_
} }
static bool isCoupleLight(const LightBlob &light_blob_i, const LightBlob &light_blob_j, uint8_t enemy_color) { static bool isCoupleLight(const LightBlob &light_blob_i, const LightBlob &light_blob_j, uint8_t enemy_color) {
// cout << (light_blob_i.blob_color==BLOB_RED) << endl;
// cout << (light_blob_j.blob_color==BLOB_RED) << endl;
// cout << lengthRatioJudge(light_blob_i, light_blob_j) << endl;
// cout << lengthJudge(light_blob_i, light_blob_j) << endl;
//// cout << heightJudge(light_blob_i, light_blob_j) << endl;
// cout << angelJudge(light_blob_i, light_blob_j) << endl;
// cout << boxAngleJudge(light_blob_i, light_blob_j) << endl;
// cout << CuoWeiDuJudge(light_blob_i, light_blob_j) << endl;
// cout << "=============" << endl;
return light_blob_i.blob_color == enemy_color && return light_blob_i.blob_color == enemy_color &&
light_blob_j.blob_color == enemy_color && light_blob_j.blob_color == enemy_color &&
lengthRatioJudge(light_blob_i, light_blob_j) && lengthRatioJudge(light_blob_i, light_blob_j) &&
lengthJudge(light_blob_i, light_blob_j) && lengthJudge(light_blob_i, light_blob_j) &&
// heightJudge(light_blob_i, light_blob_j) && // heightJudge(light_blob_i, light_blob_j) &&
angelJudge(light_blob_i, light_blob_j) && angelJudge(light_blob_i, light_blob_j) &&
boxAngleJudge(light_blob_i, light_blob_j) && boxAngleJudge(light_blob_i, light_blob_j) &&
CuoWeiDuJudge(light_blob_i, light_blob_j); CuoWeiDuJudge(light_blob_i, light_blob_j);

View File

@@ -121,7 +121,7 @@ bool ArmorFinder::findLightBlobs(const cv::Mat &src, LightBlobs &light_blobs) {
color_channel = channels[0]; /* 根据目标颜色进行通道提取 */ color_channel = channels[0]; /* 根据目标颜色进行通道提取 */
else if (enemy_color == ENEMY_RED) /* */ else if (enemy_color == ENEMY_RED) /* */
color_channel = channels[2]; /************************/ color_channel = channels[2]; /************************/
cv::threshold(color_channel, src_bin, 160, 255, CV_THRESH_BINARY); // 二值化对应通道 cv::threshold(color_channel, src_bin, 170, 255, CV_THRESH_BINARY); // 二值化对应通道
imagePreProcess(src_bin); // 开闭运算 imagePreProcess(src_bin); // 开闭运算
if(src_bin.size() == cv::Size(640, 480)) if(src_bin.size() == cv::Size(640, 480))

View File

@@ -95,14 +95,41 @@ void showArmorBox(std::string windows_name, const cv::Mat &src, const ArmorBox &
// if(box.light_blobs.size() == 2) // if(box.light_blobs.size() == 2)
// fprintf(fp, "%lf %lf %lf\n", box.light_blobs[0].length, box.light_blobs[1].length, box.blobsDistance()) // fprintf(fp, "%lf %lf %lf\n", box.light_blobs[0].length, box.light_blobs[1].length, box.blobsDistance())
// cout << box.lengthDistanceRatio() << endl; // cout << box.lengthDistanceRatio() << endl;
if(box.lengthDistanceRatio() < 0.4 && box.lengthRatio() > 0.9){ switch (box.id) {
rectangle(image2show, box.rect, Scalar(0, 255, 0), 3); case R1:
}else{ case R7:
rectangle(image2show, box.rect, Scalar(0, 255, 0), 1); case B1:
}; case B7:
if(box.lengthDistanceRatio() < 0.3){
rectangle(image2show, box.rect, Scalar(0, 255, 0), 3);
}else{
rectangle(image2show, box.rect, Scalar(0, 255, 0), 1);
}
case R2:
case R3:
case R4:
case R5:
case B2:
case B3:
case B4:
case B5:
if (box.lengthDistanceRatio() < 0.42) {
rectangle(image2show, box.rect, Scalar(0, 255, 0), 3);
}else{
rectangle(image2show, box.rect, Scalar(0, 255, 0), 1);
}
break;
default:
rectangle(image2show, box.rect, Scalar(0, 255, 0), 1);
}
// if((id2name.at(box.id)=="B1"||id2name.at(box.id)=="B7") && box.lengthDistanceRatio() < 0.3/* && box.lengthRatio() > 0.9*/){
// rectangle(image2show, box.rect, Scalar(0, 255, 0), 3);
// }else{
// rectangle(image2show, box.rect, Scalar(0, 255, 0), 1);
// };
char dist[5]; char dist[5];
// sprintf(dist, "%.1f", distance); sprintf(dist, "%.1f", box.getDistance());
if (box.id == -1) if (box.id == -1)
putText(image2show, id2name[box.id]+" "+dist, Point(box.rect.x + 2, box.rect.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1, putText(image2show, id2name[box.id]+" "+dist, Point(box.rect.x + 2, box.rect.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
Scalar(0, 255, 0)); Scalar(0, 255, 0));

View File

@@ -30,7 +30,7 @@ using namespace std;
mcu_data mcuData = { // 单片机端回传结构体 mcu_data mcuData = { // 单片机端回传结构体
0, // 当前云台yaw角 0, // 当前云台yaw角
0, // 当前云台pitch角 0, // 当前云台pitch角
BIG_ENERGY_STATE, // 当前状态,自瞄-大符-小符 ARMOR_STATE, // 当前状态,自瞄-大符-小符
0, // 云台角度标记位 0, // 云台角度标记位
1, // 是否启用数字识别 1, // 是否启用数字识别
ENEMY_RED, // 敌方颜色 ENEMY_RED, // 敌方颜色

View File

@@ -48,6 +48,7 @@ public:
bool readRaw(cv::Mat& src); bool readRaw(cv::Mat& src);
bool readProcessed(cv::Mat& src); bool readProcessed(cv::Mat& src);
bool changeBrightness(int brightness); bool changeBrightness(int brightness);
// bool once
}; };

View File

@@ -78,10 +78,12 @@ bool CameraWrapper::init() {
CameraSetAeState(h_camera, false); CameraSetAeState(h_camera, false);
CameraSetExposureTime(h_camera, CAMERA_EXPOSURE*1000); CameraSetExposureTime(h_camera, CAMERA_EXPOSURE*1000);
CameraSetAnalogGain(h_camera, ARMOR_CAMERA_GAIN); CameraSetAnalogGain(h_camera, ARMOR_CAMERA_GAIN);
CameraSetWbMode(h_camera, false);
if(mode == 0){ if(mode == 0){
CameraSetGain(h_camera, CAMERA_BLUE_GAIN, CAMERA_GREEN_GAIN, CAMERA_RED_GAIN); CameraSetGain(h_camera, CAMERA_BLUE_GAIN, CAMERA_GREEN_GAIN, CAMERA_RED_GAIN);
CameraSetLutMode(h_camera, LUTMODE_PRESET); CameraSetLutMode(h_camera, LUTMODE_PRESET);
} }
CameraSetOnceWB(h_camera);
#endif #endif
double t; double t;
CameraGetExposureTime(h_camera, &t); CameraGetExposureTime(h_camera, &t);