Merge remote-tracking branch 'origin/master'

# Conflicts:
#	armor/src/armor_finder/anti_top/anti_top.cpp
#	armor/src/armor_finder/find/find_light_blobs.cpp
#	main.cpp
This commit is contained in:
xinyang
2019-07-23 14:06:47 +08:00
47 changed files with 27710 additions and 18821 deletions

View File

@@ -6,6 +6,7 @@
#define _ARMOR_FINDER_H_
#include <map>
#include <sys/time.h>
#include <constants.h>
#include <opencv2/core.hpp>
#include <opencv2/tracking.hpp>
@@ -13,14 +14,37 @@
#include <armor_finder/classifier/classifier.h>
#include <additions/additions.h>
#define BLOB_RED ENEMY_RED
#define BLOB_BLUE ENEMY_BLUE
#define BLOB_RED ENEMY_RED
#define BLOB_BLUE ENEMY_BLUE
#define DISTANCE_HEIGHT_5MM (113.0) // 单位: m*pixel
#define BOX_RED ENEMY_RED
#define BOX_BLUE ENEMY_BLUE
#define IMAGE_CENTER_X (320)
#define IMAGE_CENTER_Y (240-20)
#define DISTANCE_HEIGHT_5MM (107.0) // 单位: m*pixel
#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<string, int> name2id; //装甲板名称到id的map
extern std::map<string, int> prior_blue;
extern std::map<string, int> prior_red;
/******************* 灯条类定义 ***********************/
@@ -28,15 +52,43 @@ class LightBlob {
public:
cv::RotatedRect rect; //灯条位置
double length; //灯条长度
uint8_t BlobColor; //灯条颜色
uint8_t blob_color; //灯条颜色
LightBlob(cv::RotatedRect &r) : rect(r) {
LightBlob(cv::RotatedRect &r, uint8_t color) : rect(r), blob_color(color) {
length = max(rect.size.height, rect.size.width);
};
LightBlob() = default;
};
typedef std::vector<LightBlob> LightBlobs;
/******************* 装甲板类定义 **********************/
class ArmorBox{
public:
typedef enum{
FRONT, SIDE, UNKNOWN
} BoxOrientation;
cv::Rect2d rect;
LightBlobs light_blobs;
uint8_t box_color;
int id;
explicit ArmorBox(const cv::Rect &pos=cv::Rect2d(), const LightBlobs &blobs=LightBlobs(), uint8_t color=0, int i=0);
double getBlobsDistance() const;
double lengthDistanceRatio() const;
double getBoxDistance() const;
BoxOrientation getOrientation() const;
// double
bool operator<(const ArmorBox &box) const;
};
typedef std::vector<ArmorBox> ArmorBoxes;
/********************* 自瞄类定义 **********************/
class ArmorFinder{
public:
@@ -50,30 +102,36 @@ private:
SEARCHING_STATE, TRACKING_STATE, STANDBY_STATE
} State; // 自瞄状态枚举定义
cv::Mat src_raw; // 当前原图
typedef enum{
NORMAL, ANTI_TOP
} AntiTopState;
const uint8_t &enemy_color; // 敌方颜色,引用外部变量,自动变化
State state; // 自瞄状态对象实例
cv::Rect2d armor_box; // 当前目标位置
int boxid; // 当前目标id
ArmorBox armor_box; // 当前目标装甲板
cv::Ptr<cv::Tracker> tracker; // tracker对象实例
Classifier classifier; // CNN分类器对象实例用于数字识别
int contour_area; // 装甲区域亮点个数,用于数字识别未启用时判断是否跟丢(已弃用)
int tracking_cnt; // 记录追踪帧数,用于定时退出追踪
Serial &serial; // 串口对象,引用外部变量,用于和能量机关共享同一个变量
const uint8_t &use_classifier; // 标记是否启用CNN分类器引用外部变量自动变化
ArmorBox::BoxOrientation last_orient; // 上一帧目标装甲板方向,用于反陀螺
timeval last_front_time; // 上一次发生装甲板方向切换的时间
int anti_top_cnt; // 满足条件的装甲板方向切换持续次数,用于反陀螺
AntiTopState anti_top_state; // 当前是否识别到陀螺
bool findLightBlobs(const cv::Mat &src, LightBlobs &light_blobs);
bool findArmorBox(const cv::Mat &src, ArmorBox &box);
bool stateSearchingTarget(cv::Mat &src); // searching state主函数
bool stateTrackingTarget(cv::Mat &src); // tracking state主函数
bool stateStandBy(); // stand by state主函数已弃用
bool findLightBlobs(const cv::Mat &src_bin, // 在二值图上寻找灯条
LightBlobs &light_blobs);
bool findArmorBoxes(const LightBlobs &light_blobs, // 根据灯条匹配装甲板候选区
std::vector<cv::Rect2d> &armor_boxes);
void antiTop(); // 反小陀螺
public:
void run(cv::Mat &src); // 自瞄主函数
bool sendBoxPosition(); // 和主控板通讯
bool sendBoxPosition(uint16_t shoot); // 和主控板通讯
};
#endif /* _ARMOR_FINDER_H_ */

View File

@@ -9,9 +9,10 @@
#include <armor_finder/armor_finder.h>
//
void showArmorBoxVector(std::string windows_name, const cv::Mat &src, const std::vector<cv::Rect2d> &armor_box);
void showArmorBox(std::string windows_name, const cv::Mat &src, cv::Rect2d armor_box, int boxid);
void showContours(std::string windows_name, const cv::Mat &src, const std::vector<LightBlob> &light_blobs);
void showArmorBoxClass(std::string window_names, const cv::Mat &src, vector<cv::Rect2d> boxes[10]);
void showArmorBoxes(std::string windows_name, const cv::Mat &src, const ArmorBoxes &armor_boxes);
void showArmorBox(std::string windows_name, const cv::Mat &src, const ArmorBox &armor_box);
void showLightBlobs(std::string windows_name, const cv::Mat &src, const LightBlobs &light_blobs);
void showArmorBoxesClass(std::string window_names, const cv::Mat &src, const ArmorBoxes &boxes);
void showTrackSearchingPos(std::string window_names, const cv::Mat &src, const cv::Rect2d pos);
#endif /* _SHOW_IMAGES_H_ */

View File

@@ -11,8 +11,7 @@ static double getTimeIntervalms(const timeval& now, const timeval &last){
void ArmorFinder::antiTop() {
static double top_periodms = 0;
static double last1_top_periodms = 0;
static double last2_top_periodms = 0;
static double last_top_periodms = 0;
uint16_t shoot_delay = 0;
timeval curr_time;
// if(anti_top_state == ANTI_TOP){
@@ -40,11 +39,10 @@ void ArmorFinder::antiTop() {
last_front_time = curr_time;
if(150<interval && interval<700){
if(anti_top_state == ANTI_TOP){
last2_top_periodms = last1_top_periodms;
last1_top_periodms = top_periodms;
last_top_periodms = top_periodms;
top_periodms = interval;
LOGM(STR_CTR(WORD_LIGHT_GREEN, "top period: %.1lf ms"), top_periodms);
shoot_delay = (last1_top_periodms+last1_top_periodms+top_periodms)/3.0-105;
shoot_delay = (last_top_periodms+top_periodms)/2.0-110;
last_orient = orientation;
}else if(anti_top_state == NORMAL){
// LOGM("interval:%.1lf", interval);

View File

@@ -0,0 +1,88 @@
//
// Created by xinyang on 19-7-13.
//
#include <armor_finder/armor_finder.h>
#include <log.h>
ArmorBox::ArmorBox(const cv::Rect &pos, const LightBlobs &blobs, uint8_t color, int i) :
rect(pos), light_blobs(blobs), box_color(color), id(i) {};
double ArmorBox::getBlobsDistance() const {
if (light_blobs.size() == 2) {
auto &x = light_blobs[0].rect.center;
auto &y = light_blobs[1].rect.center;
return sqrt((x.x - y.x) * (x.x - y.x) + (x.y - y.y) * (x.y - y.y));
} else {
return 0;
}
}
double ArmorBox::lengthDistanceRatio() const {
if (light_blobs.size() == 2) {
return max(light_blobs[0].length, light_blobs[1].length)
/ getBlobsDistance();
} else {
return 100;
}
}
double ArmorBox::getBoxDistance() 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 R8:
case B1:
case B7:
case B8:
if (lengthDistanceRatio() < 0.24) {
return FRONT;
} else {
return SIDE;
}
case R2:
case R3:
case R4:
case R5:
case B2:
case B3:
case B4:
case B5:
if (lengthDistanceRatio() < 0.48) {
return FRONT;
} else {
return SIDE;
}
default:
return UNKNOWN;
}
}
bool ArmorBox::operator<(const ArmorBox &box) const {
if (id != box.id) {
if (box_color == BOX_BLUE) {
return prior_blue[id2name[id]] < prior_blue[id2name[box.id]];
} else {
return prior_red[id2name[id]] < prior_red[id2name[box.id]];
}
} else {
auto d1 = (rect.x-IMAGE_CENTER_X)*(rect.x-IMAGE_CENTER_X)
+ (rect.y-IMAGE_CENTER_Y)*(rect.y-IMAGE_CENTER_Y);
auto d2 = (box.rect.x-IMAGE_CENTER_X)*(box.rect.x-IMAGE_CENTER_X)
+ (box.rect.y-IMAGE_CENTER_Y)*(box.rect.y-IMAGE_CENTER_Y);
return d1 < d2;
}
}

View File

@@ -35,6 +35,18 @@ std::map<string, int> name2id = { //装甲板名
{"R1", 8},{"R2", 9},{"R3", 10},{"R4", 11},{"R5", 12},{"R7", 13},{"R8", 14},
};
std::map<string, int> prior_blue = {
{"B8", 0}, {"B1", 1}, {"B3", 2}, {"B4", 2}, {"B5", 2}, {"B7", 3}, {"B2", 4},
{"R8", 5}, {"R1", 6}, {"R3", 7}, {"R4", 7}, {"R5", 7}, {"R7", 8}, {"R2", 9},
{"NO", 10},
};
std::map<string, int> prior_red = {
{"R8", 0}, {"R1", 1}, {"R3", 2}, {"R4", 2}, {"R5", 2}, {"R7", 3}, {"R2", 4},
{"B8", 5}, {"B1", 6}, {"B3", 7}, {"B4", 7}, {"B5", 7}, {"B7", 8}, {"B2", 9},
{"NO", 10},
};
ArmorFinder::ArmorFinder(uint8_t &color, Serial &u, const string &paras_folder, const uint8_t &use) :
serial(u),
enemy_color(color),
@@ -42,32 +54,25 @@ ArmorFinder::ArmorFinder(uint8_t &color, Serial &u, const string &paras_folder,
classifier(paras_folder),
contour_area(0),
use_classifier(use),
boxid(-1),
tracking_cnt(0) {
}
void ArmorFinder::run(cv::Mat &src) {
src_raw = src;
cv::Mat src_use = src.clone(); // 实际参与计算的图像对象
if (show_armor_box) { // 根据条件显示当前目标装甲板
showArmorBox("box", src, armor_box, boxid);
cv::waitKey(1);
}
// stateSearchingTarget(src_use); // for debug
// return;
// stateSearchingTarget(src); // for debug
// goto end;
switch (state) {
case SEARCHING_STATE:
if (stateSearchingTarget(src_use)) {
if ((armor_box & cv::Rect2d(0, 0, 640, 480)) == armor_box) { // 判断装甲板区域是否脱离图像区域
if (stateSearchingTarget(src)) {
// cout << armor_box.rect << endl;
if ((armor_box.rect & cv::Rect2d(0, 0, 640, 480)) == armor_box.rect) { // 判断装甲板区域是否脱离图像区域
if (!classifier || !use_classifier) { /* 如果分类器不可用或者不使用分类器 */
cv::Mat roi = src_use.clone()(armor_box), roi_gray; /* 就使用装甲区域亮点数判断是否跟丢 */
cv::Mat roi = src(armor_box.rect).clone(), roi_gray; /* 就使用装甲区域亮点数判断是否跟丢 */
cv::cvtColor(roi, roi_gray, CV_RGB2GRAY);
cv::threshold(roi_gray, roi_gray, 180, 255, cv::THRESH_BINARY);
contour_area = cv::countNonZero(roi_gray);
}
tracker = TrackerToUse::create(); // 成功搜寻到装甲板创建tracker对象
tracker->init(src_use, armor_box);
tracker->init(src, armor_box.rect);
state = TRACKING_STATE;
tracking_cnt = 0;
LOGM(STR_CTR(WORD_LIGHT_CYAN, "into track"));
@@ -75,7 +80,7 @@ void ArmorFinder::run(cv::Mat &src) {
}
break;
case TRACKING_STATE:
if (!stateTrackingTarget(src_use) || ++tracking_cnt > 100) { // 最多追踪100帧图像
if (!stateTrackingTarget(src) || ++tracking_cnt > 100) { // 最多追踪100帧图像
state = SEARCHING_STATE;
LOGM(STR_CTR(WORD_LIGHT_YELLOW, "into search!"));
}
@@ -84,5 +89,12 @@ void ArmorFinder::run(cv::Mat &src) {
default:
stateStandBy();
}
end:
antiTop();
if (show_armor_box) { // 根据条件显示当前目标装甲板
showArmorBox("box", src, armor_box);
cv::waitKey(1);
}
}

View File

@@ -1,15 +1,21 @@
//
// Created by xinyang on 19-7-10.
// Created by xinyang on 19-7-18.
//
#include <armor_finder/armor_finder.h>
#include <show_images/show_images.h>
#include <options/options.h>
#include <opencv2/highgui.hpp>
#include <log.h>
static bool angelJudge(const LightBlob &light_blob_i, const LightBlob &light_blob_j) {
float angle_i = light_blob_i.rect.size.width > light_blob_i.rect.size.height ? light_blob_i.rect.angle :
light_blob_i.rect.angle - 90;
float angle_j = light_blob_j.rect.size.width > light_blob_j.rect.size.height ? light_blob_j.rect.angle :
light_blob_j.rect.angle - 90;
return abs(angle_i - angle_j) < 10;
return abs(angle_i - angle_j) < 20;
}
static bool heightJudge(const LightBlob &light_blob_i, const LightBlob &light_blob_j) {
@@ -21,12 +27,12 @@ static bool lengthJudge(const LightBlob &light_blob_i, const LightBlob &light_bl
double side_length;
cv::Point2f centers = light_blob_i.rect.center - light_blob_j.rect.center;
side_length = sqrt(centers.ddot(centers));
return (side_length / light_blob_i.length < 6 && side_length / light_blob_i.length > 0.5);
return (side_length / light_blob_i.length < 8 && side_length / light_blob_i.length > 0.5);
}
static bool lengthRatioJudge(const LightBlob &light_blob_i, const LightBlob &light_blob_j) {
return (light_blob_i.length / light_blob_j.length < 2
&& light_blob_i.length / light_blob_j.length > 0.5);
return (light_blob_i.length / light_blob_j.length < 2.5
&& light_blob_i.length / light_blob_j.length > 0.4);
}
/* 判断两个灯条的错位度,不知道英文是什么!!! */
@@ -42,7 +48,7 @@ static bool CuoWeiDuJudge(const LightBlob &light_blob_i, const LightBlob &light_
Vector2f orientation(cos(angle), sin(angle));
Vector2f p2p(light_blob_j.rect.center.x - light_blob_i.rect.center.x,
light_blob_j.rect.center.y - light_blob_i.rect.center.y);
return abs(orientation.dot(p2p)) < 20;
return abs(orientation.dot(p2p)) < 25;
}
static bool boxAngleJudge(const LightBlob &light_blob_i, const LightBlob &light_blob_j) {
@@ -58,8 +64,8 @@ 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) {
return light_blob_i.BlobColor == enemy_color &&
light_blob_j.BlobColor == enemy_color &&
return light_blob_i.blob_color == enemy_color &&
light_blob_j.blob_color == enemy_color &&
lengthRatioJudge(light_blob_i, light_blob_j) &&
lengthJudge(light_blob_i, light_blob_j) &&
// heightJudge(light_blob_i, light_blob_j) &&
@@ -75,10 +81,11 @@ static double centerDistance(const cv::Rect2d &box) {
return dx * dx + dy * dy;
}
bool ArmorFinder::findArmorBoxes(const LightBlobs &light_blobs, std::vector<cv::Rect2d> &armor_boxes) {
bool matchArmorBoxes(const cv::Mat &src, const LightBlobs &light_blobs, ArmorBoxes &armor_boxes, uint8_t color) {
armor_boxes.clear();
for (int i = 0; i < light_blobs.size() - 1; ++i) {
for (int j = i + 1; j < light_blobs.size(); ++j) {
if (!isCoupleLight(light_blobs.at(i), light_blobs.at(j), enemy_color)) {
if (!isCoupleLight(light_blobs.at(i), light_blobs.at(j), color)) {
continue;
}
cv::Rect2d rect_left = light_blobs.at(static_cast<unsigned long>(i)).rect.boundingRect();
@@ -89,17 +96,73 @@ bool ArmorFinder::findArmorBoxes(const LightBlobs &light_blobs, std::vector<cv::
min_y = fmin(rect_left.y, rect_right.y) - 0.5 * (rect_left.height + rect_right.height) / 2.0;
max_y = fmax(rect_left.y + rect_left.height, rect_right.y + rect_right.height) +
0.5 * (rect_left.height + rect_right.height) / 2.0;
if (min_x < 0 || max_x > 640 || min_y < 0 || max_y > 480) {
if (min_x < 0 || max_x > src.cols || min_y < 0 || max_y > src.rows) {
continue;
}
armor_boxes.emplace_back(cv::Rect2d(min_x, min_y, max_x - min_x, max_y - min_y));
LightBlobs pair_blobs = {light_blobs.at(i), light_blobs.at(j)};
armor_boxes.emplace_back(
cv::Rect2d(min_x, min_y, max_x - min_x, max_y - min_y),
pair_blobs,
color
);
}
}
if (armor_boxes.empty()) {
return !armor_boxes.empty();
}
bool ArmorFinder::findArmorBox(const cv::Mat &src, ArmorBox &box) {
LightBlobs light_blobs; // 存储所有可能的灯条
ArmorBoxes armor_boxes; // 装甲板候选区
box.rect = cv::Rect2d(0, 0, 0, 0);
box.id = -1;
if (!findLightBlobs(src, light_blobs)) {
return false;
}
sort(armor_boxes.begin(), armor_boxes.end(), [](cv::Rect2d box1, cv::Rect2d box2) -> bool {
return centerDistance(box1) < centerDistance(box2);
});
if (show_light_blobs && src.size() == cv::Size(640, 480)) {
showLightBlobs("light_blobs", src, light_blobs);
cv::waitKey(1);
}
if (!matchArmorBoxes(src, light_blobs, armor_boxes, enemy_color)) {
// cout << "Box fail!" << endl;
return false;
}
if (show_armor_boxes && src.size() == cv::Size(640, 480)) {
showArmorBoxes("boxes", src, armor_boxes);
cv::waitKey(1);
}
if (classifier && use_classifier) {
for (auto &armor_box : armor_boxes) {
cv::Mat roi = src(armor_box.rect).clone();
cv::resize(roi, roi, cv::Size(48, 36));
int c = classifier(roi);
armor_box.id = c;
}
sort(armor_boxes.begin(), armor_boxes.end());
if(armor_boxes[0].id != 0){
box = armor_boxes[0];
}
if (save_labelled_boxes) {
for (const auto &one_box : armor_boxes) {
char filename[100];
sprintf(filename, PROJECT_DIR"/armor_box_photo/%s_%d.jpg", id2name[one_box.id].data(),
time(nullptr) + clock());
cv::imwrite(filename, src(armor_box.rect & cv::Rect(0, 0, src.rows, src.cols)));
}
}
if (box.rect == cv::Rect2d(0, 0, 0, 0)) {
return false;
}
if (show_armor_boxes && src.size() == cv::Size(640, 480)) {
showArmorBoxesClass("class", src, armor_boxes);
}
} else {
box = armor_boxes[0];
}
return true;
}
}

View File

@@ -128,9 +128,11 @@ bool ArmorFinder::findLightBlobs(const cv::Mat &src, LightBlobs &light_blobs) {
cv::threshold(color_channel, src_bin_light, 200, 255, CV_THRESH_BINARY); // 二值化对应通道
if(src_bin_light.empty()) return false;
imagePreProcess(src_bin_light); // 开闭运算
cv::threshold(color_channel, src_bin_dim, 160, 255, CV_THRESH_BINARY); // 二值化对应通道
if(src_bin_dim.empty()) return false;
imagePreProcess(src_bin_dim); // 开闭运算
if(src_bin_light.size() == cv::Size(640, 480) && show_light_blobs) {
@@ -154,4 +156,4 @@ bool ArmorFinder::findLightBlobs(const cv::Mat &src, LightBlobs &light_blobs) {
}
}
return light_blobs.size() >= 2;
}
}

View File

@@ -1,133 +0,0 @@
//
// Created by xinyang on 19-7-10.
//
#include <armor_finder/armor_finder.h>
static double lw_rate(const cv::RotatedRect &rect) {
return rect.size.height > rect.size.width ?
rect.size.height / rect.size.width :
rect.size.width / rect.size.height;
}
bool rectangleContainPoint(cv::RotatedRect rectangle, cv::Point2f point) {
//转化为轮廓
cv::Point2f corners[4];
rectangle.points(corners);
cv::Point2f *lastItemPointer = (corners + sizeof corners / sizeof corners[0]);
vector<cv::Point2f> contour(corners, lastItemPointer);
//判断
double indicator = pointPolygonTest(contour, point, true);
return indicator >= 0;
}
// 下面的函数可以有性能优化,暂时未做。
static double nonZeroRateOfRotateRect(const cv::Mat &bin, const cv::RotatedRect &rotrect) {
auto rect = rotrect.boundingRect();
if (rect.x < 0 || rect.y < 0 || rect.x + rect.width > bin.cols || rect.y + rect.height > bin.rows) {
return 0;
}
auto roi = bin(rect);
int cnt = 0;
for (int r = 0; r < roi.rows; r++) {
for (int c = 0; c < roi.cols; c++) {
if (rectangleContainPoint(rotrect, cv::Point(c + rect.x, r + rect.y))) {
if (roi.at<uint8_t>(r, c)) {
cnt++;
}
}
}
}
return double(cnt) / rotrect.size.area();
}
int linePointX(const cv::Point2f &p1, const cv::Point2f &p2, int y) {
return (p2.x - p1.x) / (p2.y - p1.y) * (y - p1.y) + p1.x;
}
// 性能优化后的函数
static double nonZeroRateOfRotateRect_opt(const cv::Mat &bin, const cv::RotatedRect &rotrect) {
int cnt = 0;
cv::Point2f corners[4];
rotrect.points(corners);
sort(corners, &corners[4], [](cv::Point2f p1, cv::Point2f p2) {
return p1.y < p2.y;
});
for (int r = corners[0].y; r < corners[1].y; r++) {
auto start = min(linePointX(corners[0], corners[1], r), linePointX(corners[0], corners[2], r)) - 1;
auto end = max(linePointX(corners[0], corners[1], r), linePointX(corners[0], corners[2], r)) + 1;
if (start < 0 || end > 640) return 0;
for (int c = start; c < end; c++) {
if (bin.at<uint8_t>(r, c)) {
cnt++;
}
}
}
for (int r = corners[1].y; r < corners[2].y; r++) {
auto start = min(linePointX(corners[0], corners[2], r), linePointX(corners[1], corners[3], r)) - 1;
auto end = max(linePointX(corners[0], corners[2], r), linePointX(corners[1], corners[3], r)) + 1;
if (start < 0 || end > 640) return 0;
for (int c = start; c < end; c++) {
if (bin.at<uint8_t>(r, c)) {
cnt++;
}
}
}
for (int r = corners[2].y; r < corners[3].y; r++) {
auto start = min(linePointX(corners[1], corners[3], r), linePointX(corners[2], corners[3], r)) - 1;
auto end = max(linePointX(corners[1], corners[3], r), linePointX(corners[2], corners[3], r)) + 1;
if (start < 0 || end > 640) return 0;
for (int c = start; c < end; c++) {
if (bin.at<uint8_t>(r, c)) {
cnt++;
}
}
}
return double(cnt) / rotrect.size.area();
}
static bool isValidLightBlob(const cv::Mat &bin, const cv::RotatedRect &rect) {
return (lw_rate(rect) > 1.5) &&
// (rect.size.width*rect.size.height < 3000) &&
(rect.size.width * rect.size.height > 1) &&
(nonZeroRateOfRotateRect_opt(bin, rect) > 0.8);
// (nonZeroRateOfRotateRect(bin, rect) > 0.8);
}
void get_blob_color(const cv::Mat &src, std::vector<LightBlob> &blobs) {
for (auto &blob : blobs) {
auto region = blob.rect.boundingRect();
region.x -= fmax(2, region.width * 0.1);
region.y -= fmax(2, region.height * 0.05);
region.width += 2 * fmax(2, region.width * 0.1);
region.height += 2 * fmax(2, region.height * 0.05);
region &= cv::Rect(0, 0, 640, 480);
cv::Mat roi = src(region);
long long int red_cnt = 0, blue_cnt = 0;
for (int row = 0; row < roi.rows; row++) {
for (int col = 0; col < roi.cols; col++) {
red_cnt += roi.at<cv::Vec3b>(row, col)[2];
blue_cnt += roi.at<cv::Vec3b>(row, col)[0];
}
}
if (red_cnt > blue_cnt) {
blob.BlobColor = BLOB_RED;
} else {
blob.BlobColor = BLOB_BLUE;
}
}
}
bool ArmorFinder::findLightBlobs(const cv::Mat &src_bin, LightBlobs &light_blobs) {
std::vector<std::vector<cv::Point> > light_contours;
cv::findContours(src_bin, light_contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
for (auto &light_contour : light_contours) {
cv::RotatedRect rect = cv::minAreaRect(light_contour);
if (isValidLightBlob(src_bin, rect)) {
light_blobs.emplace_back(rect);
}
}
get_blob_color(src_raw, light_blobs);
return light_blobs.size() >= 2;
}

View File

@@ -3,118 +3,15 @@
//
#include <armor_finder/armor_finder.h>
#include <opencv2/highgui.hpp>
#include <show_images/show_images.h>
#include <options/options.h>
#include <log.h>
static string prior_blue[] = {
"B8", "B1", "B3", "B4", "B5", "B7", "B2",
"R8", "R1", "R3", "R4", "R5", "R7", "R2",
};
static string prior_red[] = {
"R8", "R1", "R3", "R4", "R5", "R7", "R2",
"B8", "B1", "B3", "B4", "B5", "B7", "B2",
};
void imagePreProcess(cv::Mat &src) {
static cv::Mat kernel_erode = getStructuringElement(cv::MORPH_RECT, cv::Size(3, 5));
erode(src, src, kernel_erode);
static cv::Mat kernel_dilate = getStructuringElement(cv::MORPH_RECT, cv::Size(3, 5));
dilate(src, src, kernel_dilate);
static cv::Mat kernel_dilate2 = getStructuringElement(cv::MORPH_RECT, cv::Size(3, 5));
dilate(src, src, kernel_dilate2);
static cv::Mat kernel_erode2 = getStructuringElement(cv::MORPH_RECT, cv::Size(3, 5));
erode(src, src, kernel_erode2);
float alpha = 1.5;
int beta = 0;
src.convertTo(src, -1, alpha, beta);
}
bool ArmorFinder::stateSearchingTarget(cv::Mat &src) {
std::vector<cv::Mat> channels; // 通道拆分
cv::Mat src_bin, color; // 二值图和颜色通道图
LightBlobs light_blobs; // 存储所有可能的灯条
std::vector<cv::Rect2d> armor_boxes; // 装甲板候选区
std::vector<cv::Rect2d> boxes_number[15]; // 装甲板候选区放置在对应id位置
armor_box = cv::Rect2d(0, 0, 0, 0); // 重置目标装甲板位置
boxid = -1; // 重置目标装甲板id
cv::split(src, channels); /************************/
if (enemy_color == ENEMY_BLUE) /* */
color = channels[0]; /* 根据目标颜色进行通道提取 */
else if (enemy_color == ENEMY_RED) /* */
color = channels[2]; /************************/
cv::threshold(color, src_bin, 170, 255, CV_THRESH_BINARY); // 二值化对应通道
imagePreProcess(src_bin); // 开闭运算
if (!findLightBlobs(src_bin, light_blobs)) {
if(findArmorBox(src, armor_box)){
return true;
}else{
armor_box = ArmorBox();
return false;
}
if (show_light_blobs) {
showContours("light_blobs", src, light_blobs);
cv::waitKey(1);
}
if (!findArmorBoxes(light_blobs, armor_boxes)) {
return false;
}
if (show_armor_boxes) {
showArmorBoxVector("boxes", src, armor_boxes);
cv::waitKey(1);
}
if (classifier && use_classifier) {
for (auto box : armor_boxes) {
cv::Mat roi = src(box).clone();
cv::resize(roi, roi, cv::Size(48, 36));
int c = classifier(roi);
boxes_number[c].emplace_back(box);
}
if (enemy_color == ENEMY_BLUE) {
for (auto name : prior_blue) {
if (!boxes_number[name2id[name]].empty()) {
armor_box = boxes_number[name2id[name]][0];
boxid = name2id[name];
break;
}
}
} else if (enemy_color == ENEMY_RED) {
for (auto name : prior_red) {
if (!boxes_number[name2id[name]].empty()) {
armor_box = boxes_number[name2id[name]][0];
boxid = name2id[name];
break;
}
}
} else {
LOGE_INFO("enemy_color ERROR!");
}
if (armor_box == cv::Rect2d(0, 0, 0, 0)) {
return false;
}
if (show_armor_boxes) {
showArmorBoxClass("class", src, boxes_number);
}
if (save_labelled_boxes) {
for (int i = 0; i < sizeof(boxes_number) / sizeof(boxes_number[0]); i++) {
for (auto &box : boxes_number[i]) {
char filename[100];
sprintf(filename, PROJECT_DIR"/armor_box_photo/%s_%d.jpg", id2name[i].data(),
time(nullptr) + clock());
cv::imwrite(filename, src(box));
}
}
}
} else {
armor_box = armor_boxes[0];
boxid = -1;
}
return sendBoxPosition();
}

View File

@@ -3,13 +3,16 @@
//
#include <armor_finder/armor_finder.h>
#include <config/setconfig.h>
#include <log.h>
static bool sendTarget(Serial &serial, double x, double y, double z) {
static bool sendTarget(Serial &serial, double x, double y, double z, uint16_t shoot_delay) {
static short x_tmp, y_tmp, z_tmp;
uint8_t buff[10];
#ifdef WITH_COUNT_FPS
static time_t last_time = time(nullptr);
static int fps;
uint8_t buff[8];
time_t t = time(nullptr);
if (last_time != t) {
last_time = t;
@@ -17,6 +20,7 @@ static bool sendTarget(Serial &serial, double x, double y, double z) {
fps = 0;
}
fps += 1;
#endif
x_tmp = static_cast<short>(x * (32768 - 1) / 100);
y_tmp = static_cast<short>(y * (32768 - 1) / 100);
@@ -29,18 +33,25 @@ static bool sendTarget(Serial &serial, double x, double y, double z) {
buff[4] = static_cast<char>((y_tmp >> 0) & 0xFF);
buff[5] = static_cast<char>((z_tmp >> 8) & 0xFF);
buff[6] = static_cast<char>((z_tmp >> 0) & 0xFF);
buff[7] = 'e';
buff[7] = static_cast<char>((shoot_delay >> 8) & 0xFF);
buff[8] = static_cast<char>((shoot_delay >> 0) & 0xFF);
buff[9] = 'e';
// if(buff[7]<<8 | buff[8])
// cout << (buff[7]<<8 | buff[8]) << endl;
return serial.WriteData(buff, sizeof(buff));
}
bool ArmorFinder::sendBoxPosition() {
auto rect = armor_box;
double dx = rect.x + rect.width / 2 - 320;
double dy = rect.y + rect.height / 2 - 240 - 20;
bool ArmorFinder::sendBoxPosition(uint16_t shoot_delay) {
if (armor_box.rect == cv::Rect2d()) return false;
if (shoot_delay) {
LOGM(STR_CTR(WORD_BLUE, "shoot after %dms"), shoot_delay);
}
auto rect = armor_box.rect;
double dx = rect.x + rect.width / 2 - IMAGE_CENTER_X;
double dy = rect.y + rect.height / 2 - IMAGE_CENTER_Y;
double yaw = atan(dx / FOCUS_PIXAL) * 180 / PI;
double pitch = atan(dy / FOCUS_PIXAL) * 180 / PI;
double dist = DISTANCE_HEIGHT / rect.height;
// cout << yaw << endl;
return sendTarget(serial, yaw, -pitch, dist);
return sendTarget(serial, yaw, -pitch, dist, shoot_delay);
}

View File

@@ -2,30 +2,76 @@
// Created by xinyang on 19-3-27.
//
#include <log.h>
#include <options/options.h>
#include <armor_finder/armor_finder.h>
#include <show_images/show_images.h>
bool ArmorFinder::stateTrackingTarget(cv::Mat &src) {
if(!tracker->update(src, armor_box)){
auto pos = armor_box.rect;
if(!tracker->update(src, pos)){
armor_box = ArmorBox();
return false;
}
if((armor_box & cv::Rect2d(0, 0, 640, 480)) != armor_box){
if((pos & cv::Rect2d(0, 0, 640, 480)) != pos){
armor_box = ArmorBox();
return false;
}
cv::Mat roi = src.clone()(armor_box);
if(classifier){
cv::resize(roi, roi, cv::Size(48, 36));
if(classifier(roi) == 0){
return false;
cv::Rect2d bigger_rect;
bigger_rect.x = pos.x - pos.width / 2.0;
bigger_rect.y = pos.y - pos.height / 2.0;
bigger_rect.height = pos.height * 2;
bigger_rect.width = pos.width * 2;
bigger_rect &= cv::Rect2d(0, 0, 640, 480);
if(show_armor_box)
showTrackSearchingPos("track", src, bigger_rect);
cv::Mat roi = src(bigger_rect).clone();
ArmorBox box;
if(findArmorBox(roi, box)) {
armor_box = box;
armor_box.rect.x += bigger_rect.x;
armor_box.rect.y += bigger_rect.y;
for(auto &blob : armor_box.light_blobs){
blob.rect.center.x += bigger_rect.x;
blob.rect.center.y += bigger_rect.y;
}
}else{
cv::Mat roi_gray;
cv::cvtColor(roi, roi_gray, CV_RGB2GRAY);
cv::threshold(roi_gray, roi_gray, 180, 255, cv::THRESH_BINARY);
contour_area = cv::countNonZero(roi_gray);
if(abs(cv::countNonZero(roi_gray) - contour_area) > contour_area * 0.3){
return false;
roi = src(pos).clone();
if(classifier){
cv::resize(roi, roi, cv::Size(48, 36));
if(classifier(roi) == 0){
armor_box = ArmorBox();
return false;
}
}else{
cv::Mat roi_gray;
cv::cvtColor(roi, roi_gray, CV_RGB2GRAY);
cv::threshold(roi_gray, roi_gray, 180, 255, cv::THRESH_BINARY);
contour_area = cv::countNonZero(roi_gray);
if(abs(cv::countNonZero(roi_gray) - contour_area) > contour_area * 0.3){
armor_box = ArmorBox();
return false;
}
}
armor_box.rect = pos;
armor_box.light_blobs.clear();
}
return sendBoxPosition();
// armor_box.x -= armor_box.width / 4.0;
// armor_box.y -= armor_box.height / 4.0;
// armor_box.height *= 1.5;
// armor_box.width *= 1.5;
// roi = src(armor_box);
// if(findSearchingTarget(roi)){
//
// }
// sendBoxPosition();
return true;
}

View File

@@ -1,13 +1,30 @@
#include <show_images/show_images.h>
#include <opencv2/highgui.hpp>
#include <options/options.h>
#include <log.h>
using namespace cv;
void drawLightBlobs(cv::Mat &src, const LightBlobs &blobs){
for (const auto &blob:blobs) {
Scalar color(0,255,0);
if (blob.blob_color == BLOB_RED)
color = Scalar(0, 0, 255);
else if (blob.blob_color == BLOB_BLUE)
color = Scalar(255, 0, 0);
cv::Point2f vertices[4];
blob.rect.points(vertices);
for (int j = 0; j < 4; j++) {
cv::line(src, vertices[j], vertices[(j + 1) % 4], color, 2);
}
}
}
/**************************
* 显示多个装甲板区域 *
**************************/
void showArmorBoxVector(std::string windows_name, const cv::Mat &src, const std::vector<cv::Rect2d> &armor_box) {
void showArmorBoxes(std::string windows_name, const cv::Mat &src, const ArmorBoxes &armor_boxes) {
static Mat image2show;
if (src.type() == CV_8UC1) {// 黑白图像
cvtColor(src, image2show, COLOR_GRAY2RGB);
@@ -15,8 +32,15 @@ void showArmorBoxVector(std::string windows_name, const cv::Mat &src, const std:
image2show = src.clone();
}
for (auto &box:armor_box) {
rectangle(image2show, box, Scalar(0, 255, 0), 1);
for (auto &box:armor_boxes) {
if(box.box_color == BOX_BLUE) {
rectangle(image2show, box.rect, Scalar(0, 255, 0), 1);
drawLightBlobs(image2show, box.light_blobs);
}else if(box.box_color == BOX_RED){
rectangle(image2show, box.rect, Scalar(0, 255, 0), 1);
drawLightBlobs(image2show, box.light_blobs);
}
}
imshow(windows_name, image2show);
}
@@ -24,65 +48,79 @@ void showArmorBoxVector(std::string windows_name, const cv::Mat &src, const std:
/**************************
* 显示多个装甲板区域及其类别 *
**************************/
void showArmorBoxClass(std::string window_names, const cv::Mat &src, vector<cv::Rect2d> boxes[10]) {
void showArmorBoxesClass(std::string window_names, const cv::Mat &src, const ArmorBoxes &boxes) {
static Mat image2show;
if (src.type() == CV_8UC1) { // 黑白图像
cvtColor(src, image2show, COLOR_GRAY2RGB);
} else if (src.type() == CV_8UC3) { //RGB 彩色
image2show = src.clone();
}
for (int i = 0; i < 14; i++) {
if (!boxes[i].empty()) {
for (auto box : boxes[i]) {
rectangle(image2show, box, Scalar(0, 255, 0), 1);
if (i == -1)
putText(image2show, id2name[i], Point(box.x + 2, box.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
Scalar(0, 255, 0));
else if (1 <= i && i < 8)
putText(image2show, id2name[i], Point(box.x + 2, box.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
Scalar(255, 0, 0));
else if (8 <= i && i < 15)
putText(image2show, id2name[i], Point(box.x + 2, box.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
Scalar(0, 0, 255));
else if (i != 0)
LOGE_INFO("Invalid box id:%d!", i);
}
for (const auto &box : boxes) {
if(box.id != 0) {
rectangle(image2show, box.rect, Scalar(0, 255, 0), 1);
drawLightBlobs(image2show, box.light_blobs);
if (box.id == -1)
putText(image2show, id2name[box.id], Point(box.rect.x + 2, box.rect.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
Scalar(0, 255, 0));
else if (1 <= box.id && box.id < 8)
putText(image2show, id2name[box.id], Point(box.rect.x + 2, box.rect.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
Scalar(255, 0, 0));
else if (8 <= box.id && box.id < 15)
putText(image2show, id2name[box.id], Point(box.rect.x + 2, box.rect.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
Scalar(0, 0, 255));
else if (box.id != 0)
LOGE_INFO("Invalid box id:%d!", box.id);
}
}
imshow(window_names, image2show);
}
/**************************
* 显示单个装甲板区域及其类别 *
**************************/
void showArmorBox(std::string windows_name, const cv::Mat &src, cv::Rect2d armor_box, int boxid) {
void showArmorBox(std::string windows_name, const cv::Mat &src, const ArmorBox &box) {
static Mat image2show;
if(box.rect == cv::Rect2d()){
imshow(windows_name, src);
}
if (src.type() == CV_8UC1) { // 黑白图像
cvtColor(src, image2show, COLOR_GRAY2RGB);
} else if (src.type() == CV_8UC3) { //RGB 彩色
image2show = src.clone();
}
rectangle(image2show, armor_box, Scalar(0, 255, 0), 1);
drawLightBlobs(image2show, box.light_blobs);
// static FILE *fp = fopen(PROJECT_DIR"/ratio.txt", "w");
// if(box.light_blobs.size() == 2)
// fprintf(fp, "%lf %lf %lf\n", box.light_blobs[0].length, box.light_blobs[1].length, box.getBlobsDistance())
// cout << box.lengthDistanceRatio() << endl;
if(box.getOrientation() == ArmorBox::FRONT){
rectangle(image2show, box.rect, Scalar(0, 255, 0), 3);
}else{
rectangle(image2show, box.rect, Scalar(0, 255, 0), 1);
};
char dist[5];
// sprintf(dist, "%.1f", distance);
if (boxid == -1)
putText(image2show, id2name[boxid]+" "+dist, Point(armor_box.x + 2, armor_box.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
sprintf(dist, "%.1f", box.getBoxDistance());
if (box.id == -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));
else if (1 <= boxid && boxid < 8)
putText(image2show, id2name[boxid]+" "+dist, Point(armor_box.x + 2, armor_box.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
else if (1 <= box.id && box.id < 8)
putText(image2show, id2name[box.id]+" "+dist, Point(box.rect.x + 2, box.rect.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
Scalar(255, 0, 0));
else if (8 <= boxid && boxid < 15)
putText(image2show, id2name[boxid]+" "+dist, Point(armor_box.x + 2, armor_box.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
else if (8 <= box.id && box.id < 15)
putText(image2show, id2name[box.id]+" "+dist, Point(box.rect.x + 2, box.rect.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
Scalar(0, 0, 255));
else if (boxid != 0)
LOGE_INFO("Invalid box id:%d!", boxid);
else if (box.id != 0)
LOGE_INFO("Invalid box id:%d!", box.id);
imshow(windows_name, image2show);
}
/**************************
* 显示多个灯条区域 *
**************************/
void showContours(std::string windows_name, const cv::Mat &src, const std::vector<LightBlob> &light_blobs) {
void showLightBlobs(std::string windows_name, const cv::Mat &src, const LightBlobs &light_blobs) {
static Mat image2show;
if (src.type() == CV_8UC1) { // 黑白图像
@@ -92,13 +130,11 @@ void showContours(std::string windows_name, const cv::Mat &src, const std::vecto
}
for (const auto &light_blob:light_blobs) {
Scalar color;
if (light_blob.BlobColor == BLOB_RED)
Scalar color(0, 255, 0);
if (light_blob.blob_color == BLOB_RED)
color = Scalar(0, 0, 255);
else if (light_blob.BlobColor == BLOB_BLUE)
else if (light_blob.blob_color == BLOB_BLUE)
color = Scalar(255, 0, 0);
else
color = Scalar(0, 255, 0);
cv::Point2f vertices[4];
light_blob.rect.points(vertices);
for (int j = 0; j < 4; j++) {
@@ -107,3 +143,15 @@ void showContours(std::string windows_name, const cv::Mat &src, const std::vecto
}
imshow(windows_name, image2show);
}
void showTrackSearchingPos(std::string window_names, const cv::Mat &src, const cv::Rect2d pos){
static Mat image2show;
if (src.type() == CV_8UC1) { // 黑白图像
cvtColor(src, image2show, COLOR_GRAY2RGB);
} else if (src.type() == CV_8UC3) { //RGB 彩色
image2show = src.clone();
}
rectangle(image2show, pos, Scalar(0, 255, 0), 1);
imshow(window_names, image2show);
}

View File

@@ -11,7 +11,8 @@ const int SRC_WIDTH = 320;
const int SRC_HEIGHT = 240;
const int CLOCKWISE = 1;
const int ANTICLOCKWISE = -1;
const float ATTACK_DISTANCE = 718.0;//cm
//const float ATTACK_DISTANCE = 718.0;//cm
const float ATTACK_DISTANCE = 750.0;//cm
const double ARMOR_CENTER_TO_CYCLE_CENTER = 75.0;//cm

View File

@@ -27,12 +27,16 @@ public:
Energy(Serial &u, uint8_t &color);//构造函数,参数为串口和敌方颜色
~Energy();//默认析构函数
void run(cv::Mat &gimbal_src, cv::Mat &chassis_src);
void run(cv::Mat &gimbal_src);
void runBig(cv::Mat &gimbal_src, cv::Mat &chassis_src);
void runBig(cv::Mat &gimbal_src);
void runSmall(cv::Mat &gimbal_src);
Serial &serial;//串口
void setEnergyInit();//设置能量机关初始化
void sendTarget(Serial &serial, float x, float y, float z);
void setBigEnergyInit();//设置大能量机关初始化
void setSmallEnergyInit();//设置小能量机关初始化
void sendTarget(Serial& serial, float x, float y, float z);//发送数据
void sendTarget(Serial& serial, float x, float y, float z, uint16_t u);//发送数据
private:
@@ -51,7 +55,6 @@ private:
bool energy_rotation_init;//若仍在判断风车旋转方向则为true
bool manual_mark;//若操作手进行过手动标定则为true
bool auto_mark;//云台完成自动对心则置为true
bool shoot;//若为true则要求主控板发弹
bool start_guess;//进入猜测状态的标志
bool change_target;//目标切换的标志
@@ -77,6 +80,8 @@ private:
float center_delta_yaw, center_delta_pitch;//对心时相差的角度
float yaw_rotation, pitch_rotation;//云台yaw轴和pitch轴应该转到的角度
float origin_yaw, origin_pitch;//初始的云台角度设定值
float shoot;//若为2则要求主控板发弹
float sum_yaw, sum_pitch;//yaw和pitch的累计误差即PID中积分项
timeval time_start_guess;
@@ -158,8 +163,9 @@ private:
void getAllTargetArmorCenters();//记录所有目标装甲板中心坐标
void getRecentTargetArmorCenters();//记录近30帧目标装甲板中心坐标
void judgeShoot();//判断是否可以发弹
void JudgeMode();//判断大符还是小符
void judgeMode();//判断大符还是小符
void judgeShootInGimbal();//在云台坐标系中判断是否可以发弹
void judgeShootInWorld();//在世界坐标系中判断是否可以发弹
bool isGuessingTimeout();//判断猜测模式是否超时(没打中)
void splitBayerBG(cv::Mat src, cv::Mat &blue, cv::Mat &red);//拜耳阵列分离

View File

@@ -61,3 +61,4 @@ void Energy::circleLeastFit()
// cout << "The cycle center is: " << cycle_center << endl;
// cout << "The radius is: " << radius << endl;
}

View File

@@ -125,7 +125,7 @@ void Energy::FlowStripStruct(cv::Mat &src) {
// 此函数对图像进行腐蚀与膨胀操作
// ---------------------------------------------------------------------------------------------------------------------
void Energy::CenterRStruct(cv::Mat &src) {
Mat element_dilate_1 = getStructuringElement(MORPH_RECT, Size(8, 6));
Mat element_dilate_1 = getStructuringElement(MORPH_RECT, Size(4, 4));
Mat element_erode_1 = getStructuringElement(MORPH_RECT, Size(2, 1));
Mat element_dilate_2 = getStructuringElement(MORPH_RECT, Size(3, 3));
Mat element_erode_2 = getStructuringElement(MORPH_RECT, Size(4 , 4));
@@ -134,8 +134,8 @@ void Energy::CenterRStruct(cv::Mat &src) {
// imshow("erode_1", src);
dilate(src, src, element_dilate_1);
// imshow("dilate_1", src);
dilate(src, src, element_dilate_2);
// dilate(src, src, element_dilate_2);
// imshow("dilate_2", src);
erode(src,src, element_erode_2);
// erode(src,src, element_erode_2);
// imshow("erode_2", src);
}

View File

@@ -18,7 +18,6 @@ void Energy::clearAll(){
}
//----------------------------------------------------------------------------------------------------------------------
// 此函数用于图像预处理
// ---------------------------------------------------------------------------------------------------------------------

View File

@@ -21,7 +21,6 @@ void Energy::initEnergy() {
energy_rotation_init = true;
manual_mark = false;
auto_mark = false;
shoot = false;
start_guess = false;
change_target = false;
@@ -41,14 +40,15 @@ void Energy::initEnergy() {
last_target_polar_angle = -1000;
guess_polar_angle = -1000;
last_base_angle = -1000;
predict_rad = 20;
predict_rad = 25;
attack_distance = ATTACK_DISTANCE;
center_delta_yaw = 1000;
center_delta_pitch = 1000;
yaw_rotation = 0;
pitch_rotation = 0;
origin_yaw = 0;
origin_pitch = 0;
shoot = 0;
sum_yaw = 0;
sum_pitch = 0;
circle_center_point = Point(0, 0);
target_point = Point(0, 0);
@@ -69,7 +69,7 @@ void Energy::initEnergy() {
// 此函数对能量机关参数进行初始化
// ---------------------------------------------------------------------------------------------------------------------
void Energy::initEnergyPartParam() {
gimbal_energy_part_param_.GRAY_THRESH = 120;//home
gimbal_energy_part_param_.GRAY_THRESH = 140;//home
// gimbal_energy_part_param_.GRAY_THRESH = 200;//official
// gimbal_energy_part_param_.GRAY_THRESH = 225;
gimbal_energy_part_param_.SPLIT_GRAY_THRESH = 230;
@@ -81,7 +81,7 @@ void Energy::initEnergyPartParam() {
gimbal_energy_part_param_.FAN_CONTOUR_LENGTH_MIN = 80;
gimbal_energy_part_param_.FAN_CONTOUR_LENGTH_MAX = 100;
gimbal_energy_part_param_.FAN_CONTOUR_WIDTH_MIN = 20;
gimbal_energy_part_param_.FAN_CONTOUR_WIDTH_MAX = 50;
gimbal_energy_part_param_.FAN_CONTOUR_WIDTH_MAX = 52;
gimbal_energy_part_param_.FAN_CONTOUR_HW_RATIO_MAX = 4;
gimbal_energy_part_param_.FAN_CONTOUR_HW_RATIO_MIN = 1;
gimbal_energy_part_param_.FAN_CONTOUR_AREA_RATIO_MIN = 0.65;
@@ -107,42 +107,42 @@ void Energy::initEnergyPartParam() {
gimbal_energy_part_param_.CENTER_R_CONTOUR_WIDTH_MAX = 25;
gimbal_energy_part_param_.CENTER_R_CONTOUR_HW_RATIO_MAX = 3;
gimbal_energy_part_param_.CENTER_R_CONTOUR_HW_RATIO_MIN = 1;
gimbal_energy_part_param_.CENTER_R_CONTOUR_AREA_RATIO_MIN = 0.7;
gimbal_energy_part_param_.CENTER_R_CONTOUR_AREA_RATIO_MIN = 0.5;
gimbal_energy_part_param_.CENTER_R_CONTOUR_INTERSETION_AREA_MIN = 10;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_MAX = 17000;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_MIN = 0;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_MAX = 3000;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_MIN = 1000;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_LENGTH_MIN = 60;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_LENGTH_MAX = 100;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MIN = 20;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MAX = 50;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MAX = 52;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MAX = 3;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MIN = 1;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_RATIO_MAX = 0.58;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_RATIO_MAX = 0.65;
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_RATIO_MIN = 0.34;
gimbal_energy_part_param_.FLOW_STRIP_FAN_NON_ZERO_RATE_MAX = 0.58;
gimbal_energy_part_param_.FLOW_STRIP_FAN_NON_ZERO_RATE_MAX = 0.65;
gimbal_energy_part_param_.FLOW_STRIP_FAN_NON_ZERO_RATE_MIN = 0.34;
// gimbal_energy_part_param_.FLOW_STRIP_FAN_NON_ZERO_RATE_MAX = 0.2;
// gimbal_energy_part_param_.FLOW_STRIP_FAN_NON_ZERO_RATE_MIN = 0.08;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_AREA_MAX = 100000;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_AREA_MIN = 0;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MIN = 40;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MAX = 65;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MIN = 38;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MAX = 60;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MIN = 8;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MAX = 20;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MAX = 32;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MAX = 12;
// gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MIN = 4;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MIN = 3;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MIN = 1.8;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_AREA_RATIO_MIN = 0.5;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_INTERSETION_AREA_MIN = 117;
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_INTERSETION_AREA_MIN = 100;
gimbal_energy_part_param_.TWIN_ANGEL_MAX = 10;
gimbal_energy_part_param_.TARGET_INTERSETION_CONTOUR_AREA_MIN = 40;
chassis_energy_part_param_.GRAY_THRESH = 120;//home_small
chassis_energy_part_param_.GRAY_THRESH = 230;//home_big
chassis_energy_part_param_.GRAY_THRESH = 120;//home
// chassis_energy_part_param_.GRAY_THRESH = 200;//official
// chassis_energy_part_param_.GRAY_THRESH = 225;
chassis_energy_part_param_.SPLIT_GRAY_THRESH = 230;
@@ -189,7 +189,7 @@ void Energy::initEnergyPartParam() {
chassis_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_LENGTH_MIN = 90;
chassis_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_LENGTH_MAX = 140;
chassis_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MIN = 35;
chassis_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MAX = 60;
chassis_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MAX = 65;
chassis_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MAX = 3;
chassis_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MIN = 1;
chassis_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_RATIO_MAX = 0.55;
@@ -231,11 +231,11 @@ void Energy::initRotation() {
else if (target_polar_angle > last_target_polar_angle) anticlockwise_rotation_init_cnt++;
}
//由于刚开始圆心判断不准,角度变化可能计算有误,因此需要在角度正向或逆向变化足够大时才可确定是否为顺逆时针
if (clockwise_rotation_init_cnt == 30) {
if (clockwise_rotation_init_cnt == 15) {
energy_rotation_direction = CLOCKWISE;//顺时针变化30次确定为顺时针
cout << "rotation: " << energy_rotation_direction << endl;
energy_rotation_init = false;
} else if (anticlockwise_rotation_init_cnt == 30) {
} else if (anticlockwise_rotation_init_cnt == 15) {
energy_rotation_direction = ANTICLOCKWISE;//逆时针变化30次确定为顺时针
cout << "rotation: " << energy_rotation_direction << endl;
energy_rotation_init = false;

View File

@@ -44,4 +44,33 @@ void Energy::setEnergyInit() {
is_small = false;
is_gimbal = true;
is_chassis = false;
}
//----------------------------------------------------------------------------------------------------------------------
// 此函数为大能量机关再初始化函数
// ---------------------------------------------------------------------------------------------------------------------
void Energy::setBigEnergyInit() {
initEnergy();
initEnergyPartParam();
is_big = true;
is_small = false;
is_gimbal = true;
is_chassis = false;
}
//----------------------------------------------------------------------------------------------------------------------
// 此函数为大能量机关再初始化函数
// ---------------------------------------------------------------------------------------------------------------------
void Energy::setSmallEnergyInit() {
initEnergy();
initEnergyPartParam();
is_big = false;
is_small = true;
is_gimbal = true;
is_chassis = false;
}

View File

@@ -69,6 +69,7 @@ int Energy::findArmors(const cv::Mat src) {
ArmorStruct(src_bin);//图像膨胀,防止图像断开并更方便寻找
findContours(src_bin, armor_contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
imshow("armor struct", src_bin);
// findContours(src_bin, armor_contours_external, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
// for (int i = 0; i < armor_contours_external.size(); i++)//去除外轮廓
@@ -132,7 +133,7 @@ bool Energy::findCenterR(const cv::Mat src) {
circle_center_point = centerR.center;
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;
// 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;
@@ -147,10 +148,11 @@ bool Energy::findCenterR(const cv::Mat src) {
// cout << "R intersection: " << contourArea(intersection) << endl;
// return true;
// }
// cout << cur_rect.center << endl;
return true;
}
cout << "find center R false!" << endl;
// cv::waitKey(0);
return false;
}
@@ -159,7 +161,7 @@ bool Energy::findCenterR(const cv::Mat src) {
//----------------------------------------------------------------------------------------------------------------------
// 此函数用于判断找到的矩形候选区是否为含流动条的扇叶
// ---------------------------------------------------------------------------------------------------------------------
bool Energy:: findFlowStripFan(const cv::Mat src) {
bool Energy::findFlowStripFan(const cv::Mat src) {
if (src.empty())return false;
static Mat src_bin;
static Mat src_copy;
@@ -170,7 +172,7 @@ bool Energy:: findFlowStripFan(const cv::Mat src) {
}
std::vector<vector<Point> > flow_strip_fan_contours;
FlowStripFanStruct(src_bin);//图像膨胀,防止图像断开并更方便寻找
// imshow("flow strip fan struct", src_bin);
imshow("flow strip fan struct", src_bin);
findContours(src_bin, flow_strip_fan_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
@@ -193,11 +195,12 @@ bool Energy:: findFlowStripFan(const cv::Mat src) {
// cout << "non zero: " << non_zero_rate << endl;
// cout<<cur_contour_area / cur_size.area()<<endl;
// }
// cout << cur_rect.center << endl;
return true;
}
// showFlowStripFan("strip fan", src_bin);
cout << "flow strip fan false!" << endl;
// waitKey(0);
return false;
}
@@ -227,15 +230,16 @@ bool Energy::findFlowStrip(const cv::Mat src) {
// Size2f cur_size = cur_rect.size;
// float length = cur_size.height > cur_size.width ? cur_size.height : cur_size.width;
// float width = cur_size.height < cur_size.width ? cur_size.height : cur_size.width;
// if (length / width > 4 && width > 7 && width<30) {
// if (length / width > 2.5 && width > 7 && width<40) {
// cout << cur_rect.center << endl;
// flow_strip = cv::minAreaRect(flow_strip_contour);
// cout << "flow strip area: " << length << '\t' << width << endl;
// }
// cout << cur_rect.center << endl;
return true;
}
// waitKey();
cout << "flow strip false!" << endl;
// waitKey(0);
return false;
}
@@ -252,7 +256,7 @@ bool Energy::findCenterROI(const cv::Mat src) {
vector<Point2f> mask_rect;
target_armor.points(vertices); //计算矩形的4个顶点
for (int i = 0; i < 4; i++)
line(src_mask, vertices[i], vertices[(i + 1) % 4], Scalar(0, 0, 0), 15);
line(src_mask, vertices[i], vertices[(i + 1) % 4], Scalar(0, 0, 0), 20);
// imshow("fill", src_mask);
if (!findFlowStrip(src_mask))return false;
float length = target_armor.size.height > target_armor.size.width ?

View File

@@ -4,6 +4,7 @@
#include "energy/energy.h"
#include "energy/constant.h"
#include "config/setconfig.h"
using namespace std;
using namespace cv;
@@ -12,8 +13,13 @@ using namespace cv;
// 此函数通过自瞄逻辑击打目标点,用于大符的自动对心和小符直接打击
// ---------------------------------------------------------------------------------------------------------------------
void Energy::getAimPoint(cv::Point target_point) {
double dx = -(target_point.x - 320 - 10);
double dy = -(target_point.y - 240 - 22);
//五号车
// double dx = -(target_point.x - 320 - 10);
// double dy = -(target_point.y - 240 - 22);
//四号车
double dx = -(target_point.x - 320 - COMPENSATE_YAW);
double dy = -(target_point.y - 240 - COMPENSATE_PITCH);
yaw_rotation = atan(dx / FOCUS_PIXAL) * 180 / PI;
pitch_rotation = atan(dy / FOCUS_PIXAL) * 180 / PI;
// cout << "yaw: " << yaw_rotation << '\t' << "pitch: " << pitch_rotation << endl;
}

View File

@@ -13,18 +13,24 @@ using namespace cv;
// ---------------------------------------------------------------------------------------------------------------------
bool Energy::getOrigin() {
if (!auto_mark && !manual_mark) {
double dx = -(circle_center_point.x - 320);
double dy = -(circle_center_point.y - 240);
center_delta_yaw = atan(dx / FOCUS_PIXAL) * 180 / PI;
center_delta_pitch = atan(dy / FOCUS_PIXAL) * 180 / PI;
if (abs(center_delta_pitch) > 0.3 || abs(center_delta_pitch) > 0.3) {
sendTarget(serial, center_delta_yaw, center_delta_pitch, false);
//五号车
// double dx = -(circle_center_point.x - 320 - 10);
// double dy = -(circle_center_point.y - 240 - 22);
//四号车
double dx = -(circle_center_point.x - 320 - 7);
double dy = -(circle_center_point.y - 240 - 64);
center_delta_yaw = static_cast<float>(atan(dx / FOCUS_PIXAL) * 180 / PI);
center_delta_pitch = static_cast<float>(atan(dy / FOCUS_PIXAL) * 180 / PI);
if (abs(center_delta_yaw) > 0.3 || abs(center_delta_pitch) > 0.3) {
// cout << "origin not get!" << endl;
// cout << center_delta_yaw << '\t' << center_delta_pitch << endl;
sendTarget(serial, center_delta_yaw, center_delta_pitch, 0);
return false;
} else {
origin_yaw = mcuData.curr_yaw;
origin_pitch = mcuData.curr_pitch;
auto_mark = true;
sendTarget(serial, center_delta_yaw, center_delta_pitch, true);
sendTarget(serial, center_delta_yaw, center_delta_pitch, 1);
LOGM(STR_CTR(WORD_BLUE_CODE, "auto mark success!"));
return true;
}

View File

@@ -27,6 +27,7 @@ bool Energy::isValidFanContour(cv::Mat &src, const vector<cv::Point> &fan_contou
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) {
//cout<<"length width fail."<<endl;
// cout << "length: " << length << '\t' << "width: " << width << '\t' << cur_rect.center << endl;
return false;
//矩形边长不合适
}
@@ -34,12 +35,14 @@ bool Energy::isValidFanContour(cv::Mat &src, const vector<cv::Point> &fan_contou
if (length_width_ratio > energy_part_param_.FAN_CONTOUR_HW_RATIO_MAX ||
length_width_ratio < energy_part_param_.FAN_CONTOUR_HW_RATIO_MIN) {
//cout<<"length width ratio fail."<<endl;
// cout << "HW: " << length_width_ratio << '\t' << cur_rect.center << endl;
return false;
//长宽比不合适
}
// cout << cur_contour_area / cur_size.area() << endl;
if (cur_contour_area / cur_size.area() < energy_part_param_.FAN_CONTOUR_AREA_RATIO_MIN) {
// cout << cur_contour_area / cur_size.area() << endl;
// cout << "area ratio: " << cur_contour_area / cur_size.area() << '\t' << cur_rect.center << endl;
return false;//轮廓对矩形的面积占有率不合适
}
double non_zero_rate = nonZeroRateOfRotateRect(src, cur_rect);
@@ -71,6 +74,7 @@ bool Energy::isValidArmorContour(const vector<cv::Point> &armor_contour) {
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) {
//cout<<"length width fail."<<endl;
// cout << "length: " << length << '\t' << "width: " << width << '\t' << cur_rect.center << endl;
return false;
//矩形边长不合适
}
@@ -79,11 +83,14 @@ bool Energy::isValidArmorContour(const vector<cv::Point> &armor_contour) {
if (length_width_ratio > energy_part_param_.ARMOR_CONTOUR_HW_RATIO_MAX ||
length_width_ratio < energy_part_param_.ARMOR_CONTOUR_HW_RATIO_MIN) {
//cout<<"length width ratio fail."<<endl;
// cout << "HW: " << length_width_ratio << '\t' << cur_rect.center << endl;
return false;
//长宽比不合适
}
if (cur_contour_area / cur_size.area() < energy_part_param_.ARMOR_CONTOUR_AREA_RATIO_MIN)
if (cur_contour_area / cur_size.area() < energy_part_param_.ARMOR_CONTOUR_AREA_RATIO_MIN) {
// cout << "area ratio: " << cur_contour_area / cur_size.area() << '\t' << cur_rect.center << endl;
return false;//轮廓对矩形的面积占有率不合适
}
return true;
}
@@ -108,6 +115,7 @@ bool Energy::isValidCenterRContour(const vector<cv::Point> &center_R_contour) {
|| 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: " << length << '\t' << "width: " << width << '\t' << cur_rect.center << endl;
return false;
//矩形边长不合适
}
@@ -115,16 +123,19 @@ bool Energy::isValidCenterRContour(const vector<cv::Point> &center_R_contour) {
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) {
//cout<<"length width ratio fail."<<endl;
// cout << "HW: " << length_width_ratio << '\t' << cur_rect.center << endl;
return false;
//长宽比不合适
}
if (cur_contour_area / cur_size.area() < energy_part_param_.CENTER_R_CONTOUR_AREA_RATIO_MIN)
if (cur_contour_area / cur_size.area() < energy_part_param_.CENTER_R_CONTOUR_AREA_RATIO_MIN) {
// cout << "area ratio: " << cur_contour_area / cur_size.area() << '\t' << cur_rect.center << endl;
return false;//轮廓对矩形的面积占有率不合适
}
std::vector<cv::Point2f> intersection;
if (rotatedRectangleIntersection(cur_rect, center_ROI, intersection) == 0) {
return false;
} else if (contourArea(intersection) < energy_part_param_.CENTER_R_CONTOUR_INTERSETION_AREA_MIN) {
cout << "R intersection: " << contourArea(intersection) << endl;
// cout << "R intersection: " << contourArea(intersection) << '\t' << cur_rect.center << endl;
return false;
}
return true;
@@ -138,11 +149,12 @@ bool Energy::isValidFlowStripFanContour(cv::Mat &src, const vector<cv::Point> &f
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;
// cout << "area: " << cur_contour_area << '\t' << endl;
return false;
//选区面积大小不合适
}
// cout << "area: " << cur_contour_area << endl;
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;//将矩形的长边设置为长
@@ -151,21 +163,23 @@ bool Energy::isValidFlowStripFanContour(cv::Mat &src, const vector<cv::Point> &f
|| 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;
// cout<<"length width fail."<<endl;
// cout << "length: " << length << '\t' << "width: " << width << '\t' << cur_rect.center << 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;
// cout << "HW: " << length_width_ratio << '\t' << cur_rect.center << endl;
return false;
//长宽比不合适
}
// cout << cur_contour_area / cur_size.area() << endl;
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) {
// cout << "area ratio: " << cur_contour_area / cur_size.area() << '\t' << cur_rect.center << endl;
return false;
}
// 轮廓对矩形的面积占有率不合适
@@ -202,21 +216,28 @@ bool Energy::isValidFlowStripContour(const vector<cv::Point> &flow_strip_contour
length > energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MAX ||
width > energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MAX) {
// cout<<"length width fail."<<endl;
// cout << "length: " << length << '\t' << "width: " << width << '\t' << cur_rect.center << endl;
return false;
//矩形边长不合适
}
// cout << length << '\t' << width << endl;
float length_width_ratio = length / width;//计算矩形长宽比
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) {
// cout<<"hw fail."<<endl;
// cout << "HW: " << length_width_ratio << '\t' << cur_rect.center << endl;
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) {
// cout << "area ratio: " << cur_contour_area / cur_size.area() << '\t' << cur_rect.center << endl;
return false;//轮廓对矩形的面积占有率不合适
}
std::vector<cv::Point2f> intersection;
if (rotatedRectangleIntersection(cur_rect, flow_strip_fan, intersection) == 0 ||
contourArea(intersection) < energy_part_param_.FLOW_STRIP_CONTOUR_INTERSETION_AREA_MIN) {
if (rotatedRectangleIntersection(cur_rect, flow_strip_fan, intersection) == 0) {
return false;
} else if (contourArea(intersection) < energy_part_param_.FLOW_STRIP_CONTOUR_INTERSETION_AREA_MIN) {
// cout << "intersection: " << contourArea(intersection) << '\t' << cur_rect.center << endl;
return false;
}
return true;

View File

@@ -12,7 +12,7 @@ using namespace cv;
//----------------------------------------------------------------------------------------------------------------------
// 此函数用于判断大小符
// ---------------------------------------------------------------------------------------------------------------------
void Energy::JudgeMode() {
void Energy::judgeMode() {
getRecentTargetArmorCenters();
if (recent_target_armor_centers.size() < 30) {
return;

View File

@@ -4,23 +4,44 @@
#include "energy/energy.h"
#include "log.h"
#include "config/setconfig.h"
using namespace std;
using namespace cv;
//----------------------------------------------------------------------------------------------------------------------
// 此函数用于判断是否可以发弹
// 此函数用于判断世界坐标系下是否可以发弹
// ---------------------------------------------------------------------------------------------------------------------
void Energy::judgeShoot(){
if (abs(yaw_rotation - mcuData.curr_yaw) < 0.3 && fabs(pitch_rotation - mcuData.curr_pitch) < 0.3) {
shoot = true;
void Energy::judgeShootInWorld(){
if (abs(yaw_rotation - mcuData.curr_yaw) < 0.8 && fabs(pitch_rotation - mcuData.curr_pitch) < 0.8) {
shoot = 4;
is_predicting = false;
is_guessing = true;
start_guess = true;
gettimeofday(&time_start_guess, NULL);
LOGM(STR_CTR(WORD_LIGHT_RED, "Start Guessing!"));
} else
shoot = false;
shoot = 2;
}
//----------------------------------------------------------------------------------------------------------------------
// 此函数用于判断云台坐标系下是否可以发弹
// ---------------------------------------------------------------------------------------------------------------------
void Energy::judgeShootInGimbal(){
if (abs(yaw_rotation) < 0.5 && fabs(pitch_rotation) < 0.5) {
shoot = 4;
is_predicting = false;
is_guessing = true;
start_guess = true;
gettimeofday(&time_start_guess, NULL);
// LOGM(STR_CTR(WORD_LIGHT_RED, "Start Guessing!"));
} else
shoot = 2;
sum_yaw += yaw_rotation;
sum_pitch += pitch_rotation;
yaw_rotation = AIM_KP * yaw_rotation + AIM_KI * sum_yaw;
pitch_rotation = AIM_KP * pitch_rotation + AIM_KI * sum_pitch;
}

View File

@@ -17,5 +17,5 @@ bool Energy::isGuessingTimeout() {
timeval cur_time;
gettimeofday(&cur_time, NULL);
return (cur_time.tv_sec - time_start_guess.tv_sec) * 1000.0 +
(cur_time.tv_usec - time_start_guess.tv_usec) / 1000.0 > 500;
(cur_time.tv_usec - time_start_guess.tv_usec) / 1000.0 > 1000;
};

View File

@@ -12,16 +12,15 @@ using namespace cv;
//----------------------------------------------------------------------------------------------------------------------
// 此函数为能量机关模式主控制流函数,且步兵需要同时拥有云台摄像头和底盘摄像头
// ---------------------------------------------------------------------------------------------------------------------
void Energy::run(cv::Mat &gimbal_src, cv::Mat &chassis_src) {
void Energy::runBig(cv::Mat &gimbal_src, cv::Mat &chassis_src) {
if (chassis_src.empty())
run(gimbal_src);//仅拥有云台摄像头则调用单摄像头的run函数
runBig(gimbal_src);//仅拥有云台摄像头则调用单摄像头的run函数
else if (is_gimbal) {
// energy_part_param_ = chassis_energy_part_param_;
energy_part_param_ = gimbal_energy_part_param_;
clearAll();
initImage(gimbal_src);
findFans(gimbal_src);
showFans("fan",gimbal_src);
// findFans(gimbal_src);
// showFans("fan",gimbal_src);
if (findArmors(gimbal_src) < 1)return;
if (show_energy)showArmors("armor", gimbal_src);
@@ -37,7 +36,6 @@ void Energy::run(cv::Mat &gimbal_src, cv::Mat &chassis_src) {
initEnergy();
destroyAllWindows();
} else if (is_chassis) {
// energy_part_param_ = chassis_energy_part_param_;
energy_part_param_ = chassis_energy_part_param_;
clearAll();
initImage(chassis_src);
@@ -47,7 +45,8 @@ void Energy::run(cv::Mat &gimbal_src, cv::Mat &chassis_src) {
if (findArmors(chassis_src) < 1)return;
if (show_energy)showArmors("armor", chassis_src);
if (!findFlowStripFan(chassis_src)) return;
if (!findFlowStripFan(chassis_src))return;
showFlowStripFan("flow strip fan", chassis_src);
if (!findTargetInFlowStripFan()) return;
if (!findCenterROI(chassis_src))return;
if (show_energy)showFlowStripFan("strip", chassis_src);
@@ -55,27 +54,14 @@ void Energy::run(cv::Mat &gimbal_src, cv::Mat &chassis_src) {
if (show_energy)showCenterR("R", chassis_src);
getTargetPolarAngle();
changeTarget();
JudgeMode();
if (energy_mode_init)return;
if (is_big && energy_rotation_init) {
initRotation();
return;
}
if (is_predicting) {
getPredictPoint(target_point);
gimbalRotation();
judgeShoot();
sendTarget(serial, yaw_rotation, pitch_rotation, shoot);
} else if (is_guessing && stayGuessing()) {
findFans(chassis_src);
if (show_energy)showFans("fans", chassis_src);
if (save_mark)writeDownMark();
if (!guessTarget()) return;
if (show_energy)showGuessTarget("guess", chassis_src);
getPredictPoint(guess_point);
gimbalRotation();
sendTarget(serial, yaw_rotation, pitch_rotation, false);
}
getPredictPoint(target_point);
gimbalRotation();
judgeShootInWorld();
sendTarget(serial, yaw_rotation, pitch_rotation, change_target);
}
}
@@ -83,7 +69,7 @@ void Energy::run(cv::Mat &gimbal_src, cv::Mat &chassis_src) {
//----------------------------------------------------------------------------------------------------------------------
// 此函数为能量机关模式主控制流函数,且步兵仅拥有云台摄像头
// ---------------------------------------------------------------------------------------------------------------------
void Energy::run(cv::Mat &gimbal_src) {
void Energy::runBig(cv::Mat &gimbal_src) {
energy_part_param_ = gimbal_energy_part_param_;
clearAll();
initImage(gimbal_src);
@@ -102,26 +88,57 @@ void Energy::run(cv::Mat &gimbal_src) {
if (show_energy)showCenterR("R", gimbal_src);
changeTarget();
getTargetPolarAngle();
JudgeMode();
if (energy_mode_init)return;
if (!getOrigin())return;
if (is_big && energy_rotation_init) {
// if (!getOrigin())return;
if (energy_rotation_init) {
initRotation();
return;
}
if (is_predicting) {
getPredictPoint(target_point);
gimbalRotation();
judgeShoot();
sendTarget(serial, yaw_rotation, pitch_rotation, shoot);
} else if (is_guessing && stayGuessing()) {
findFans(gimbal_src);
if (show_energy)showFans("fans", gimbal_src);
if (save_mark)writeDownMark();
guessTarget();
if (show_energy)showGuessTarget("guess", gimbal_src);
getPredictPoint(guess_point);
gimbalRotation();
sendTarget(serial, yaw_rotation, pitch_rotation, false);
}
getPredictPoint(target_point);
getAimPoint(predict_point);
judgeShootInGimbal();
sendTarget(serial, yaw_rotation, pitch_rotation, change_target);
}
//----------------------------------------------------------------------------------------------------------------------
// 此函数为小能量机关模式主控制流函数,击打小符只需要拥有云台摄像头
// ---------------------------------------------------------------------------------------------------------------------
void Energy::runSmall(cv::Mat &gimbal_src) {
energy_part_param_ = gimbal_energy_part_param_;
clearAll();
initImage(gimbal_src);
if (show_process)imshow("bin", gimbal_src);
if (findArmors(gimbal_src) < 1)return;
if (show_energy)showArmors("armor", gimbal_src);
if (!findFlowStripFan(gimbal_src))return;
if (!findTargetInFlowStripFan()) return;
// if (!findCenterROI(gimbal_src))return;
// if (show_energy)showFlowStripFan("strip", gimbal_src);
// if (!findCenterR(gimbal_src))return;
// if (show_energy)showCenterR("R", gimbal_src);
changeTarget();
getAimPoint(target_point);
judgeShootInGimbal();
sendTarget(serial, yaw_rotation, pitch_rotation, change_target);
}
//if (is_predicting) {
//getPredictPoint(target_point);
//getAimPoint(predict_point);
//cout << yaw_rotation << '\t' << pitch_rotation << endl;
//judgeShootInGimbal();
//sendTarget(serial, yaw_rotation, pitch_rotation, shoot);
//} else if (is_guessing && stayGuessing()) {
//findFans(gimbal_src);
//if (show_energy)showFans("fans", gimbal_src);
//if (save_mark)writeDownMark();
//guessTarget();
//if (show_energy)showGuessTarget("guess", gimbal_src);
//getPredictPoint(guess_point);
//getAimPoint(predict_point);
//sendTarget(serial, yaw_rotation, pitch_rotation, 5);
//}

View File

@@ -7,14 +7,25 @@
using namespace std;
//----------------------------------------------------------------------------------------------------------------------
// 此函数用于发送数据给主控板
// ---------------------------------------------------------------------------------------------------------------------
void Energy::sendTarget(Serial& serial, float x, float y, float z){
static short x_tmp, y_tmp, z_tmp;
uint8_t buff[8];
short x_tmp, y_tmp, z_tmp;
uint8_t buff[10];
#ifdef WITH_COUNT_FPS
static auto last_time = time(nullptr);
static int fps = 0;
time_t t = time(nullptr);
if (last_time != t) {
last_time = t;
cout << "fps:" << fps << ", (" << x << "," << y << "," << z << ")" << endl;
fps = 0;
}
fps += 1;
#endif
x_tmp = static_cast<short>(x * (32768 - 1) / 100);
y_tmp = static_cast<short>(y * (32768 - 1) / 100);
z_tmp = static_cast<short>(z * (32768 - 1) / 100);
@@ -25,8 +36,48 @@ void Energy::sendTarget(Serial& serial, float x, float y, float z){
buff[4] = static_cast<char>((y_tmp >> 0) & 0xFF);
buff[5] = static_cast<char>((z_tmp >> 8) & 0xFF);
buff[6] = static_cast<char>((z_tmp >> 0) & 0xFF);
buff[7] = 'e';
buff[9] = 'e';
serial.WriteData(buff, sizeof(buff));
send_cnt+=1;
// LOGM(STR_CTR(WORD_LIGHT_PURPLE, "send"));
}
}
//----------------------------------------------------------------------------------------------------------------------
// 此函数用于发送数据给主控板
// ---------------------------------------------------------------------------------------------------------------------
void Energy::sendTarget(Serial& serial, float x, float y, float z, uint16_t u){
short x_tmp, y_tmp, z_tmp;
uint8_t buff[10];
#ifdef WITH_COUNT_FPS
static auto last_time = time(nullptr);
static int fps = 0;
time_t t = time(nullptr);
if (last_time != t) {
last_time = t;
cout << "fps:" << fps << ", (" << x << "," << y << "," << z << ")" << endl;
fps = 0;
}
fps += 1;
#endif
x_tmp = static_cast<short>(x * (32768 - 1) / 100);
y_tmp = static_cast<short>(y * (32768 - 1) / 100);
z_tmp = static_cast<short>(z * (32768 - 1) / 100);
buff[0] = 's';
buff[1] = static_cast<char>((x_tmp >> 8) & 0xFF);
buff[2] = static_cast<char>((x_tmp >> 0) & 0xFF);
buff[3] = static_cast<char>((y_tmp >> 8) & 0xFF);
buff[4] = static_cast<char>((y_tmp >> 0) & 0xFF);
buff[5] = static_cast<char>((z_tmp >> 8) & 0xFF);
buff[6] = static_cast<char>((z_tmp >> 0) & 0xFF);
buff[7] = static_cast<char>((u >> 8) & 0xFF);
buff[8] = static_cast<char>((u >> 0) & 0xFF);;
buff[9] = 'e';
serial.WriteData(buff, sizeof(buff));
send_cnt+=1;
// LOGM(STR_CTR(WORD_LIGHT_PURPLE, "send"));
}

View File

@@ -43,7 +43,6 @@ void Energy::stretch(cv::Point point_1, cv::Point2f &point_2) {
double x_0 = point_1.x - circle_center_point.x;
double y_0 = point_1.y - circle_center_point.y;
double r_0 = sqrt(pow(x_0, 2) + pow(y_0, 2));
point_2.x = static_cast<float >( ARMOR_CENTER_TO_CYCLE_CENTER * x_0 / r_0);
point_2.y = static_cast<float >( ARMOR_CENTER_TO_CYCLE_CENTER * y_0 / r_0);
}

View File

@@ -33,7 +33,7 @@ mcu_data mcuData = { // 单片机端回传结构体
ARMOR_STATE, // 当前状态,自瞄-大符-小符
0, // 云台角度标记位
1, // 是否启用数字识别
ENEMY_BLUE, // 敌方颜色
ENEMY_RED, // 敌方颜色
};
WrapperHead *video_gimbal = nullptr; // 云台摄像头视频源
@@ -61,11 +61,11 @@ int main(int argc, char *argv[]) {
while (true) {
// 打开视频源
if (from_camera) {
video_gimbal = new CameraWrapper(0/*, "armor"*/);
video_chassis = new CameraWrapper(1/*, "energy"*/);
video_gimbal = new CameraWrapper(ARMOR_CAMERA_GAIN, 0/*, "armor"*/);
video_chassis = new CameraWrapper(ENERGY_CAMERA_GAIN, 0/*, "energy"*/);
} else {
video_gimbal = new VideoWrapper("/home/sun/项目/energy_video/gimble3.avi");
video_chassis = new VideoWrapper("/home/sun/项目/energy_video/gimble3.avi");
video_gimbal = new VideoWrapper("/home/sun/项目/energy_video/gimbal132.avi");
video_chassis = new VideoWrapper("/home/sun/项目/energy_video/gimbal132.avi");
}
if (video_gimbal->init()) {
LOGM("video_gimbal source initialization successfully.");
@@ -95,7 +95,13 @@ int main(int argc, char *argv[]) {
if (mcuData.state == BIG_ENERGY_STATE) {//大能量机关模式
if (last_state != BIG_ENERGY_STATE) {//若上一帧不是大能量机关模式,即刚往完成切换,则需要初始化
destroyAllWindows();
((CameraWrapper *) video_gimbal)->changeBrightness(ENERGY_CAMERA_GAIN);
delete video_gimbal;
video_gimbal = new CameraWrapper(ENERGY_CAMERA_GAIN, 0/*, "armor"*/);
if (video_gimbal->init()) {
LOGM("video_gimbal source initialization successfully.");
} else {
LOGW("video_gimbal source unavailable!");
}
energy.setBigEnergyInit();
checkReconnect(video_chassis->read(chassis_src));
#ifdef CHASSIS_FLIP_MODE
@@ -111,11 +117,18 @@ int main(int argc, char *argv[]) {
if (save_video) saveVideos(gimbal_src, chassis_src);//保存视频
if (show_origin) showOrigin(gimbal_src, chassis_src);//显示原始图像
energy.runBig(gimbal_src, chassis_src);
// energy.runBig(gimbal_src);
last_state = mcuData.state;//更新上一帧状态
} else if (mcuData.state == SMALL_ENERGY_STATE) {
if (mcuData.state != SMALL_ENERGY_STATE) {
destroyAllWindows();
((CameraWrapper *) video_gimbal)->changeBrightness(ENERGY_CAMERA_GAIN);
delete video_gimbal;
video_gimbal = new CameraWrapper(ENERGY_CAMERA_GAIN, 0/*, "armor"*/);
if (video_gimbal->init()) {
LOGM("video_gimbal source initialization successfully.");
} else {
LOGW("video_gimbal source unavailable!");
}
energy.setSmallEnergyInit();
}
ok = checkReconnect(video_gimbal->read(gimbal_src));
@@ -130,7 +143,13 @@ int main(int argc, char *argv[]) {
} else { // 自瞄模式
if (last_state != ARMOR_STATE) {
destroyAllWindows();
((CameraWrapper *) video_gimbal)->changeBrightness(ARMOR_CAMERA_GAIN);
delete video_gimbal;
video_gimbal = new CameraWrapper(ARMOR_CAMERA_GAIN, 0/*, "armor"*/);
if (video_gimbal->init()) {
LOGM("video_gimbal source initialization successfully.");
} else {
LOGW("video_gimbal source unavailable!");
}
}
last_state = mcuData.state;
ok = checkReconnect(video_gimbal->read(gimbal_src));
@@ -138,13 +157,13 @@ int main(int argc, char *argv[]) {
flip(gimbal_src, gimbal_src, GIMBAL_FLIP_MODE);
#endif
if (!from_camera) extract(gimbal_src);
if (save_video) saveVideos(gimbal_src);
// if (save_video) saveVideos(gimbal_src);
if (show_origin) showOrigin(gimbal_src);
CNT_TIME("Armor Time", {
armorFinder.run(gimbal_src);
});
}
// cv::waitKey(1);
// cv::waitKey(0);
// });
} while (ok);
delete video_gimbal;

View File

@@ -38,9 +38,10 @@ private:
IplImage* iplImage;
int channel;
public:
CameraWrapper(int camera_mode=1, const std::string &n="NULL");
int gain;
CameraWrapper(int gain, int camera_mode=1, const std::string &n="NULL");
~CameraWrapper() final;
bool init() final;
@@ -48,6 +49,7 @@ public:
bool readRaw(cv::Mat& src);
bool readProcessed(cv::Mat& src);
bool changeBrightness(int brightness);
// bool once
};

View File

@@ -12,27 +12,41 @@
#define CAMERA_EXPOSURE (10)
#endif
#ifndef CAMERA_BLUE_GAIN
#define CAMERA_BLUE_GAIN (100)
#ifndef CAMERA_RED_GAIN
#define CAMERA_RED_GAIN (100)
#endif
#ifndef CAMERA_GREEN_GAIN
#define CAMERA_GREEN_GAIN (100)
#define CAMERA_GREEN_GAIN (100)
#endif
#ifndef CAMERA_RED_GAIN
#define CAMERA_RED_GAIN (100)
#ifndef CAMERA_BLUE_GAIN
#define CAMERA_BLUE_GAIN (100)
#endif
#ifndef ARMOR_CAMERA_GAIN
#define ARMOR_CAMERA_GAIN (30)
#endif
#ifndef ENERGY_CAMERA_GAIN
#define ENERGY_CAMERA_GAIN (20)
#endif
#ifndef AIM_KP
#define AIM_KP (6)
#endif
#ifndef AIM_KI
#define AIM_KI (0.1)
#endif
#ifndef COMPENSATE_YAW
#define COMPENSATE_YAW (5)
#endif
#ifndef COMPENSATE_PITCH
#define COMPENSATE_PITCH (74)
#endif
//#define GIMBAL_FLIP_MODE (-1)
//#define CHASSIS_FLIP_MODE (-1)
//#define WITH_TIME_BASED_CAMERA_GAIN
#define WITH_COUNT_FPS
#endif /* SETCONFIG_H */

View File

@@ -30,27 +30,27 @@ extern ArmorFinder armorFinder;
extern Energy energy;
void uartReceive(Serial *pSerial) {
char buffer[20];
int cnt = 0;
char buffer[30];
LOGM(STR_CTR(WORD_LIGHT_WHITE, "data receive start!"));
while (true) {
char byte = 0;
memset(buffer, 0, sizeof(buffer));
while (pSerial->ReadData((uint8_t *) &byte, 1) && byte != '\n') {
buffer[cnt++] = byte;
if (cnt >= sizeof(buffer)) {
// LOGE("data receive over flow!");
cnt = 0;
}
}
if (cnt == 0 && byte == '\n') {
// LOGM("%d", cnt);
}
if (cnt == sizeof(mcuData)) {
pSerial->ReadData((uint8_t *) buffer, sizeof(mcuData)+1);
if (buffer[sizeof(mcuData)] == '\n') {
memcpy(&mcuData, buffer, sizeof(mcuData));
// LOGM("Get, state:%c, mark:%d!", mcuData.state, (int) mcuData.mark);
// LOGM("Get yaw: %f, pitch: %f!", mcuData.curr_yaw, mcuData.curr_pitch);
// static int t = time(nullptr);
// static int cnt = 0;
// if(time(nullptr) > t){
// t = time(nullptr);
// LOGM("fps:%d", cnt);
// cnt = 0;
// }else{
// cnt++;
// }
}else{
// LOGW("corrupt data!");
}
cnt = 0;
}
}
@@ -75,13 +75,15 @@ cv::VideoWriter initVideoWriter(const std::string &filename_prefix) {
bool checkReconnect(bool is_camera_0_connect, bool is_camera_1_connect) {
if (!is_camera_0_connect) {
int curr_gain = ((CameraWrapper* )video_gimbal)->gain;
delete video_gimbal;
video_gimbal = new CameraWrapper(0, "armor");
video_gimbal = new CameraWrapper(curr_gain, 0/*, "armor"*/);
is_camera_0_connect = video_gimbal->init();
}
if (!is_camera_1_connect) {
int curr_gain = ((CameraWrapper* )video_gimbal)->gain;
delete video_chassis;
video_chassis = new CameraWrapper(1, "energy");
video_chassis = new CameraWrapper(curr_gain, 0/*, "energy"*/);
is_camera_1_connect = video_chassis->init();
}
return is_camera_0_connect && is_camera_1_connect;
@@ -89,8 +91,9 @@ bool checkReconnect(bool is_camera_0_connect, bool is_camera_1_connect) {
bool checkReconnect(bool is_camera_connect) {
if (!is_camera_connect) {
int curr_gain = ((CameraWrapper* )video_gimbal)->gain;
delete video_gimbal;
video_gimbal = new CameraWrapper(0, "armor");
video_gimbal = new CameraWrapper(curr_gain, 0/*, "armor"*/);
is_camera_connect = video_gimbal->init();
}
return is_camera_connect;

View File

@@ -13,79 +13,107 @@ using std::cout;
using std::endl;
using namespace cv;
CameraWrapper::CameraWrapper(int camera_mode, const std::string &n):
CameraWrapper::CameraWrapper(int gain, int camera_mode, const std::string &n) :
name(n),
mode(camera_mode),
camera_cnts(2),
camera_status(-1),
iplImage(nullptr),
rgb_buffer(nullptr),
channel(3){
channel(3),
gain(gain){
}
bool CameraWrapper::init() {
CameraSdkInit(1);
int camera_enumerate_device_status = CameraEnumerateDevice(camera_enum_list, &camera_cnts);
if(camera_enumerate_device_status != CAMERA_STATUS_SUCCESS){
int camera_enumerate_device_status = CameraEnumerateDevice(camera_enum_list, &camera_cnts);
if (camera_enumerate_device_status != CAMERA_STATUS_SUCCESS) {
LOGE("CameraEnumerateDevice fail with %d!", camera_enumerate_device_status);
}
if (camera_cnts == 0) {
LOGE("No camera device detected!");
return false;
}else if(camera_cnts >= 1){
} else if (camera_cnts >= 1) {
LOGM("%d camera device detected!", camera_cnts);
}
int i;
for(i=0; i<camera_cnts; i++){
for (i = 0; i < camera_cnts; i++) {
camera_status = CameraInit(&camera_enum_list[i], -1, -1, &h_camera);
if (camera_status != CAMERA_STATUS_SUCCESS) {
CameraUnInit(h_camera);
continue;
}
CameraGetFriendlyName(h_camera, camera_name);
if(name=="NULL" || strcmp(name.data(), camera_name)==0){
if (name == "NULL" || strcmp(name.data(), camera_name) == 0) {
break;
}
CameraUnInit(h_camera);
}
if(i >= camera_cnts){
if (i >= camera_cnts) {
LOGE("No device name %s or device open error!!", name.data());
return false;
}
auto status = CameraGetCapability(h_camera, &tCapability);
if (status != CAMERA_STATUS_SUCCESS) {
cout << "CameraGetCapability return error code " << status << endl;
return false;
}
auto status = CameraGetCapability(h_camera, &tCapability);
if (status != CAMERA_STATUS_SUCCESS) {
cout << "CameraGetCapability return error code " << status << endl;
return false;
}
rgb_buffer = (unsigned char *)malloc(tCapability.sResolutionRange.iHeightMax *
tCapability.sResolutionRange.iWidthMax * 3);
rgb_buffer = (unsigned char *) malloc(tCapability.sResolutionRange.iHeightMax *
tCapability.sResolutionRange.iWidthMax * 3);
#ifdef Windows
char filepath[200];
sprintf(filepath, PROJECT_DIR"/others/%s.Config", name.data());
if (CameraReadParameterFromFile(h_camera, filepath) != CAMERA_STATUS_SUCCESS) {
LOGE("Load parameter %s from file fail!", filepath);
return false;
}
if (CameraLoadParameter(h_camera, PARAMETER_TEAM_A) != CAMERA_STATUS_SUCCESS) {
LOGE("CameraLoadParameter %s fail!", filepath);
return false;
}
LOGM("successfully loaded %s!", filepath);
char filepath[200];
sprintf(filepath, PROJECT_DIR"/others/%s.Config", name.data());
if (CameraReadParameterFromFile(h_camera, filepath) != CAMERA_STATUS_SUCCESS) {
LOGE("Load parameter %s from file fail!", filepath);
return false;
}
if (CameraLoadParameter(h_camera, PARAMETER_TEAM_A) != CAMERA_STATUS_SUCCESS) {
LOGE("CameraLoadParameter %s fail!", filepath);
return false;
}
LOGM("successfully loaded %s!", filepath);
#elif defined(Linux)
CameraSetAeState(h_camera, false);
CameraSetExposureTime(h_camera, CAMERA_EXPOSURE*1000);
CameraSetAnalogGain(h_camera, ARMOR_CAMERA_GAIN);
if(mode == 0){
CameraSetGain(h_camera, CAMERA_BLUE_GAIN, CAMERA_GREEN_GAIN, CAMERA_RED_GAIN);
CameraSetExposureTime(h_camera, CAMERA_EXPOSURE * 1000);
#ifndef WITH_TIME_BASED_CAMERA_GAIN
CameraSetAnalogGain(h_camera, gain);
#else
#include <sys/time.h>
timeval tv;
int gain;
gettimeofday(&tv, nullptr);
float hour = (tv.tv_sec % (3600 * 24)) / 3600.0;
if (6 <= hour && hour < 10) {
gain = 20;
LOGM("Set gain to morning 20");
} else if (10 <= hour && hour < 16) {
gain = 10;
LOGM("Set gain to day 10");
} else if (16 <= hour && hour < 17) {
gain = 20;
LOGM("Set gain to early evening 20");
} else if (17 <= hour && hour < 18) {
gain = 40;
LOGM("Set gain to evening 40");
} else {
gain = 50;
LOGM("Set gain to early night 50");
}
CameraSetAnalogGain(h_camera, gain);
#endif
if (mode == 0) {
CameraSetGain(h_camera, CAMERA_RED_GAIN, CAMERA_GREEN_GAIN, CAMERA_BLUE_GAIN);
CameraSetLutMode(h_camera, LUTMODE_PRESET);
}
#endif
double t;
CameraGetExposureTime(h_camera, &t);
LOGM("Exposure time: %lfms", t / 1000.0);
double t;
CameraGetExposureTime(h_camera, &t);
LOGM("Exposure time: %lfms", t / 1000.0);
/*让SDK进入工作模式开始接收来自相机发送的图像
数据。如果当前相机是触发模式,则需要接收到
触发帧以后才会更新图像。 */
@@ -97,7 +125,7 @@ bool CameraWrapper::init() {
CameraSetGamma、CameraSetContrast、CameraSetGain等设置图像伽马、对比度、RGB数字增益等等。
CameraGetFriendlyName CameraSetFriendlyName 获取/设置相机名称(该名称可写入相机硬件)
*/
cout << tCapability.sIspCapacity.bMonoSensor << endl;
cout << tCapability.sIspCapacity.bMonoSensor << endl;
if (tCapability.sIspCapacity.bMonoSensor) {
channel = 1;
CameraSetIspOutFormat(h_camera, CAMERA_MEDIA_TYPE_MONO8);
@@ -111,16 +139,17 @@ bool CameraWrapper::init() {
}
bool CameraWrapper::changeBrightness(int brightness) {
CameraUnInit(h_camera);
CameraSetAnalogGain(h_camera, brightness);
}
bool CameraWrapper::read(cv::Mat& src) {
if(mode==0)return readProcessed(src);
if(mode==1)return readRaw(src);
bool CameraWrapper::read(cv::Mat &src) {
if (mode == 0)return readProcessed(src);
if (mode == 1)return readRaw(src);
}
bool CameraWrapper::readRaw(cv::Mat &src) {
if (CameraGetImageBuffer(h_camera, &frame_info, &pby_buffer, 1000) == CAMERA_STATUS_SUCCESS){
if (CameraGetImageBuffer(h_camera, &frame_info, &pby_buffer, 1000) == CAMERA_STATUS_SUCCESS) {
if (iplImage) {
cvReleaseImageHeader(&iplImage);
}
@@ -144,8 +173,9 @@ bool CameraWrapper::readRaw(cv::Mat &src) {
bool CameraWrapper::readProcessed(cv::Mat &src) {
// cerr << "Get-1" << endl;
if (CameraGetImageBuffer(h_camera, &frame_info, &pby_buffer, 1000) == CAMERA_STATUS_SUCCESS){
CameraImageProcess(h_camera, pby_buffer, rgb_buffer, &frame_info); // this function is super slow, better not to use it.
if (CameraGetImageBuffer(h_camera, &frame_info, &pby_buffer, 1000) == CAMERA_STATUS_SUCCESS) {
CameraImageProcess(h_camera, pby_buffer, rgb_buffer,
&frame_info); // this function is super slow, better not to use it.
if (iplImage) {
cvReleaseImageHeader(&iplImage);
}
@@ -162,11 +192,9 @@ bool CameraWrapper::readProcessed(cv::Mat &src) {
}
}
CameraWrapper::~CameraWrapper()
{
CameraWrapper::~CameraWrapper() {
CameraUnInit(h_camera);
//注意先反初始化后再free
if(rgb_buffer != nullptr)
if (rgb_buffer != nullptr)
free(rgb_buffer);
}

View File

@@ -191,7 +191,7 @@ Serial::Serial(int nSpeed, char nEvent, int nBits, int nStop) :
nSpeed(nSpeed), nEvent(nEvent), nBits(nBits), nStop(nStop) {
if (wait_uart) {
LOGM("Wait for serial be ready!");
while (InitPort(nSpeed, nEvent, nBits, nStop) == false);
while (!InitPort(nSpeed, nEvent, nBits, nStop));
LOGM("Port set successfully!");
} else {
if (InitPort(nSpeed, nEvent, nBits, nStop)) {
@@ -234,7 +234,7 @@ bool Serial::WriteData(const unsigned char *pData, unsigned int length) {
return false;
}
while ((curr = write(fd, pData + cnt, length - cnt)) > 0 && (cnt += curr) < length);
if (cnt < 0) {
if (curr < 0) {
LOGE("Serial offline!");
close(fd);
if (wait_uart) {
@@ -248,7 +248,7 @@ bool Serial::WriteData(const unsigned char *pData, unsigned int length) {
bool Serial::ReadData(unsigned char *buffer, unsigned int length) {
int cnt = 0, curr = 0;
while ((curr = read(fd, buffer + cnt, length - cnt)) > 0 && (cnt += curr) < length);
if (cnt < 0) {
if (curr < 0) {
LOGE("Serial offline!");
close(fd);
if (wait_uart) {

View File

@@ -54,16 +54,14 @@ def save_para(folder, paras):
save_bias(fp, paras[7])
STEPS = 10000
BATCH = 30
LEARNING_RATE_BASE = 0.005
STEPS = 100000
BATCH = 50
LEARNING_RATE_BASE = 0.001
LEARNING_RATE_DECAY = 0.99
MOVING_AVERAGE_DECAY = 0.99
def train(dataset, show_bar=False):
test_images, test_labels = dataset.all_test_sets()
x = tf.placeholder(tf.float32, [None, generate.SRC_ROWS, generate.SRC_COLS, generate.SRC_CHANNELS])
y_= tf.placeholder(tf.float32, [None, forward.OUTPUT_NODES])
keep_rate = tf.placeholder(tf.float32)
@@ -103,11 +101,12 @@ def train(dataset, show_bar=False):
_, loss_value, step = sess.run(
[train_op, loss, global_step],
feed_dict={x: images_samples, y_: labels_samples, keep_rate:0.5}
feed_dict={x: images_samples, y_: labels_samples, keep_rate:0.3}
)
if i % 100 == 0:
if i % 1000 == 0:
if i % 500 == 0:
test_images, test_labels = dataset.sample_test_sets(10000)
acc = sess.run(accuracy, feed_dict={x: test_images, y_: test_labels, keep_rate:1.0})
bar.set_postfix({"loss": loss_value, "acc": acc})
@@ -116,6 +115,9 @@ def train(dataset, show_bar=False):
vars_val = sess.run(vars)
save_para("/home/xinyang/Workspace/RM_auto-aim/tools/para", vars_val)
print("save done!")
# pred = sess.run(y, feed_dict={x: test_images, keep_rate:1.0})
# nodes_val = sess.run(nodes, feed_dict={x:test_images})
# return vars_val, nodes_val
DevList = mvsdk.CameraEnumerateDevice()

View File

@@ -35,10 +35,10 @@ CONV1_OUTPUT_CHANNELS = 6
CONV2_KERNAL_SIZE = 3
# 第二层卷积输出通道数
CONV2_OUTPUT_CHANNELS = 10
CONV2_OUTPUT_CHANNELS = 12
# 第一层全连接宽度
FC1_OUTPUT_NODES = 16
FC1_OUTPUT_NODES = 30
# 第二层全连接宽度(输出标签类型数)
FC2_OUTPUT_NODES = 15

View File

@@ -40,7 +40,7 @@ class DataSet:
files = os.listdir(dir)
for file in tqdm(files, postfix={"loading id": i}, dynamic_ncols=True):
if file[-3:] == "jpg":
if random.random() > 0.2:
if random.random() > 0.7:
self.train_samples.append(self.file2nparray("%s/%s" % (dir, file)))
self.train_labels.append(self.id2label(i))
else:
@@ -61,6 +61,15 @@ class DataSet:
labels.append(self.train_labels[id])
return np.array(samples), np.array(labels)
def sample_test_sets(self, length):
samples = []
labels = []
for i in range(length):
id = random.randint(0, len(self.test_samples)-1)
samples.append(self.test_samples[id])
labels.append(self.test_labels[id])
return np.array(samples), np.array(labels)
def all_train_sets(self):
return self.train_samples[:], self.train_labels[:]

View File

@@ -2,5 +2,5 @@
echo "#!/bin/bash" > $2/startup-run
echo "$1/tools/auto-pull.sh" >> $2/startup-run
echo "gnome-terminal -- bash -c \"echo sjturm | sudo -S $1/tools/monitor.sh \\\"$2/run --run-with-camera --save-video --wait-uart --save-labelled-boxes --show-armor-box\\\"\"" >> $2/startup-run
echo "gnome-terminal -- bash -c \"echo sjturm | sudo -S $1/tools/monitor.sh \\\"$2/run --run-with-camera --save-video --wait-uart --save-labelled-boxes\\\"\"" >> $2/startup-run
chmod +x $2/startup-run

View File

@@ -1,7 +1,7 @@
6
-0.012731806
-0.68924344
1.0428871
0.09240551
0.87806237
-0.51778877
-0.20627302
1.6024942
1.7967451
1.4466392
-0.098023266
-0.006771178

View File

@@ -2,453 +2,453 @@
6
5
5
-0.0705555
0.086937346
0.297247
0.51908225
0.41566578
0.22415005
0.21470949
0.42054617
0.57512695
0.50255156
0.2663179
0.10764991
0.32504323
0.27210033
0.32694185
0.18968254
-0.03312495
-0.28554282
-0.27717206
0.010500877
-0.16386741
-0.58856106
-1.0167654
-0.59654444
-0.07342564
0.6650266
0.6682501
0.61575854
0.20123789
0.13246079
0.9794644
0.9181109
0.75080305
0.5678118
0.17880438
0.8291312
0.9157011
0.8058578
0.6174977
0.3349475
0.93871576
1.0840453
0.9012157
0.6562343
0.28151926
0.8399793
0.9920022
0.64904636
0.6055482
0.15666491
-0.8087083
-0.5565874
-0.8960519
-0.80074924
-0.74640626
-0.2773623
-0.20795147
-0.1870408
-0.15045224
-0.13983378
-0.10816965
0.031628396
-0.116946414
-0.013991349
0.21591163
-0.18964738
0.0040286863
-0.30242768
-0.24229145
0.23588136
-0.331128
-0.5470479
-0.7203085
-0.6601643
-0.05225026
0.45265025
0.75259274
0.74857485
0.7100708
0.34476462
0.46986035
0.5765347
0.6258838
0.3804861
0.3160558
0.6183596
0.59951615
0.60037804
0.6340707
0.34009996
0.7194144
0.8571618
0.94336456
0.90685135
0.41317853
1.0044444
1.0062212
1.0895951
0.92497915
0.7468299
-1.2501324
-0.74794984
-0.047555014
0.49243745
0.8178278
-1.2034731
-0.49681732
0.015281494
0.60018766
0.713024
-0.84448695
-0.0899703
0.09781959
0.4817282
0.51024574
0.010328657
0.2768326
0.6458937
0.65859175
0.39070535
0.60249025
1.1937758
0.9160051
0.8284883
0.53566974
-0.4362068
-0.2836022
-0.32180697
0.022249598
0.29908466
-0.5530434
-0.4986115
-0.278484
-0.31018886
-0.24363342
-0.35979065
-0.43008342
-0.37437305
-0.30203703
-0.5734246
0.02336341
-0.25258422
-0.3121478
-0.6288646
-0.4711073
0.12114608
-0.061813425
-0.12937883
-0.6477893
-0.6810196
1.8673725
2.8808968
3.1819828
3.0621288
2.5003161
2.4616675
3.2074707
3.5739362
3.1081522
2.4229178
2.4271266
3.280304
3.0261867
2.3990371
1.8921077
2.005818
2.4233122
2.1124473
1.5049059
1.0315852
1.0267158
0.8723091
0.44316038
0.1576413
0.22018914
0.18436278
-0.04525133
-0.28330094
-0.50770444
-0.4281736
0.26419267
0.16408478
0.19734842
-0.2016362
-0.32106283
0.64052576
0.45036018
0.42224813
0.106944986
-0.15083833
0.9302013
0.7691678
0.6336322
0.078011096
-0.031026825
0.80035543
0.60188663
0.38603687
-0.03504348
-0.19659142
0.61344516
0.8947993
0.97315925
0.74691004
0.49092364
1.2537221
1.9796665
1.9934042
1.6571536
1.5510287
1.7490395
2.4188108
2.487965
2.0581145
1.922978
1.7984617
2.3430247
2.2450094
1.9467311
1.6972682
1.2808937
1.5145483
1.4981558
1.1744506
1.2942766
-0.028776312
0.08628688
0.14530973
0.060263254
-0.1992724
-0.3509845
-0.14943084
0.05269242
-0.047488246
-0.32251114
-0.055337034
-0.0606678
0.13780722
0.025866544
-0.2515092
0.36665168
0.4256815
0.44711438
0.45632693
0.18695426
0.83469534
0.73099476
0.90957487
0.7863896
0.60097635
-2.77742
-1.898205
-0.51413226
0.29049698
0.93399036
-2.6324046
-1.413464
-0.11643134
0.7600749
1.0856903
-2.0343983
-0.7860615
0.3931903
1.0088302
1.2542579
-1.0282527
0.00558986
0.7271341
1.2017635
0.9958149
0.2970806
1.2236876
1.36118
1.3418391
0.8660408
-1.1435972
-0.83455884
-0.7378884
-0.20356347
0.21133415
-0.84094524
-1.1279244
-0.6961366
-0.4854085
-0.026166996
-0.54931265
-0.4710362
-0.7298363
-0.64001644
-0.62205493
0.03693532
-0.40307578
-0.4964193
-0.42969394
-0.5397872
0.3220369
0.14219745
-0.4169855
-0.48323318
-0.77415246
-0.4052389
0.5951485
0.4901534
0.51781464
0.026524775
0.19928466
0.8500332
0.8974233
0.75791407
0.29939106
0.1305985
0.94468176
0.8779284
0.47177282
0.018099217
-0.2669419
0.14852984
0.17997491
-0.40414903
-0.57394934
-0.8052322
-0.6834026
-0.9813351
-1.2330854
-1.1226501
-0.2375166
-0.25760472
-0.6702083
-0.83058023
-0.845694
-0.035079293
0.15334488
-0.20645554
-0.6201716
-0.58026224
0.23743017
0.41283235
0.2761712
-0.080429204
-0.5188592
0.713986
0.6536175
0.46903017
0.15473464
-0.28156337
0.5111026
0.42682606
0.4112979
0.07900778
-0.2720577
-0.4981358
-0.051663946
-0.023117686
-0.19846022
-0.19126081
0.29513282
0.93106616
0.9072645
0.5732627
0.26237917
0.39974377
1.1159221
1.0814219
0.950581
0.671661
0.48101172
1.0488389
1.003414
0.9169417
0.5284077
-0.20465238
0.40837994
0.26445296
0.16031574
0.18525025
-1.1795493
-1.0623146
-1.3544596
-1.3211613
-1.4418778
-1.2897592
-1.3648815
-1.5633347
-1.4766223
-1.5375725
-1.0636053
-1.0550519
-1.2028064
-1.3285335
-1.4901532
-0.59239966
-0.5102294
-0.7126663
-0.6390671
-0.88960606
0.11505768
0.08690188
-0.012430734
-0.23703271
-0.070601396
-2.499217
-1.5118762
-0.63362616
0.34636214
0.80023897
-2.2490098
-1.210647
-0.30495015
0.6582943
0.92495674
-1.949688
-0.931986
0.08990933
0.8216611
0.81956995
-1.0822672
-0.17065391
0.52672815
0.6972465
0.6062274
-0.1929201
0.5915268
0.72986585
0.88998604
0.5383484
0.69495237
0.8119897
1.0762402
1.4192832
1.67176
0.63202345
0.958035
1.1269803
1.2325205
1.1469792
0.7853533
1.0906031
1.1132238
1.087981
1.0139153
1.3069341
1.2574402
1.2478752
1.1044679
0.7778477
1.4372398
1.3009509
1.2459791
0.84846544
0.73138183
-0.10642219
0.54904705
1.0220182
1.2654289
1.0080621
0.63893425
1.0596974
1.5017769
1.7486153
1.2255592
0.7572802
1.1565144
1.2662624
1.3252954
1.1559033
0.22455153
0.46842065
0.6101949
0.6682584
0.1469474
-0.19053003
-0.30085373
-0.505979
-0.6151139
-0.7488737
-0.67636555
-0.7467412
-0.7404055
-0.77479744
-0.75153095
-0.5121083
-0.580226
-0.57781655
-0.6191948
-0.4956569
-0.5530203
-0.54242903
-0.58190167
-0.808631
-0.5255669
-0.5567334
-0.65943664
-0.675188
-0.7753057
-0.5219072
-0.4224288
-0.4372446
-0.65674895
-0.88619053
-0.5918416
0.45536855
0.382092
-0.017086059
-0.4412066
-0.32249
0.5902474
0.4910132
0.02227385
-0.4520488
-0.6278883
0.60164636
0.3453617
0.16053873
-0.39892384
-0.4782997
0.56412727
0.5470579
0.33888572
-0.025963284
0.010916833
0.7818745
0.9463605
0.72511697
0.44537586
0.35324848
-0.6419165
-0.347417
-0.40558645
-0.50654674
-0.44879192
-0.49447027
-0.31920582
-0.1661499
-0.4432326
-0.33963177
-0.38981852
-0.4906231
-0.45195618
-0.52474713
-0.39969632
-0.4819537
-0.71747667
-0.821255
-0.8445041
-0.89447993
-0.859059
-0.98320967
-1.0902424
-1.105878
-1.2187494
0.67084956
0.9035801
1.2065095
1.3081064
1.2326727
1.0170805
1.0677104
1.5938762
1.4207084
1.3485196
1.0809016
1.3998586
1.7368488
1.5395899
1.5694551
1.3630624
1.4492949
1.5428637
1.393225
1.4149159
1.1494107
1.2268404
1.2541622
0.96135026
0.90241027
-0.31921467
-0.110522695
0.09325943
-0.0139649
-0.028535917
-0.24136181
0.03892438
0.20345062
-0.074525945
-0.029405555
-0.07647651
-0.15445644
-0.058089375
-0.40588626
-0.27692583
-0.2698881
-0.55068505
-0.5919062
-0.5438777
-0.5993602
-0.7458306
-0.81796175
-0.94331497
-1.0076928
-0.8992378
1.9416478
3.2734282
4.160874
4.7219324
4.1175704
3.0404797
4.511751
5.663269
5.930972
4.7846756
3.3442042
4.758655
5.6102233
5.5837803
4.3014107
2.793397
3.7502306
4.3392096
4.142601
2.9172728
1.819791
2.428208
2.3962913
2.0173726
1.0743914
0.26512346
0.3457875
0.58334744
0.40681112
0.40550798
0.29478824
0.732128
0.8325436
0.603493
0.7258464
0.5068629
0.67576087
0.74854803
0.60851085
0.77726454
0.3519754
0.468439
0.6548478
0.70905083
0.3086395
0.4289891
0.47042668
0.37940606
0.45548278
0.14207979
0.71661115
0.09474261
-0.7471369
-1.7338398
-2.5905223
0.7082176
0.21243899
-0.6654869
-1.7607315
-2.7247927
0.6009304
0.10814533
-0.6752587
-1.7909975
-2.3464935
0.79290503
0.49252048
-0.43408415
-1.3109739
-1.9383324
0.9131795
0.58063436
-0.065964356
-0.84630096
-1.3107594
0.9702296
1.7605543
1.9099594
1.8536079
1.3434014
1.1538997
1.8189181
1.9872671
2.0980296
1.5539708
0.9389947
1.4959635
1.8016711
1.5903975
1.2731018
0.78981453
1.0439569
1.3309318
1.2204188
0.78188473
0.41300166
0.4995686
0.52244127
0.5596004
0.21890602
0.30612093
0.85429645
1.2398238
1.2750283
1.3086212
1.0696554
1.3433759
1.729579
1.7326889
1.7986484
1.3991985
1.7318608
2.0507987
1.941499
1.7631179
1.4714234
1.8296314
1.9416764
1.8468171
1.6414593
1.4085735
1.5106102
1.610607
1.5357318
1.1668565
1.3847203
1.9328053
2.0932007
1.6669843
1.3775337
1.6736194
2.307166
2.3085163
2.008549
1.2341207
1.6037624
2.0786712
1.9735341
1.5647856
1.02917
1.3709607
1.4461753
1.256765
0.9555051
0.36569837
0.7852095
0.7917901
0.43664944
0.2549527
-0.067954175
0.20057896
1.3856035
2.0629358
2.809679
2.3610249
0.83472407
2.064841
3.0214195
3.401786
2.7669187
1.1871954
2.2021434
2.9477324
3.2896252
2.3611999
0.58470565
1.433704
1.8206064
1.6048844
1.0893
0.079494156
0.14756773
0.21510047
0.17841841
-0.3402442
0.82796144
0.89763546
0.9589713
0.86110723
0.6416584
1.0780864
1.2395475
1.4097389
1.1237956
1.0438948
1.0541381
1.3774344
1.422105
1.0753438
0.956809
0.99444
0.99848217
1.2054675
1.0716856
0.8924131
0.67220867
0.89100254
0.7673037
0.74212146
0.4557632
1.4435326
1.0917244
0.5117782
-0.042295564
-0.3919759
1.3343437
1.0884248
0.5695666
0.095347434
-0.17561129
1.5594242
1.1927198
0.81222206
0.10072425
-0.01981995
1.4395866
1.4196151
0.99251515
0.5299192
0.3711792
1.7289668
1.5802932
1.4318615
0.9496403
0.90711755
0.7756156
1.6576271
1.7558899
1.423089
1.063295
0.9460997
1.68862
1.8560133
1.7430701
1.267287
0.8309027
1.4070404
1.6903514
1.5321271
1.0099223
0.26294753
0.86975366
0.8681627
0.6666984
0.39146528
-0.17483807
0.06906817
0.0685056
0.0048298114
-0.29763746
-0.72470987
-0.3025738
0.1441088
0.6175989
0.71524495
-0.08114317
0.23537244
0.65833175
0.748487
0.7920688
0.08497454
0.5255702
0.82396054
1.130095
0.9759796
0.31005707
0.51547265
0.85156286
0.89206517
0.5910351
0.28886735
0.5871289
0.55338776
0.54379845
0.27539033
1.3043873
2.1130838
2.00019
1.9147623
1.2632021
1.6259333
2.4304924
2.4733207
2.0936246
1.3039585
1.5398262
2.1048331
2.2389119
1.5818008
0.94920427
1.1412464
1.5037223
1.2156814
1.0366565
0.3966581
0.37856415
0.6628915
0.5291198
0.11434809
-0.09481559

View File

@@ -1,13 +1,13 @@
12
0.0336404
0.81687707
-0.088157885
1.072176
-0.019678842
-0.23005776
2.6509802
2.31109
2.8000503
-0.044337805
-0.20568089
2.5650184
-0.6611704
1.472362
-0.059240177
0.6448027
-0.09498331
0.07005496
1.5227689
1.6761788
1.3155555
3.944478
0.41402242
1.6400838

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +1,31 @@
20
-0.19178796
-0.0275628
0.45375344
2.1090505
-0.012145723
0.2213703
2.624133
-0.82816005
0.25926802
-0.014570757
0.72068256
0.249013
2.195925
-0.014568891
-0.59766585
-0.020068042
-0.05986349
-1.3474371
-0.49981204
0.6370428
30
-0.7973528
-0.16212165
-0.016621558
-0.010184621
-0.02323284
-0.65347326
0.3813474
-0.01980829
0.014691165
0.84623796
1.0044321
0.9791296
0.09865961
0.32203308
0.008520375
-0.27646253
-0.034938164
-0.0024497542
-0.035473134
0.28444487
-0.7223666
-0.43071944
-0.27131405
0.18943691
-0.7551859
0.22790527
-0.19145727
0.3364544
0.8732161
0.93184555

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +1,16 @@
15
1.8846483
0.426767
-0.43499732
-0.86950755
-1.4404491
-1.6620952
0.43332458
-0.047994245
-0.8123727
0.097763464
-0.61916274
0.20783848
-1.0543438
0.42724028
0.7927464
0.74399966
0.65725124
0.28723997
-0.28500625
-0.6551816
-0.5096106
0.6995224
0.47489655
-0.637414
-0.14589947
-0.6946489
0.06361784
-0.9587668
0.33230728
0.01565033

View File

@@ -1,302 +1,452 @@
20
30
15
3.1785574e-34
1.5611281e-34
-1.5863359e-34
-2.1766939e-34
-2.3130055e-34
-2.662751e-34
-3.2626066e-34
2.8627675e-34
2.7861122e-34
-2.9668104e-34
3.0360296e-34
2.9419657e-34
3.1102713e-34
-2.8726263e-34
3.0484892e-34
4.3197746e-34
-1.8445088e-34
-3.530525e-34
-3.5233124e-34
2.2262768e-34
1.2378974e-34
3.7615624e-34
-2.2716454e-34
2.5169786e-34
-3.353324e-34
3.5685113e-34
-4.122433e-34
1.7969215e-34
5.2897058e-34
2.3318663e-34
0.022835148
-0.029413782
-0.12952074
0.18896067
-0.06554771
0.11628288
-0.06948121
-0.025129182
0.009227986
-0.10632306
0.21482462
-0.09871392
0.089015536
-0.008572652
-0.028414002
0.08512151
-0.21057208
0.12899724
-0.121678144
-0.044324484
0.012617375
0.23971003
-0.029345443
-0.10093057
0.13569276
-0.05262047
-0.057448562
-0.057186298
0.22441685
-0.09055193
-2.5289643e-34
1.7009551e-34
-3.9381888e-36
2.326881e-34
-2.8111998e-34
-3.5335243e-35
-1.1998445e-34
-3.4805974e-34
1.8599213e-34
-1.7831123e-34
1.1460405e-34
2.0934657e-34
1.563032e-34
-1.0113456e-35
2.4719906e-35
-0.12601055
0.19141342
-0.069146484
-0.0025679446
-0.11021721
-0.047209635
0.121572815
-0.021320255
0.17498343
-0.07666946
-0.03474931
-0.053848345
0.038261224
0.09783123
-0.04364654
0.2465007
0.1849186
-0.052974403
-0.064460956
-0.0467655
-0.036299426
-0.08964782
-0.022229096
0.20783813
-0.08701921
-0.021651257
-0.007302513
-0.08308651
-0.07215878
-0.0007826862
-6.1247035e-34
4.463276e-34
5.4647075e-34
-5.3594374e-34
-7.624689e-35
4.547081e-34
-4.9066397e-34
-3.6748373e-34
-5.033634e-34
5.2652385e-34
-5.817056e-34
-4.3149362e-34
5.304378e-34
5.2734927e-34
4.9347583e-34
0.057774916
0.091525115
0.14736745
0.13339345
0.15654251
0.09139076
0.12214476
0.106167495
-0.1375304
-0.11402692
-0.07316204
-0.08932755
-0.11316809
-0.10894508
-0.12546284
-3.2000347e-34
-2.36952e-34
-2.2271435e-34
2.732874e-34
-2.5469592e-34
2.4332584e-34
2.4015109e-34
2.305403e-34
-1.0759744e-34
1.7449821e-34
-2.3276338e-34
-1.6425085e-34
2.3379538e-34
-1.2265797e-35
-2.2131944e-34
-0.007536282
-0.015670829
-0.044145193
-0.06925844
-0.038289294
0.04218386
-0.028006999
0.19194373
-0.008162281
-0.04310273
-0.032295864
-0.013634144
0.012049367
-0.04765994
0.15002576
0.028484903
-0.12657242
-0.10019828
-0.021912435
-0.07220948
-0.07850285
-0.11347996
-0.084765114
0.099906415
0.07358634
0.085178904
0.04134392
0.09367139
0.11517161
0.15800452
0.2303931
-0.04586972
-0.08725446
-0.033236336
0.1308958
-0.036943685
-0.014320934
-0.0052397517
-0.013388744
-0.024721963
-0.05172364
0.03730736
-0.02536234
-0.04374987
-0.033061035
-0.0024779101
0.000728523
3.03098e-06
-0.0006537406
0.0014257621
7.1307574e-07
2.82788e-05
-1.4571673e-08
-9.1665876e-05
-0.0005169288
-0.00088055246
0.0009669605
0.0002642583
7.58049e-06
5.0228886e-05
4.1370527e-34
-2.3665282e-34
2.6231246e-34
3.7994393e-34
4.0085556e-34
-2.6690339e-34
1.8781805e-34
-1.982984e-34
-3.0113217e-34
-2.1200167e-34
-2.0077406e-35
3.0132427e-34
-3.0806865e-34
-1.9560212e-34
1.2020748e-34
4.1127485e-34
-3.2173455e-34
4.0228943e-34
-3.1162013e-34
-5.1426757e-34
2.6755438e-34
3.6094879e-34
-4.8759634e-34
3.4464383e-34
-2.8995517e-34
-3.1393783e-34
-2.2658088e-34
-3.3108237e-34
-1.3505708e-35
2.4738205e-34
3.783955e-34
3.6061226e-34
3.193828e-34
3.7868991e-34
3.6567402e-34
-3.0349225e-34
3.3677782e-34
2.8857424e-34
2.5269046e-34
2.2737943e-34
-2.65504e-34
-2.732385e-34
2.6953094e-34
2.9642443e-34
2.6588915e-34
-0.07233555
-0.030644806
0.014339875
0.010646929
0.15107094
-0.04039454
-0.1018803
-0.024136122
0.013392502
-0.0011950728
0.06232135
0.20024493
-0.06713317
-0.08364978
-0.010007126
0.073318966
0.0020213877
0.015295026
-0.09381448
0.018438634
0.15810835
-0.122952715
-0.06948898
-0.03245277
-0.07937658
-0.074316666
0.14917618
0.21517377
-0.07048892
-0.060168184
0.02568059
-0.04876075
0.19848819
0.073280066
-0.09127431
-0.040448762
-0.11075618
-0.0018404849
-0.04922203
0.22584344
0.08676703
0.023621265
-0.02429366
-0.13942361
-0.047222435
0.01272495
-0.10762496
0.029348347
0.043351036
0.014999958
-0.06224802
-0.023997843
0.02832638
-0.041784886
0.0986206
0.071423925
0.071765825
-0.0512679
-0.044301357
-0.013093688
-0.11556479
0.03982802
0.09731361
0.00295955
-0.03545694
-0.006381662
0.02806398
0.0045560263
0.05397426
0.03402133
-0.036305163
-0.043878928
-0.0142929
0.017667498
-0.025763642
4.463302e-34
7.2691345e-34
8.845337e-34
1.0892352e-33
4.7136717e-34
8.0413215e-35
9.200099e-34
-4.0106226e-36
4.1104475e-34
5.224466e-35
2.8301181e-34
-8.116642e-34
-3.1305442e-34
-2.6887943e-34
-2.190287e-34
-1.0852689e-33
-3.8716697e-34
-3.4582993e-34
4.0845394e-34
-4.580933e-34
-5.545946e-34
-6.0027574e-34
8.783881e-34
1.1282351e-33
2.8688931e-34
-6.931309e-34
-7.412748e-34
6.843897e-34
-1.07383705e-33
-4.422186e-34
4.9493538e-34
-3.3879648e-34
-2.5583285e-34
-9.684053e-38
1.1755804e-33
5.0118e-34
-6.8979133e-35
5.570329e-34
2.0730477e-34
-6.9826827e-35
1.7651477e-34
6.505341e-34
1.1404848e-33
3.768194e-36
-8.696617e-34
1.6646721e-33
1.5833977e-33
-1.16577035e-33
1.3946439e-33
-1.6903357e-33
1.18764e-33
-1.4414919e-33
1.4874023e-33
-1.4271845e-33
-1.5428872e-33
-1.5855378e-33
-1.5143901e-33
1.4189191e-33
-1.4440388e-33
1.333818e-33
0.17302258
-0.027978221
0.016748061
-0.059101477
-0.02370323
0.055812847
-0.027396126
0.0083711
-0.019884026
-0.02066343
-0.005153278
-0.010312685
0.029041208
-0.050187044
-0.024670767
-2.6037262e-33
-2.611591e-33
2.4881792e-33
2.7212167e-33
-2.5234833e-33
-2.2103461e-33
1.9122722e-33
9.588927e-34
2.7108281e-33
-2.3352854e-33
-2.7606323e-33
-2.5427623e-33
2.6146137e-33
2.4776098e-33
2.5404514e-33
0.06246555
0.10426002
-0.052243777
0.017077662
-0.03715354
-0.018698398
-0.06796197
0.03528635
0.06418046
-0.000768907
-0.026170308
-0.019549962
0.054662388
-0.044521194
-0.07334332
0.04758694
-0.08954524
0.09964462
-0.031682633
-0.015182594
-0.039172467
0.07632043
-0.01974726
-0.08796382
0.087372005
-0.016114255
-0.025341872
-0.021241697
0.075716406
-0.027058382
-0.015432766
0.0073655327
-0.01209919
-0.041824125
-0.006816338
0.0045526098
-0.0005398891
0.13293515
-0.014088044
-0.04277335
-0.046146225
-0.011611434
-0.013375685
-0.017687852
0.099150814
0.035996642
0.016294181
-0.08048032
-0.041648608
-0.012340834
-0.024473786
0.16153657
-0.026676055
0.04658439
-0.052000005
-0.026849354
-0.03671153
-0.03710232
0.1337519
-0.031022256
-0.01850948
0.01128599
0.090702474
-0.008731814
-0.00024545888
-0.010025267
-0.039491266
-0.020047752
0.034077633
0.019151518
-0.017094668
-0.01866218
-0.017035574
0.005504165
-0.0069074775
-0.00089758425
-0.0016957085
0.00025294858
-0.002470556
-0.00253977
-0.0026819948
-0.001282234
-0.0027133073
0.0060566748
-0.0017536315
-0.0004967247
-0.004892902
0.0044350573
-0.0026093745
0.003550591
0.04047877
0.05901869
0.043092217
0.08706535
0.077308305
0.044446126
0.051501554
0.017045613
-0.056876663
-0.051144525
-0.050281346
-0.011186705
-0.055486917
-0.0782539
-0.0805333
-0.043732617
-0.0068375436
-0.03201547
-0.059948742
0.05957991
0.067795284
-0.04184092
0.004160195
0.008685335
-0.054342967
-0.033768225
0.11686653
0.081372775
-0.017015154
-0.023423227
8.78021e-34
8.345785e-34
7.4883407e-34
8.48771e-34
8.274504e-34
8.027745e-34
8.773579e-34
8.519454e-34
-8.11835e-34
-7.688669e-34
8.082543e-34
-7.3258576e-34
-8.51516e-34
7.221161e-34
7.827067e-34
1.2615198e-33
1.0976719e-33
1.1967251e-33
-1.0436973e-33
-8.499446e-34
2.2683726e-34
-1.3970104e-33
1.5193663e-33
1.2094788e-33
-1.133173e-33
-1.2547036e-33
-1.4050951e-33
-1.4054403e-33
-1.142544e-33
1.0450027e-33
7.6956433e-34
8.744477e-34
-3.8514544e-35
4.8746516e-34
-9.3443655e-34
-1.3859844e-34
-1.2412909e-34
-1.6619894e-34
-1.0620242e-33
1.4781585e-34
-7.03722e-34
6.034873e-34
4.964442e-34
6.136231e-34
8.249319e-34
0.008318748
0.041124124
-0.016857537
-0.04932119
-0.0122754285
0.10398687
-0.015096632
-0.0022395186
-0.015617358
0.036401253
-0.060664278
0.010920629
0.053897887
-0.030621164
-0.030898456
-0.032895576
-0.102701336
-0.026651151
0.11469333
-0.063634604
0.06844623
-0.018467609
0.00821091
-0.07843062
-0.0055042044
0.090303816
-0.046396058
0.075963
0.03063942
0.020872513
-0.01299387
-0.0037207452
-0.0242024
0.06550928
-0.024706954
0.014491363
-0.011790568
-0.0025269324
-0.004879747
-0.030484857
0.0600873
-0.023517173
0.03269997
0.0051519005
-0.012163694
1.1904957e-33
1.0479699e-33
5.779416e-34
1.1540947e-33
-9.659636e-34
-1.0160334e-33
-8.223222e-34
8.918577e-34
1.0935816e-33
-9.294705e-34
-1.1592887e-33
9.246344e-34
1.180318e-33
-9.126836e-34
1.1287711e-33
0.026146693
0.09916242
-0.043090336
0.0017119434
0.0016878549
-0.017987054
-0.049805358
-0.022761522
0.092246346
-0.040928245
0.06459246
-0.017492786
-0.0049494132
-0.04219089
-0.03418938
-1.7006182e-33
-1.4530463e-33
1.42898475e-33
1.5074225e-33
-1.3642416e-33
-1.4290173e-33
1.4108531e-33
-1.2353524e-33
1.5234947e-33
-1.3775423e-33
1.4153025e-33
1.3714305e-33
-1.484371e-33
-1.44253985e-33
1.3046794e-33
0.044514116
-0.000882356
-0.0096916985
-0.04236413
0.091675386
-0.023483241
0.014011558
-0.004130279
-0.036856808
-0.033731807
-0.012403026
0.002606612
0.017260972
0.015992519
-0.015452466
0.07528171
-0.021592995
-0.06897829
0.0042408453
-0.027098294
-0.06743852
-0.09114424
-0.10261911
0.10710511
0.049893394
0.059722904
0.04513747
0.053101413
0.041433763
0.09596609
0.09589958
-0.025171956
-0.0013778559
-0.016897377
-0.022183804
-0.00023300173
-0.0065004122
0.0055662235
-0.014621925
0.0004447254
0.00226211
-0.011209562
-0.0183207
-0.011526959
0.005361926
0.17491823
-0.018875118
0.03126051
-0.039963342
-0.033307772
0.0015879893
-0.041357704
-0.0036194928
-0.03158664
-0.004237409
-0.034398682
-0.017561572
0.023918597
-0.0046276804
-0.011843316
0.023838982
0.11698544
-0.036167253
-0.019597769
-0.012699235
-0.012540517
-0.03393306
-0.0059446017
-0.00016750683
0.0014437584
-0.0015821535
-0.0019046782
-0.0021211132
-0.02051653
-0.008041249