反小陀螺前置代码已完成。

This commit is contained in:
xinyang
2019-07-16 16:31:58 +08:00
parent 298c4c9114
commit 73230d91f1
24 changed files with 18873 additions and 18675 deletions

View File

@@ -13,8 +13,11 @@
#include <armor_finder/classifier/classifier.h> #include <armor_finder/classifier/classifier.h>
#include <additions/additions.h> #include <additions/additions.h>
#define BLOB_RED ENEMY_RED #define BLOB_RED ENEMY_RED
#define BLOB_BLUE ENEMY_BLUE #define BLOB_BLUE ENEMY_BLUE
#define BOX_RED ENEMY_RED
#define BOX_BLUE ENEMY_BLUE
#define DISTANCE_HEIGHT_5MM (113.0) // 单位: m*pixel #define DISTANCE_HEIGHT_5MM (113.0) // 单位: m*pixel
#define DISTANCE_HEIGHT DISTANCE_HEIGHT_5MM #define DISTANCE_HEIGHT DISTANCE_HEIGHT_5MM
@@ -22,21 +25,53 @@
extern std::map<int, string> id2name; //装甲板id到名称的map extern std::map<int, string> id2name; //装甲板id到名称的map
extern std::map<string, int> name2id; //装甲板名称到id的map extern std::map<string, int> name2id; //装甲板名称到id的map
/******************* 灯条类定义 ***********************/ /******************* 灯条类定义 ***********************/
class LightBlob { class LightBlob {
public: public:
cv::RotatedRect rect; //灯条位置 cv::RotatedRect rect; //灯条位置
double length; //灯条长度 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); length = max(rect.size.height, rect.size.width);
}; };
LightBlob() = default;
}; };
typedef std::vector<LightBlob> LightBlobs; typedef std::vector<LightBlob> LightBlobs;
/******************* 装甲板类定义 **********************/
class ArmorBox{
public:
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 blobsDistance() 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));
}
}
double lengthDistanceRatio() const {
if(light_blobs.size() == 2){
return (light_blobs[0].length+light_blobs[1].length)/2.0
/ blobsDistance();
}else{
return 100;
}
}
};
typedef std::vector<ArmorBox> ArmorBoxes;
/********************* 自瞄类定义 **********************/ /********************* 自瞄类定义 **********************/
class ArmorFinder{ class ArmorFinder{
public: public:
@@ -50,11 +85,9 @@ private:
SEARCHING_STATE, TRACKING_STATE, STANDBY_STATE SEARCHING_STATE, TRACKING_STATE, STANDBY_STATE
} State; // 自瞄状态枚举定义 } State; // 自瞄状态枚举定义
cv::Mat src_raw; // 当前原图
const uint8_t &enemy_color; // 敌方颜色,引用外部变量,自动变化 const uint8_t &enemy_color; // 敌方颜色,引用外部变量,自动变化
State state; // 自瞄状态对象实例 State state; // 自瞄状态对象实例
cv::Rect2d armor_box; // 当前目标位置 ArmorBox armor_box; // 当前目标装甲板
int boxid; // 当前目标id
cv::Ptr<cv::Tracker> tracker; // tracker对象实例 cv::Ptr<cv::Tracker> tracker; // tracker对象实例
Classifier classifier; // CNN分类器对象实例用于数字识别 Classifier classifier; // CNN分类器对象实例用于数字识别
int contour_area; // 装甲区域亮点个数,用于数字识别未启用时判断是否跟丢(已弃用) int contour_area; // 装甲区域亮点个数,用于数字识别未启用时判断是否跟丢(已弃用)
@@ -62,15 +95,15 @@ private:
Serial &serial; // 串口对象,引用外部变量,用于和能量机关共享同一个变量 Serial &serial; // 串口对象,引用外部变量,用于和能量机关共享同一个变量
const uint8_t &use_classifier; // 标记是否启用CNN分类器引用外部变量自动变化 const uint8_t &use_classifier; // 标记是否启用CNN分类器引用外部变量自动变化
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 stateSearchingTarget(cv::Mat &src); // searching state主函数
bool stateTrackingTarget(cv::Mat &src); // tracking state主函数 bool stateTrackingTarget(cv::Mat &src); // tracking state主函数
bool stateStandBy(); // stand by state主函数已弃用 bool stateStandBy(); // stand by state主函数已弃用
bool findLightBlobs(const cv::Mat &src_bin, // 在二值图上寻找灯条 void anti_top(); // 反小陀螺
LightBlobs &light_blobs);
bool findArmorBoxes(const LightBlobs &light_blobs, // 根据灯条匹配装甲板候选区
std::vector<cv::Rect2d> &armor_boxes);
public: public:
void run(cv::Mat &src); // 自瞄主函数 void run(cv::Mat &src); // 自瞄主函数
bool sendBoxPosition(); // 和主控板通讯 bool sendBoxPosition(); // 和主控板通讯

View File

@@ -9,9 +9,10 @@
#include <armor_finder/armor_finder.h> #include <armor_finder/armor_finder.h>
// //
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);
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 &armor_box);
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);
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[15]);
void showTrackSearchingPos(std::string window_names, const cv::Mat &src, const cv::Rect2d pos);
#endif /* _SHOW_IMAGES_H_ */ #endif /* _SHOW_IMAGES_H_ */

View File

@@ -0,0 +1,52 @@
//
// Created by xinyang on 19-7-15.
//
#include <armor_finder/armor_finder.h>
#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
void ArmorFinder::anti_top() {
// switch (armor_box.id) {
// case R1:
// case R7:
// case B1:
// case B7:
// if (armor_box.rect != cv::Rect2d()) {
// sendBoxPosition();
// }
// case R2:
// case R3:
// case R4:
// case R5:
// case B2:
// case B3:
// case B4:
// case B5:
// if (armor_box.rect != cv::Rect2d()) {
// sendBoxPosition();
// }
// default:
// if (armor_box.rect != cv::Rect2d()) {
// sendBoxPosition();
// }
// }
if (armor_box.rect != cv::Rect2d()) {
sendBoxPosition();
}
}

View File

@@ -0,0 +1,212 @@
//
// Created by xinyang on 19-7-13.
//
#include <armor_finder/armor_finder.h>
#include <show_images/show_images.h>
#include <options/options.h>
#include <opencv2/highgui.hpp>
#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",
};
ArmorBox::ArmorBox(const cv::Rect &pos, const LightBlobs &blobs, uint8_t color, int i) :
rect(pos), light_blobs(blobs), box_color(color), id(i){};
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;
}
static bool heightJudge(const LightBlob &light_blob_i, const LightBlob &light_blob_j) {
cv::Point2f centers = light_blob_i.rect.center - light_blob_j.rect.center;
return abs(centers.y) < 30;
}
static bool lengthJudge(const LightBlob &light_blob_i, const LightBlob &light_blob_j) {
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);
}
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);
}
/* 判断两个灯条的错位度,不知道英文是什么!!! */
static bool CuoWeiDuJudge(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;
float angle = (angle_i + angle_j) / 2.0 / 180.0 * 3.14159265459;
if (abs(angle_i - angle_j) > 90) {
angle += 3.14159265459 / 2;
}
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;
}
static bool boxAngleJudge(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;
float angle = (angle_i + angle_j) / 2.0;
if (abs(angle_i - angle_j) > 90) {
angle += 90.0;
}
return (-120.0 < angle && angle < -60.0) || (60.0 < angle && angle < 120.0);
}
static bool isCoupleLight(const LightBlob &light_blob_i, const LightBlob &light_blob_j, uint8_t enemy_color) {
// cout << (light_blob_i.blob_color==BLOB_RED) << endl;
// cout << (light_blob_j.blob_color==BLOB_RED) << endl;
// cout << lengthRatioJudge(light_blob_i, light_blob_j) << endl;
// cout << lengthJudge(light_blob_i, light_blob_j) << endl;
//// cout << heightJudge(light_blob_i, light_blob_j) << endl;
// cout << angelJudge(light_blob_i, light_blob_j) << endl;
// cout << boxAngleJudge(light_blob_i, light_blob_j) << endl;
// cout << CuoWeiDuJudge(light_blob_i, light_blob_j) << endl;
// cout << "=============" << endl;
return light_blob_i.blob_color == enemy_color &&
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) &&
angelJudge(light_blob_i, light_blob_j) &&
boxAngleJudge(light_blob_i, light_blob_j) &&
CuoWeiDuJudge(light_blob_i, light_blob_j);
}
static double centerDistance(const cv::Rect2d &box) {
double dx = box.x - box.width / 2 - 320;
double dy = box.y - box.height / 2 - 240;
return dx * dx + dy * dy;
}
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), color)) {
// cout << "match fail" << endl;
continue;
}
cv::Rect2d rect_left = light_blobs.at(static_cast<unsigned long>(i)).rect.boundingRect();
cv::Rect2d rect_right = light_blobs.at(static_cast<unsigned long>(j)).rect.boundingRect();
double min_x, min_y, max_x, max_y;
min_x = fmin(rect_left.x, rect_right.x) - 4;
max_x = fmax(rect_left.x + rect_left.width, rect_right.x + rect_right.width) + 4;
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 > src.cols || min_y < 0 || max_y > src.rows) {
// cout << "out of range" << endl;
continue;
}
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 false;
}
sort(armor_boxes.begin(), armor_boxes.end(), [](ArmorBox box1, ArmorBox box2) -> bool {
return centerDistance(box1.rect) < centerDistance(box2.rect);
});
return true;
}
bool ArmorFinder::findArmorBox(const cv::Mat &src, ArmorBox &box){
LightBlobs light_blobs; // 存储所有可能的灯条
ArmorBoxes armor_boxes; // 装甲板候选区
ArmorBoxes boxes_number[15]; // 装甲板候选区放置在对应id位置
box.rect = cv::Rect2d(0,0,0,0);
box.id = -1;
if (!findLightBlobs(src, light_blobs)) {
return false;
}
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;
boxes_number[c].emplace_back(armor_box);
}
if (enemy_color == ENEMY_BLUE) {
for (auto &name : prior_blue) {
if (!boxes_number[name2id[name]].empty()) {
box = boxes_number[name2id[name]][0];
break;
}
}
} else if (enemy_color == ENEMY_RED) {
for (auto &name : prior_red) {
if (!boxes_number[name2id[name]].empty()) {
box = boxes_number[name2id[name]][0];
break;
}
}
} else {
LOGE_INFO("enemy_color ERROR!");
}
if (save_labelled_boxes) {
for (int i = 0; i < sizeof(boxes_number) / sizeof(boxes_number[0]); i++) {
for (auto &armor_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(armor_box.rect));
}
}
}
if (box.rect == cv::Rect2d(0, 0, 0, 0)) {
return false;
}
if (show_armor_boxes && src.size()==cv::Size(640, 480)) {
showArmorBoxesClass("class", src, boxes_number);
}
} else {
box = armor_boxes[0];
}
return true;
}

View File

@@ -0,0 +1,136 @@
//
// Created by xinyang on 19-7-10.
//
#include <armor_finder/armor_finder.h>
#include <opencv2/highgui.hpp>
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;
}
static double areaRatio(const std::vector<cv::Point> &contour, const cv::RotatedRect &rect){
return cv::contourArea(contour) / rect.size.area();
}
static bool isValidLightBlob(const std::vector<cv::Point> &contour, const cv::RotatedRect &rect) {
return (lw_rate(rect) > 1.5) &&
// (rect.size.area() < 3000) &&
(rect.size.area() > 5) &&
(areaRatio(contour, rect) > 0.7);
}
// 此函数可以有性能优化.
static uint8_t get_blob_color(const cv::Mat &src, const cv::RotatedRect &blobPos) {
auto region = blobPos.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, src.cols, src.rows);
cv::Mat roi = src(region);
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) {
return BLOB_RED;
} else {
return BLOB_BLUE;
}
}
static float 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 get_blob_color_opt(const cv::Mat &src, cv::RotatedRect blobPos) {
int blue_cnt=0, red_cnt=0;
blobPos.size.height *= 1.05;
blobPos.size.width *= 1.1;
cv::Point2f corners[4];
blobPos.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++) {
red_cnt += src.at<cv::Vec3b>(r, c)[2];
blue_cnt += src.at<cv::Vec3b>(r, c)[0];
}
}
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++) {
red_cnt += src.at<cv::Vec3b>(r, c)[2];
blue_cnt += src.at<cv::Vec3b>(r, c)[0];
}
}
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++) {
red_cnt += src.at<cv::Vec3b>(r, c)[2];
blue_cnt += src.at<cv::Vec3b>(r, c)[0];
}
}
if (red_cnt > blue_cnt) {
return BLOB_RED;
} else {
return BLOB_BLUE;
}
}
static 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::findLightBlobs(const cv::Mat &src, LightBlobs &light_blobs) {
cv::Mat src_bin, color_channel;
std::vector<cv::Mat> channels; // 通道拆分
cv::split(src, channels); /************************/
if (enemy_color == ENEMY_BLUE) /* */
color_channel = channels[0]; /* 根据目标颜色进行通道提取 */
else if (enemy_color == ENEMY_RED) /* */
color_channel = channels[2]; /************************/
cv::threshold(color_channel, src_bin, 160, 255, CV_THRESH_BINARY); // 二值化对应通道
imagePreProcess(src_bin); // 开闭运算
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(light_contour, rect)) {
light_blobs.emplace_back(rect, get_blob_color(src, rect));
}
}
return light_blobs.size() >= 2;
}

View File

@@ -42,32 +42,25 @@ ArmorFinder::ArmorFinder(uint8_t &color, Serial &u, const string &paras_folder,
classifier(paras_folder), classifier(paras_folder),
contour_area(0), contour_area(0),
use_classifier(use), use_classifier(use),
boxid(-1),
tracking_cnt(0) { tracking_cnt(0) {
} }
void ArmorFinder::run(cv::Mat &src) { 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 // stateSearchingTarget(src_use); // for debug
// return; // return;
switch (state) { switch (state) {
case SEARCHING_STATE: case SEARCHING_STATE:
if (stateSearchingTarget(src_use)) { if (stateSearchingTarget(src)) {
if ((armor_box & cv::Rect2d(0, 0, 640, 480)) == armor_box) { // 判断装甲板区域是否脱离图像区域 // cout << armor_box.rect << endl;
if ((armor_box.rect & cv::Rect2d(0, 0, 640, 480)) == armor_box.rect) { // 判断装甲板区域是否脱离图像区域
if (!classifier || !use_classifier) { /* 如果分类器不可用或者不使用分类器 */ 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::cvtColor(roi, roi_gray, CV_RGB2GRAY);
cv::threshold(roi_gray, roi_gray, 180, 255, cv::THRESH_BINARY); cv::threshold(roi_gray, roi_gray, 180, 255, cv::THRESH_BINARY);
contour_area = cv::countNonZero(roi_gray); contour_area = cv::countNonZero(roi_gray);
} }
tracker = TrackerToUse::create(); // 成功搜寻到装甲板创建tracker对象 tracker = TrackerToUse::create(); // 成功搜寻到装甲板创建tracker对象
tracker->init(src_use, armor_box); tracker->init(src, armor_box.rect);
state = TRACKING_STATE; state = TRACKING_STATE;
tracking_cnt = 0; tracking_cnt = 0;
LOGM(STR_CTR(WORD_LIGHT_CYAN, "into track")); LOGM(STR_CTR(WORD_LIGHT_CYAN, "into track"));
@@ -75,7 +68,7 @@ void ArmorFinder::run(cv::Mat &src) {
} }
break; break;
case TRACKING_STATE: case TRACKING_STATE:
if (!stateTrackingTarget(src_use) || ++tracking_cnt > 100) { // 最多追踪100帧图像 if (!stateTrackingTarget(src) || ++tracking_cnt > 100) { // 最多追踪100帧图像
state = SEARCHING_STATE; state = SEARCHING_STATE;
LOGM(STR_CTR(WORD_LIGHT_YELLOW, "into search!")); LOGM(STR_CTR(WORD_LIGHT_YELLOW, "into search!"));
} }
@@ -84,5 +77,12 @@ void ArmorFinder::run(cv::Mat &src) {
default: default:
stateStandBy(); stateStandBy();
} }
anti_top();
if (show_armor_box) { // 根据条件显示当前目标装甲板
showArmorBox("box", src, armor_box);
cv::waitKey(1);
}
} }

View File

@@ -1,105 +0,0 @@
//
// Created by xinyang on 19-7-10.
//
#include <armor_finder/armor_finder.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;
}
static bool heightJudge(const LightBlob &light_blob_i, const LightBlob &light_blob_j) {
cv::Point2f centers = light_blob_i.rect.center - light_blob_j.rect.center;
return abs(centers.y) < 30;
}
static bool lengthJudge(const LightBlob &light_blob_i, const LightBlob &light_blob_j) {
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);
}
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);
}
/* 判断两个灯条的错位度,不知道英文是什么!!! */
static bool CuoWeiDuJudge(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;
float angle = (angle_i + angle_j) / 2.0 / 180.0 * 3.14159265459;
if (abs(angle_i - angle_j) > 90) {
angle += 3.14159265459 / 2;
}
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;
}
static bool boxAngleJudge(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;
float angle = (angle_i + angle_j) / 2.0;
if (abs(angle_i - angle_j) > 90) {
angle += 90.0;
}
return (-120.0 < angle && angle < -60.0) || (60.0 < angle && angle < 120.0);
}
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 &&
lengthRatioJudge(light_blob_i, light_blob_j) &&
lengthJudge(light_blob_i, light_blob_j) &&
// heightJudge(light_blob_i, light_blob_j) &&
angelJudge(light_blob_i, light_blob_j) &&
boxAngleJudge(light_blob_i, light_blob_j) &&
CuoWeiDuJudge(light_blob_i, light_blob_j);
}
static double centerDistance(const cv::Rect2d &box) {
double dx = box.x - box.width / 2 - 320;
double dy = box.y - box.height / 2 - 240;
return dx * dx + dy * dy;
}
bool ArmorFinder::findArmorBoxes(const LightBlobs &light_blobs, std::vector<cv::Rect2d> &armor_boxes) {
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)) {
continue;
}
cv::Rect2d rect_left = light_blobs.at(static_cast<unsigned long>(i)).rect.boundingRect();
cv::Rect2d rect_right = light_blobs.at(static_cast<unsigned long>(j)).rect.boundingRect();
double min_x, min_y, max_x, max_y;
min_x = fmin(rect_left.x, rect_right.x) - 4;
max_x = fmax(rect_left.x + rect_left.width, rect_right.x + rect_right.width) + 4;
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) {
continue;
}
armor_boxes.emplace_back(cv::Rect2d(min_x, min_y, max_x - min_x, max_y - min_y));
}
}
if (armor_boxes.empty()) {
return false;
}
sort(armor_boxes.begin(), armor_boxes.end(), [](cv::Rect2d box1, cv::Rect2d box2) -> bool {
return centerDistance(box1) < centerDistance(box2);
});
return true;
}

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 <armor_finder/armor_finder.h>
#include <opencv2/highgui.hpp>
#include <show_images/show_images.h> #include <show_images/show_images.h>
#include <options/options.h> #include <options/options.h>
#include <log.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) { bool ArmorFinder::stateSearchingTarget(cv::Mat &src) {
std::vector<cv::Mat> channels; // 通道拆分 if(findArmorBox(src, armor_box)){
cv::Mat src_bin, color; // 二值图和颜色通道图 return true;
LightBlobs light_blobs; // 存储所有可能的灯条 }else{
std::vector<cv::Rect2d> armor_boxes; // 装甲板候选区 armor_box = ArmorBox();
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)) {
return false; 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

@@ -35,7 +35,7 @@ static bool sendTarget(Serial &serial, double x, double y, double z) {
} }
bool ArmorFinder::sendBoxPosition() { bool ArmorFinder::sendBoxPosition() {
auto rect = armor_box; auto rect = armor_box.rect;
double dx = rect.x + rect.width / 2 - 320; double dx = rect.x + rect.width / 2 - 320;
double dy = rect.y + rect.height / 2 - 240 - 20; double dy = rect.y + rect.height / 2 - 240 - 20;
double yaw = atan(dx / FOCUS_PIXAL) * 180 / PI; double yaw = atan(dx / FOCUS_PIXAL) * 180 / PI;

View File

@@ -2,30 +2,76 @@
// Created by xinyang on 19-3-27. // Created by xinyang on 19-3-27.
// //
#include <log.h> #include <log.h>
#include <options/options.h>
#include <armor_finder/armor_finder.h> #include <armor_finder/armor_finder.h>
#include <show_images/show_images.h>
bool ArmorFinder::stateTrackingTarget(cv::Mat &src) { 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; 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; return false;
} }
cv::Mat roi = src.clone()(armor_box); cv::Rect2d bigger_rect;
if(classifier){
cv::resize(roi, roi, cv::Size(48, 36)); bigger_rect.x = pos.x - pos.width / 2.0;
if(classifier(roi) == 0){ bigger_rect.y = pos.y - pos.height / 2.0;
return false; 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{ }else{
cv::Mat roi_gray; roi = src(pos).clone();
cv::cvtColor(roi, roi_gray, CV_RGB2GRAY); if(classifier){
cv::threshold(roi_gray, roi_gray, 180, 255, cv::THRESH_BINARY); cv::resize(roi, roi, cv::Size(48, 36));
contour_area = cv::countNonZero(roi_gray); if(classifier(roi) == 0){
if(abs(cv::countNonZero(roi_gray) - contour_area) > contour_area * 0.3){ armor_box = ArmorBox();
return false; 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 <show_images/show_images.h>
#include <opencv2/highgui.hpp> #include <opencv2/highgui.hpp>
#include <options/options.h>
#include <log.h> #include <log.h>
using namespace cv; 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; static Mat image2show;
if (src.type() == CV_8UC1) {// 黑白图像 if (src.type() == CV_8UC1) {// 黑白图像
cvtColor(src, image2show, COLOR_GRAY2RGB); cvtColor(src, image2show, COLOR_GRAY2RGB);
@@ -15,8 +32,15 @@ void showArmorBoxVector(std::string windows_name, const cv::Mat &src, const std:
image2show = src.clone(); image2show = src.clone();
} }
for (auto &box:armor_box) { for (auto &box:armor_boxes) {
rectangle(image2show, box, Scalar(0, 255, 0), 1); 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); imshow(windows_name, image2show);
} }
@@ -24,25 +48,26 @@ 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[15]) {
static Mat image2show; static Mat image2show;
if (src.type() == CV_8UC1) { // 黑白图像 if (src.type() == CV_8UC1) { // 黑白图像
cvtColor(src, image2show, COLOR_GRAY2RGB); cvtColor(src, image2show, COLOR_GRAY2RGB);
} else if (src.type() == CV_8UC3) { //RGB 彩色 } else if (src.type() == CV_8UC3) { //RGB 彩色
image2show = src.clone(); image2show = src.clone();
} }
for (int i = 0; i < 14; i++) { for (int i = 1; i < 15; i++) {
if (!boxes[i].empty()) { if (!boxes[i].empty()) {
for (auto box : boxes[i]) { for (auto box : boxes[i]) {
rectangle(image2show, box, Scalar(0, 255, 0), 1); rectangle(image2show, box.rect, Scalar(0, 255, 0), 1);
drawLightBlobs(image2show, box.light_blobs);
if (i == -1) if (i == -1)
putText(image2show, id2name[i], Point(box.x + 2, box.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1, putText(image2show, id2name[i], Point(box.rect.x + 2, box.rect.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
Scalar(0, 255, 0)); Scalar(0, 255, 0));
else if (1 <= i && i < 8) else if (1 <= i && i < 8)
putText(image2show, id2name[i], Point(box.x + 2, box.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1, putText(image2show, id2name[i], Point(box.rect.x + 2, box.rect.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
Scalar(255, 0, 0)); Scalar(255, 0, 0));
else if (8 <= i && i < 15) else if (8 <= i && i < 15)
putText(image2show, id2name[i], Point(box.x + 2, box.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1, putText(image2show, id2name[i], Point(box.rect.x + 2, box.rect.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
Scalar(0, 0, 255)); Scalar(0, 0, 255));
else if (i != 0) else if (i != 0)
LOGE_INFO("Invalid box id:%d!", i); LOGE_INFO("Invalid box id:%d!", i);
@@ -55,34 +80,47 @@ void showArmorBoxClass(std::string window_names, const cv::Mat &src, vector<cv::
/************************** /**************************
* 显示单个装甲板区域及其类别 * * 显示单个装甲板区域及其类别 *
**************************/ **************************/
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; static Mat image2show;
if(box.rect == cv::Rect2d()){
imshow(windows_name, src);
}
if (src.type() == CV_8UC1) { // 黑白图像 if (src.type() == CV_8UC1) { // 黑白图像
cvtColor(src, image2show, COLOR_GRAY2RGB); cvtColor(src, image2show, COLOR_GRAY2RGB);
} else if (src.type() == CV_8UC3) { //RGB 彩色 } else if (src.type() == CV_8UC3) { //RGB 彩色
image2show = src.clone(); 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.blobsDistance())
cout << box.rect.width/box.rect.height << endl;
if(box.rect.width/box.rect.height > 1.6){
rectangle(image2show, box.rect, Scalar(0, 255, 0), 3);
}else{
rectangle(image2show, box.rect, Scalar(0, 255, 0), 1);
};
char dist[5]; char dist[5];
// sprintf(dist, "%.1f", distance); // sprintf(dist, "%.1f", distance);
if (boxid == -1) if (box.id == -1)
putText(image2show, id2name[boxid]+" "+dist, Point(armor_box.x + 2, armor_box.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1, putText(image2show, id2name[box.id]+" "+dist, Point(box.rect.x + 2, box.rect.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
Scalar(0, 255, 0)); Scalar(0, 255, 0));
else if (1 <= boxid && boxid < 8) else if (1 <= box.id && box.id < 8)
putText(image2show, id2name[boxid]+" "+dist, Point(armor_box.x + 2, armor_box.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1, putText(image2show, id2name[box.id]+" "+dist, Point(box.rect.x + 2, box.rect.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
Scalar(255, 0, 0)); Scalar(255, 0, 0));
else if (8 <= boxid && boxid < 15) else if (8 <= box.id && box.id < 15)
putText(image2show, id2name[boxid]+" "+dist, Point(armor_box.x + 2, armor_box.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1, putText(image2show, id2name[box.id]+" "+dist, Point(box.rect.x + 2, box.rect.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
Scalar(0, 0, 255)); Scalar(0, 0, 255));
else if (boxid != 0) else if (box.id != 0)
LOGE_INFO("Invalid box id:%d!", boxid); LOGE_INFO("Invalid box id:%d!", box.id);
imshow(windows_name, image2show); 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; static Mat image2show;
if (src.type() == CV_8UC1) { // 黑白图像 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) { for (const auto &light_blob:light_blobs) {
Scalar color; Scalar color(0, 255, 0);
if (light_blob.BlobColor == BLOB_RED) if (light_blob.blob_color == BLOB_RED)
color = Scalar(0, 0, 255); 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); color = Scalar(255, 0, 0);
else
color = Scalar(0, 255, 0);
cv::Point2f vertices[4]; cv::Point2f vertices[4];
light_blob.rect.points(vertices); light_blob.rect.points(vertices);
for (int j = 0; j < 4; j++) { 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); 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

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

View File

@@ -54,16 +54,14 @@ def save_para(folder, paras):
save_bias(fp, paras[7]) save_bias(fp, paras[7])
STEPS = 10000 STEPS = 20000
BATCH = 30 BATCH = 50
LEARNING_RATE_BASE = 0.005 LEARNING_RATE_BASE = 0.005
LEARNING_RATE_DECAY = 0.99 LEARNING_RATE_DECAY = 0.99
MOVING_AVERAGE_DECAY = 0.99 MOVING_AVERAGE_DECAY = 0.99
def train(dataset, show_bar=False): 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]) x = tf.placeholder(tf.float32, [None, generate.SRC_ROWS, generate.SRC_COLS, generate.SRC_CHANNELS])
y_= tf.placeholder(tf.float32, [None, forward.OUTPUT_NODES]) y_= tf.placeholder(tf.float32, [None, forward.OUTPUT_NODES])
keep_rate = tf.placeholder(tf.float32) keep_rate = tf.placeholder(tf.float32)
@@ -107,7 +105,8 @@ def train(dataset, show_bar=False):
) )
if i % 100 == 0: 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}) acc = sess.run(accuracy, feed_dict={x: test_images, y_: test_labels, keep_rate:1.0})
bar.set_postfix({"loss": loss_value, "acc": acc}) bar.set_postfix({"loss": loss_value, "acc": acc})
@@ -116,6 +115,9 @@ def train(dataset, show_bar=False):
vars_val = sess.run(vars) vars_val = sess.run(vars)
save_para("/home/xinyang/Workspace/RM_auto-aim/tools/para", vars_val) save_para("/home/xinyang/Workspace/RM_auto-aim/tools/para", vars_val)
print("save done!") 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}) # nodes_val = sess.run(nodes, feed_dict={x:test_images})
# return vars_val, nodes_val # return vars_val, nodes_val
DevList = mvsdk.CameraEnumerateDevice() DevList = mvsdk.CameraEnumerateDevice()
@@ -204,9 +206,9 @@ def train(dataset, show_bar=False):
if __name__ == "__main__": if __name__ == "__main__":
import os # import os
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" # os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"] = "-1" # os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
dataset = generate.DataSet("/home/xinyang/Workspace/box_cut") dataset = generate.DataSet("/home/xinyang/Workspace/box_cut")
train(dataset, show_bar=True) train(dataset, show_bar=True)
input("press enter to continue...") input("press enter to continue...")

View File

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

View File

@@ -40,7 +40,7 @@ class DataSet:
files = os.listdir(dir) files = os.listdir(dir)
for file in tqdm(files, postfix={"loading id": i}, dynamic_ncols=True): for file in tqdm(files, postfix={"loading id": i}, dynamic_ncols=True):
if file[-3:] == "jpg": 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_samples.append(self.file2nparray("%s/%s" % (dir, file)))
self.train_labels.append(self.id2label(i)) self.train_labels.append(self.id2label(i))
else: else:
@@ -61,6 +61,15 @@ class DataSet:
labels.append(self.train_labels[id]) labels.append(self.train_labels[id])
return np.array(samples), np.array(labels) 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): def all_train_sets(self):
return self.train_samples[:], self.train_labels[:] return self.train_samples[:], self.train_labels[:]

View File

@@ -1,7 +1,7 @@
6 6
-0.012731806 0.71588296
-0.68924344 0.11027224
1.0428871 0.5223108
0.09240551 2.472485
0.87806237 0.27160552
-0.51778877 2.29277

View File

@@ -2,453 +2,453 @@
6 6
5 5
5 5
-0.0705555 -0.88012725
0.086937346 -1.0834439
0.297247 -1.3267924
0.51908225 -1.1549424
0.41566578 -1.0650164
0.22415005 -0.556848
0.21470949 -0.96584696
0.42054617 -0.92094207
0.57512695 -0.8122867
0.50255156 -0.6862978
0.2663179 -0.45814085
0.10764991 -0.72940165
0.32504323 -0.5661026
0.27210033 -0.3622125
0.32694185 -0.22462772
0.18968254 -0.38875562
-0.03312495 -0.4397983
-0.28554282 -0.36654872
-0.27717206 -0.20731705
0.010500877 -0.03394899
-0.16386741 -0.45235923
-0.58856106 -0.6464031
-1.0167654 -0.41129747
-0.59654444 -0.05619224
-0.07342564 -0.10460437
0.6650266 -0.19211882
0.6682501 -0.7301527
0.61575854 -0.33149132
0.20123789 0.198266
0.13246079 0.7046016
0.9794644 0.37492985
0.9181109 -0.20615123
0.75080305 0.031133946
0.5678118 0.51563126
0.17880438 0.5250833
0.8291312 0.53731644
0.9157011 -0.098048255
0.8058578 0.08348564
0.6174977 -0.021599947
0.3349475 -0.24505879
0.93871576 0.22221932
1.0840453 -0.24253948
0.9012157 -0.32930574
0.6562343 -0.7114027
0.28151926 -1.2710199
0.8399793 0.045749612
0.9920022 -0.807872
0.64904636 -1.0033796
0.6055482 -1.6865261
0.15666491 -2.0497494
-0.8087083 -1.9287797
-0.5565874 -2.1446464
-0.8960519 -1.7040968
-0.80074924 -1.4303613
-0.74640626 -1.2351265
-0.2773623 -0.6758041
-0.20795147 -0.71685314
-0.1870408 -0.21431081
-0.15045224 0.07991056
-0.13983378 -0.3487312
-0.10816965 0.17201507
0.031628396 0.6606464
-0.116946414 0.79005384
-0.013991349 0.5726958
0.21591163 -0.20626955
-0.18964738 0.67691
0.0040286863 1.0496907
-0.30242768 1.0913255
-0.24229145 0.48710188
0.23588136 -0.4968
-0.331128 0.9180211
-0.5470479 0.7865262
-0.7203085 0.6951502
-0.6601643 -0.2679864
-0.05225026 -1.0100036
0.45265025 -0.6549106
0.75259274 -0.7277044
0.74857485 -0.6865319
0.7100708 -0.6717992
0.34476462 -0.50691587
0.46986035 -0.3242441
0.5765347 -0.2603625
0.6258838 -0.20068945
0.3804861 -0.28516608
0.3160558 -0.4555812
0.6183596 -0.11707577
0.59951615 -0.39915577
0.60037804 -0.4174412
0.6340707 -0.40552583
0.34009996 -0.32087803
0.7194144 -0.078136295
0.8571618 -0.35391638
0.94336456 -0.520493
0.90685135 -0.52106434
0.41317853 -0.42825955
1.0044444 -0.03405384
1.0062212 -0.45503956
1.0895951 -0.54937404
0.92497915 -0.39296526
0.7468299 -0.27851546
-1.2501324 0.4076081
-0.74794984 0.48703498
-0.047555014 0.24596901
0.49243745 0.052479118
0.8178278 -0.11822296
-1.2034731 0.34343225
-0.49681732 0.73309004
0.015281494 0.51623255
0.60018766 0.30654356
0.713024 0.24352127
-0.84448695 0.60910547
-0.0899703 0.7742304
0.09781959 0.77255154
0.4817282 0.70245695
0.51024574 0.3654784
0.010328657 0.5132427
0.2768326 0.97475594
0.6458937 0.8458663
0.65859175 0.8264121
0.39070535 0.5510292
0.60249025 0.58496714
1.1937758 0.8284266
0.9160051 0.975897
0.8284883 1.17892
0.53566974 0.591301
-0.4362068 1.1138518
-0.2836022 0.20256059
-0.32180697 -0.71471
0.022249598 -1.5062889
0.29908466 -1.8032609
-0.5530434 1.0235786
-0.4986115 0.007276212
-0.278484 -0.6360013
-0.31018886 -1.2706653
-0.24363342 -1.7817974
-0.35979065 1.0436956
-0.43008342 0.20097604
-0.37437305 -0.2987995
-0.30203703 -0.56377083
-0.5734246 -0.8813779
0.02336341 0.98090833
-0.25258422 0.37666252
-0.3121478 0.20098194
-0.6288646 -0.095219366
-0.4711073 -0.054543417
0.12114608 0.8959234
-0.061813425 0.57586765
-0.12937883 0.5812942
-0.6477893 0.7652194
-0.6810196 0.79247415
1.8673725 -1.085829
2.8808968 -1.8046223
3.1819828 -2.003757
3.0621288 -1.8771393
2.5003161 -1.3204845
2.4616675 -0.4507941
3.2074707 -0.9565954
3.5739362 -0.7566931
3.1081522 -0.6415545
2.4229178 -0.7355338
2.4271266 0.12221917
3.280304 0.12962714
3.0261867 0.21181518
2.3990371 0.12851173
1.8921077 0.16504385
2.005818 0.54737926
2.4233122 0.6203841
2.1124473 0.60023224
1.5049059 0.6481109
1.0315852 0.65906626
1.0267158 0.6013462
0.8723091 0.28479722
0.44316038 0.5672894
0.1576413 0.5267723
0.22018914 0.6083729
0.18436278 0.5649867
-0.04525133 0.60430235
-0.28330094 1.5300179
-0.50770444 2.4085896
-0.4281736 3.1521795
0.26419267 1.3312007
0.16408478 1.5702604
0.19734842 2.339582
-0.2016362 2.8835678
-0.32106283 3.0516002
0.64052576 1.8068197
0.45036018 1.8284152
0.42224813 2.76448
0.106944986 2.7162426
-0.15083833 2.4563086
0.9302013 1.7156839
0.7691678 1.8515067
0.6336322 2.155838
0.078011096 2.0362217
-0.031026825 1.2552027
0.80035543 1.1692859
0.60188663 1.1990427
0.38603687 0.9825375
-0.03504348 0.64745605
-0.19659142 0.035192925
0.61344516 -2.4190683
0.8947993 -2.6218698
0.97315925 -1.7210245
0.74691004 -0.59167504
0.49092364 -0.2248943
1.2537221 -0.7396114
1.9796665 -0.33055
1.9934042 0.65298605
1.6571536 1.3416215
1.5510287 1.0957731
1.7490395 0.7281771
2.4188108 1.5008746
2.487965 2.6411202
2.0581145 2.3255975
1.922978 1.5528944
1.7984617 1.3773445
2.3430247 2.3360834
2.2450094 2.8816288
1.9467311 2.3304975
1.6972682 1.2286245
1.2808937 1.4434187
1.5145483 1.7744198
1.4981558 1.9265875
1.1744506 1.2489811
1.2942766 0.2797401
-0.028776312 -0.09615959
0.08628688 0.16094038
0.14530973 0.3554371
0.060263254 0.23911111
-0.1992724 -0.06330284
-0.3509845 0.5609407
-0.14943084 0.8231102
0.05269242 0.9812489
-0.047488246 0.9308894
-0.32251114 0.68197936
-0.055337034 0.85066247
-0.0606678 1.0460051
0.13780722 1.084312
0.025866544 1.1126771
-0.2515092 0.74939555
0.36665168 0.8017988
0.4256815 0.7592088
0.44711438 0.8252279
0.45632693 0.79122925
0.18695426 0.5297534
0.83469534 0.6613406
0.73099476 0.44538468
0.90957487 0.5151108
0.7863896 0.6671852
0.60097635 0.7874201
-2.77742 -0.4186904
-1.898205 -0.3242715
-0.51413226 -0.5268131
0.29049698 -0.18947162
0.93399036 -0.2694565
-2.6324046 -0.15294357
-1.413464 -0.1322854
-0.11643134 -0.2539519
0.7600749 -0.15333539
1.0856903 0.05965038
-2.0343983 0.2450266
-0.7860615 0.120711945
0.3931903 0.15696979
1.0088302 0.3281986
1.2542579 0.31796503
-1.0282527 0.40242982
0.00558986 0.5733415
0.7271341 0.49882093
1.2017635 0.60947615
0.9958149 0.334392
0.2970806 0.6618857
1.2236876 0.8864793
1.36118 1.0756456
1.3418391 0.9072118
0.8660408 0.7288261
-1.1435972 1.6306185
-0.83455884 -0.17470317
-0.7378884 -2.2861571
-0.20356347 -3.243416
0.21133415 -3.8216188
-0.84094524 1.298335
-1.1279244 -0.3161169
-0.6961366 -1.9428326
-0.4854085 -2.924675
-0.026166996 -3.4508967
-0.54931265 1.4310157
-0.4710362 0.29793683
-0.7298363 -0.95937806
-0.64001644 -1.8052684
-0.62205493 -2.306103
0.03693532 1.4935204
-0.40307578 0.7772036
-0.4964193 0.13935064
-0.42969394 -0.24669245
-0.5397872 -0.15737781
0.3220369 1.7619401
0.14219745 1.245751
-0.4169855 1.3405502
-0.48323318 1.0143193
-0.77415246 1.3876462
-0.4052389 0.41608283
0.5951485 -0.0019760344
0.4901534 -0.1893673
0.51781464 0.09514666
0.026524775 0.54823136
0.19928466 0.964588
0.8500332 0.7129088
0.8974233 0.57392573
0.75791407 0.7456952
0.29939106 0.77417094
0.1305985 1.5659263
0.94468176 1.4913323
0.8779284 1.3906319
0.47177282 1.3289422
0.018099217 1.3123989
-0.2669419 1.873557
0.14852984 1.6543763
0.17997491 1.5637997
-0.40414903 1.4798887
-0.57394934 1.5663011
-0.8052322 1.279134
-0.6834026 1.3002201
-0.9813351 1.2334508
-1.2330854 1.3779926
-1.1226501 1.2066296
-0.2375166 -1.6879292
-0.25760472 -1.2416688
-0.6702083 -0.37319517
-0.83058023 0.41894484
-0.845694 0.8655407
-0.035079293 -0.83897734
0.15334488 -0.13220531
-0.20645554 0.73035866
-0.6201716 0.99015117
-0.58026224 0.8889001
0.23743017 -0.27788094
0.41283235 0.43835258
0.2761712 1.1142663
-0.080429204 1.2273054
-0.5188592 0.46670702
0.713986 -0.10278471
0.6536175 0.3053077
0.46903017 0.63106036
0.15473464 0.32803783
-0.28156337 -0.031589434
0.5111026 -0.7163978
0.42682606 -0.3427183
0.4112979 -0.51233417
0.07900778 -0.78456146
-0.2720577 -1.0866679
-0.4981358 -3.8261662
-0.051663946 -3.7541032
-0.023117686 -2.61236
-0.19846022 -1.6549827
-0.19126081 -1.3225579
0.29513282 -2.0429566
0.93106616 -1.5835449
0.9072645 -0.32761127
0.5732627 0.08814101
0.26237917 -0.18790397
0.39974377 -0.4660247
1.1159221 0.3267658
1.0814219 1.3274832
0.950581 1.0225959
0.671661 0.34919935
0.48101172 0.13662326
1.0488389 0.9643171
1.003414 1.5944754
0.9169417 0.88023806
0.5284077 -0.21318172
-0.20465238 0.026309159
0.40837994 0.6345419
0.26445296 0.5887162
0.16031574 -0.3010577
0.18525025 -1.1375724
-1.1795493 -0.8718964
-1.0623146 -0.82920974
-1.3544596 -0.6232904
-1.3211613 -0.74801314
-1.4418778 -0.87020314
-1.2897592 -0.12218699
-1.3648815 -0.16813752
-1.5633347 -0.20974346
-1.4766223 -0.065411456
-1.5375725 -0.5438282
-1.0636053 0.25449827
-1.0550519 0.09498743
-1.2028064 0.16415021
-1.3285335 -0.09611701
-1.4901532 -0.23606166
-0.59239966 0.024526453
-0.5102294 0.03917652
-0.7126663 -0.16637869
-0.6390671 -0.41614
-0.88960606 -0.2787596
0.11505768 -0.038930748
0.08690188 -0.33195582
-0.012430734 -0.59900284
-0.23703271 -0.6113101
-0.070601396 -0.4237758
-2.499217 -1.8987347
-1.5118762 -2.0578907
-0.63362616 -2.0330722
0.34636214 -1.9274229
0.80023897 -1.4714608
-2.2490098 -1.5901667
-1.210647 -1.6496544
-0.30495015 -1.674033
0.6582943 -1.5349553
0.92495674 -1.386249
-1.949688 -0.99938065
-0.931986 -1.0959543
0.08990933 -1.0847377
0.8216611 -0.92340446
0.81956995 -0.9949902
-1.0822672 -0.6592509
-0.17065391 -0.42724258
0.52672815 -0.34276384
0.6972465 -0.3720277
0.6062274 -0.39551106
-0.1929201 0.021055123
0.5915268 -0.05688377
0.72986585 -0.042158354
0.88998604 -0.12772384
0.5383484 -0.040917125
0.69495237 1.6949501
0.8119897 0.47236556
1.0762402 -0.9547053
1.4192832 -1.4116721
1.67176 -1.7465404
0.63202345 1.5048041
0.958035 0.34429762
1.1269803 -0.80934155
1.2325205 -1.3507533
1.1469792 -1.5732571
0.7853533 1.2798805
1.0906031 0.3696374
1.1132238 -0.42060608
1.087981 -0.9014883
1.0139153 -1.0100555
1.3069341 1.4363178
1.2574402 0.74688774
1.2478752 0.22157043
1.1044679 -0.034964394
0.7778477 0.1653901
1.4372398 1.5520315
1.3009509 1.3167152
1.2459791 1.1333643
0.84846544 1.2378848
0.73138183 1.5101963

View File

@@ -1,13 +1,13 @@
12 12
0.0336404 1.5451434
0.81687707 0.5222038
-0.088157885 2.0963469
1.072176 -0.57179046
-0.019678842 -0.2855711
-0.23005776 -0.032694478
2.6509802 1.832644
2.31109 1.2115502
2.8000503 -0.027030528
-0.044337805 0.17428438
-0.20568089 1.168477
2.5650184 -0.2180474

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +1,21 @@
20 20
-0.19178796 -0.70642257
-0.0275628 -0.056150615
0.45375344 2.415955
2.1090505 4.7507133
-0.012145723 -1.4209929
0.2213703 1.0922831
2.624133 -1.694851
-0.82816005 -0.5906952
0.25926802 -2.1798584
-0.014570757 -0.08606467
0.72068256 -0.22582765
0.249013 -0.4746353
2.195925 -0.13185214
-0.014568891 -0.035128176
-0.59766585 1.2385731
-0.020068042 -0.20468248
-0.05986349 0.74708694
-1.3474371 -0.022125142
-0.49981204 -0.26213062
0.6370428 -0.017111544

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +1,16 @@
15 15
1.8846483 4.195475
0.426767 0.61133766
-0.43499732 -1.1685454
-0.86950755 -1.5834343
-1.4404491 -0.6064409
-1.6620952 -0.9403711
0.43332458 0.90569496
-0.047994245 -0.21881863
-0.8123727 -1.448064
0.097763464 -0.8449567
-0.61916274 -1.7948693
0.20783848 -0.27719417
-1.0543438 -1.2483711
0.42724028 -0.8139322
0.7927464 -0.2559766

View File

@@ -1,302 +1,302 @@
20 20
15 15
3.1785574e-34 9.5176764e-35
1.5611281e-34 2.6973015e-35
-1.5863359e-34 -1.0265361e-34
-2.1766939e-34 4.8646514e-35
-2.3130055e-34 -6.1254127e-35
-2.662751e-34 -1.6196579e-34
-3.2626066e-34 -1.8820483e-34
2.8627675e-34 -2.584517e-35
2.7861122e-34 -4.927594e-35
-2.9668104e-34 -3.488553e-35
3.0360296e-34 -2.9690036e-36
2.9419657e-34 1.5346769e-34
3.1102713e-34 1.6494082e-34
-2.8726263e-34 1.3472117e-34
3.0484892e-34 -2.5107618e-34
4.3197746e-34 2.268937e-34
-1.8445088e-34 9.398538e-35
-3.530525e-34 1.644702e-35
-3.5233124e-34 -1.6242308e-34
2.2262768e-34 8.513796e-35
1.2378974e-34 3.0014082e-35
3.7615624e-34 -1.0057763e-34
-2.2716454e-34 -1.3751538e-34
2.5169786e-34 6.8052886e-35
-3.353324e-34 1.9979714e-34
3.5685113e-34 -1.7513593e-34
-4.122433e-34 -1.03661325e-35
1.7969215e-34 -1.413942e-34
5.2897058e-34 -1.7989849e-34
2.3318663e-34 1.1580782e-34
0.022835148 0.0218359
-0.029413782 -0.15200815
-0.12952074 -0.1530447
0.18896067 -0.11596871
-0.06554771 -0.120887555
0.11628288 -0.12549017
-0.06948121 -0.2251816
-0.025129182 -0.1637355
0.009227986 0.18958397
-0.10632306 0.14058124
0.21482462 0.16278608
-0.09871392 0.13417986
0.089015536 0.17509618
-0.008572652 0.123550944
-0.028414002 0.20413227
0.08512151 0.3238295
-0.21057208 -0.041693848
0.12899724 0.037450343
-0.121678144 -0.012114005
-0.044324484 0.01018214
0.012617375 0.02646931
0.23971003 -0.07791344
-0.029345443 -0.027645374
-0.10093057 -0.013312955
0.13569276 -0.0074518123
-0.05262047 -0.003935848
-0.057448562 -0.09201503
-0.057186298 -0.03893186
0.22441685 0.01961441
-0.09055193 -0.05324372
-2.5289643e-34 -0.012457668
1.7009551e-34 -0.062585026
-3.9381888e-36 -0.008908539
2.326881e-34 -0.0629493
-2.8111998e-34 0.24958569
-3.5335243e-35 -0.03930332
-1.1998445e-34 -0.043610368
-3.4805974e-34 -0.12702048
1.8599213e-34 -0.000797345
-1.7831123e-34 0.02613423
1.1460405e-34 -0.09447535
2.0934657e-34 0.2817806
1.563032e-34 -0.06397205
-1.0113456e-35 -0.07081673
2.4719906e-35 -0.09150827
-0.12601055 -0.016954083
0.19141342 0.02051717
-0.069146484 0.022037832
-0.0025679446 0.017766865
-0.11021721 0.029039811
-0.047209635 0.012314047
0.121572815 -0.0077047157
-0.021320255 -0.015749076
0.17498343 0.05030162
-0.07666946 -0.031626157
-0.03474931 -0.05287401
-0.053848345 0.014365553
0.038261224 -0.01407179
0.09783123 -0.021317631
-0.04364654 -0.05706852
0.2465007 -0.02678457
0.1849186 -0.105518445
-0.052974403 0.27412787
-0.064460956 0.04771162
-0.0467655 -0.1086562
-0.036299426 -0.099820994
-0.08964782 0.0973671
-0.022229096 -0.06100566
0.20783813 -0.03766413
-0.08701921 0.2596975
-0.021651257 0.038008798
-0.007302513 -0.0740367
-0.08308651 -0.091172025
-0.07215878 0.026401479
-0.0007826862 -0.12918255
-6.1247035e-34 0.014127405
4.463276e-34 0.068192564
5.4647075e-34 0.11106736
-5.3594374e-34 0.1292755
-7.624689e-35 0.15436788
4.547081e-34 0.10970291
-4.9066397e-34 0.053550284
-3.6748373e-34 0.08892467
-5.033634e-34 -0.104417644
5.2652385e-34 -0.14925948
-5.817056e-34 -0.09724801
-4.3149362e-34 -0.13138048
5.304378e-34 -0.12574866
5.2734927e-34 -0.16883968
4.9347583e-34 0.00016213852
0.057774916 -0.09524724
0.091525115 0.052638154
0.14736745 -0.028680086
0.13339345 -0.022195095
0.15654251 0.033073273
0.09139076 -0.028824894
0.12214476 -0.029216787
0.106167495 0.2449274
-0.1375304 -0.024783885
-0.11402692 -0.07764256
-0.07316204 -0.061912637
-0.08932755 -0.016075077
-0.11316809 -0.02446794
-0.10894508 -0.04687931
-0.12546284 0.17324682
-3.2000347e-34 -1.3664915e-34
-2.36952e-34 1.7117406e-34
-2.2271435e-34 -9.564682e-35
2.732874e-34 -1.4027299e-34
-2.5469592e-34 1.4579916e-34
2.4332584e-34 -1.5181731e-34
2.4015109e-34 -5.093483e-36
2.305403e-34 -1.3727128e-34
-1.0759744e-34 6.642354e-35
1.7449821e-34 1.1984039e-34
-2.3276338e-34 1.9791884e-35
-1.6425085e-34 -5.4484714e-35
2.3379538e-34 -6.4366914e-35
-1.2265797e-35 1.1018957e-34
-2.2131944e-34 -1.0511991e-34
-0.007536282 1.3135222e-34
-0.015670829 -8.0284806e-35
-0.044145193 -1.4709747e-34
-0.06925844 1.0851237e-34
-0.038289294 8.875944e-35
0.04218386 -2.134088e-34
-0.028006999 2.476544e-34
0.19194373 5.107793e-35
-0.008162281 -7.8870063e-35
-0.04310273 -1.2691251e-34
-0.032295864 3.553694e-35
-0.013634144 -2.838257e-35
0.012049367 1.7464395e-34
-0.04765994 -1.1272938e-34
0.15002576 -1.1091627e-34
0.028484903 -1.3049241e-35
-0.12657242 1.1383583e-34
-0.10019828 1.7742291e-34
-0.021912435 -5.4422295e-35
-0.07220948 -1.2520755e-34
-0.07850285 1.1593796e-34
-0.11347996 -1.3331117e-34
-0.084765114 -1.0903274e-34
0.099906415 1.0538526e-34
0.07358634 7.9193657e-35
0.085178904 1.1578206e-34
0.04134392 1.546746e-34
0.09367139 9.3627936e-35
0.11517161 -7.405613e-35
0.15800452 -1.4241364e-34
0.2303931 -1.6654584e-34
-0.04586972 -1.4364477e-34
-0.08725446 6.825994e-35
-0.033236336 -1.3888286e-34
0.1308958 -1.5188911e-34
-0.036943685 8.7407935e-35
-0.014320934 2.1660504e-34
-0.0052397517 7.709884e-35
-0.013388744 1.1298119e-34
-0.024721963 -1.2047787e-34
-0.05172364 1.1614278e-34
0.03730736 4.7399006e-35
-0.02536234 -1.2590873e-34
-0.04374987 -1.918393e-34
-0.033061035 -1.7949879e-34
-0.0024779101 -6.1133507e-35
0.000728523 -1.7124091e-34
3.03098e-06 1.0027753e-34
-0.0006537406 -1.4256245e-34
0.0014257621 -9.5877e-35
7.1307574e-07 1.3339576e-34
2.82788e-05 1.7497148e-34
-1.4571673e-08 -1.1125746e-34
-9.1665876e-05 7.0308837e-35
-0.0005169288 2.0289246e-34
-0.00088055246 7.613218e-35
0.0009669605 1.3593351e-34
0.0002642583 -1.4274189e-34
7.58049e-06 1.768648e-35
5.0228886e-05 -1.3698061e-34
4.1370527e-34 0.04678968
-2.3665282e-34 0.37355593
2.6231246e-34 -0.09611428
3.7994393e-34 -0.054369465
4.0085556e-34 -0.015629357
-2.6690339e-34 -0.05580367
1.8781805e-34 -0.15901911
-1.982984e-34 -0.05126771
-3.0113217e-34 0.29752824
-2.1200167e-34 -0.051793195
-2.0077406e-35 -0.05781779
3.0132427e-34 -0.005978182
-3.0806865e-34 -0.0062369592
-1.9560212e-34 -0.17817976
1.2020748e-34 -0.0695161
4.1127485e-34 0.01831622
-3.2173455e-34 0.0074989474
4.0228943e-34 -0.11100493
-3.1162013e-34 0.24856003
-5.1426757e-34 -0.09703029
2.6755438e-34 0.07897827
3.6094879e-34 -0.04009854
-4.8759634e-34 0.0011075956
3.4464383e-34 -0.05595696
-2.8995517e-34 -0.09211669
-3.1393783e-34 0.22572945
-2.2658088e-34 0.0075836987
-3.3108237e-34 -0.009474817
-1.3505708e-35 -0.06432295
2.4738205e-34 -0.06951075
3.783955e-34 -0.05645414
3.6061226e-34 0.071479894
3.193828e-34 -0.11390204
3.7868991e-34 -0.012603015
3.6567402e-34 -0.043284483
-3.0349225e-34 -0.04052057
3.3677782e-34 0.28288093
2.8857424e-34 -0.030568892
2.5269046e-34 0.09779256
2.2737943e-34 -0.13973251
-2.65504e-34 -0.040824693
-2.732385e-34 -0.027763024
2.6953094e-34 -0.03966024
2.9642443e-34 0.28015924
2.6588915e-34 -0.09235123
-0.07233555 2.280181e-35
-0.030644806 1.653167e-34
0.014339875 -1.005274e-34
0.010646929 -3.4991933e-35
0.15107094 -1.4336594e-34
-0.04039454 -8.870093e-35
-0.1018803 1.6485537e-34
-0.024136122 -5.371398e-35
0.013392502 7.8157064e-35
-0.0011950728 1.1268512e-34
0.06232135 1.166938e-34
0.20024493 8.906015e-35
-0.06713317 -1.324139e-34
-0.08364978 -8.3128986e-35
-0.010007126 1.9132389e-34
0.073318966 -0.02137251
0.0020213877 -0.031748243
0.015295026 -0.03333544
-0.09381448 -0.17488997
0.018438634 -0.0012877738
0.15810835 0.2770376
-0.122952715 -0.045211032
-0.06948898 -0.049781293
-0.03245277 0.012432407
-0.07937658 -0.027718045
-0.074316666 -0.11303352
0.14917618 0.0018709565
0.21517377 0.260287
-0.07048892 -0.03933455
-0.060168184 -0.06063989
0.02568059 1.5933611e-34
-0.04876075 -1.5264233e-34
0.19848819 -3.1662806e-36
0.073280066 9.1825354e-35
-0.09127431 -2.950698e-35
-0.040448762 -1.924178e-35
-0.11075618 1.084847e-34
-0.0018404849 -1.0707888e-34
-0.04922203 1.8103465e-34
0.22584344 -9.76697e-35
0.08676703 -1.7214133e-34
0.023621265 -4.1789677e-35
-0.02429366 -1.9926278e-34
-0.13942361 1.846652e-35
-0.047222435 -1.3287502e-34