# Conflicts:
#	main.cpp
This commit is contained in:
sun
2019-07-09 13:59:02 +08:00
29 changed files with 12997 additions and 13089 deletions

View File

@@ -1,17 +1,11 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.5) CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
PROJECT(AutoAim) PROJECT(SJTU-RM-CV)
SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD 11)
SET(CMAKE_BUILD_TYPE RELEASE) SET(CMAKE_BUILD_TYPE RELEASE)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPATH=\"\\\"${PROJECT_SOURCE_DIR}\\\"\"") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPATH=\"\\\"${PROJECT_SOURCE_DIR}\\\"\"")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D${CMAKE_SYSTEM_NAME}") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D${CMAKE_SYSTEM_NAME}")
# Todo
## 使用编译期固定选项,以略微提升性能。
#SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DFIX_OPTIONS")
## 固定使用相机运行
#SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DRUN_WITH_CAMERA")
SET(BIN_NAME "run") SET(BIN_NAME "run")
FIND_PROGRAM(CCACHE_FOUND ccache) FIND_PROGRAM(CCACHE_FOUND ccache)
@@ -21,7 +15,6 @@ IF(CCACHE_FOUND)
MESSAGE("< Use ccache for compiler >") MESSAGE("< Use ccache for compiler >")
ENDIF() ENDIF()
FIND_PACKAGE(Eigen3 REQUIRED) FIND_PACKAGE(Eigen3 REQUIRED)
FIND_PACKAGE(OpenCV 3 REQUIRED) FIND_PACKAGE(OpenCV 3 REQUIRED)
FIND_PACKAGE(Threads) FIND_PACKAGE(Threads)
@@ -34,7 +27,7 @@ INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/armor/include)
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/others/include) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/others/include)
FILE(GLOB_RECURSE sourcefiles "others/src/*.cpp" "energy/src/*cpp" "armor/src/*.cpp") FILE(GLOB_RECURSE sourcefiles "others/src/*.cpp" "energy/src/*cpp" "armor/src/*.cpp")
ADD_EXECUTABLE(${BIN_NAME} main.cpp ${sourcefiles} ) ADD_EXECUTABLE(${BIN_NAME} main.cpp ${sourcefiles} others/include/constants.h)
TARGET_LINK_LIBRARIES(${BIN_NAME} ${CMAKE_THREAD_LIBS_INIT}) TARGET_LINK_LIBRARIES(${BIN_NAME} ${CMAKE_THREAD_LIBS_INIT})
TARGET_LINK_LIBRARIES(${BIN_NAME} ${OpenCV_LIBS}) TARGET_LINK_LIBRARIES(${BIN_NAME} ${OpenCV_LIBS})
@@ -52,3 +45,4 @@ ELSE ()
ENDIF() ENDIF()
ADD_CUSTOM_TARGET(create-startup COMMAND "${PROJECT_SOURCE_DIR}/tools/create-startup.sh" "${PROJECT_SOURCE_DIR}" "${CMAKE_BINARY_DIR}") ADD_CUSTOM_TARGET(create-startup COMMAND "${PROJECT_SOURCE_DIR}/tools/create-startup.sh" "${PROJECT_SOURCE_DIR}" "${CMAKE_BINARY_DIR}")
ADD_CUSTOM_TARGET(train-cnn COMMAND "gnome-terminal" "--" "bash" "-c" "${PROJECT_SOURCE_DIR}/tools/TrainCNN/backward.py")

View File

@@ -5,61 +5,62 @@
#ifndef _ARMOR_FINDER_H_ #ifndef _ARMOR_FINDER_H_
#define _ARMOR_FINDER_H_ #define _ARMOR_FINDER_H_
#include <map>
#include <constants.h>
#include <opencv2/core.hpp> #include <opencv2/core.hpp>
#include <opencv2/tracking.hpp> #include <opencv2/tracking.hpp>
#include <serial/serial.h> #include <serial/serial.h>
#include <armor_finder/classifier/classifier.h> #include <armor_finder/classifier/classifier.h>
#include "additions/additions.h" #include <additions/additions.h>
class ArmorFinder{
public:
ArmorFinder(uint8_t &color, Serial &u, string paras_folder, const uint8_t &use);
~ArmorFinder() = default;
private:
typedef cv::TrackerKCF TrackerToUse;
typedef enum{
SEARCHING_STATE, TRACKING_STATE, STANDBY_STATE
} State;
const uint8_t &enemy_color;
State state;
cv::Rect2d armor_box;
int boxid;
cv::Ptr<cv::Tracker> tracker;
cv::Mat src_gray;
Classifier classifier;
int contour_area;
Serial &serial;
const uint8_t &use_classifier;
bool stateSearchingTarget(cv::Mat &src);
bool stateTrackingTarget(cv::Mat &src);
bool stateStandBy();
public:
void run(cv::Mat &src);
bool sendBoxPosition();
};
#define BLOB_RED ENEMY_RED #define BLOB_RED ENEMY_RED
#define BLOB_BLUE ENEMY_BLUE #define BLOB_BLUE ENEMY_BLUE
extern std::map<int, string> id2name; //装甲板id到名称的map
extern std::map<string, int> name2id; //装甲板名称到id的map
/********************* 自瞄类定义 **********************/
class ArmorFinder{
public:
ArmorFinder(uint8_t &color, Serial &u, const string &paras_folder, const uint8_t &use);
~ArmorFinder() = default;
private:
typedef cv::TrackerKCF TrackerToUse; // Tracker类型定义
typedef enum{
SEARCHING_STATE, TRACKING_STATE, STANDBY_STATE
} State; // 自瞄状态枚举定义
const uint8_t &enemy_color; // 敌方颜色,引用外部变量,自动变化
State state; // 自瞄状态对象实例
cv::Rect2d armor_box; // 当前目标位置
int boxid; // 当前目标id
cv::Ptr<cv::Tracker> tracker; // tracker对象实例
Classifier classifier; // CNN分类器对象实例用于数字识别
int contour_area; // 装甲区域亮点个数,用于数字识别未启用时判断是否跟丢(已弃用)
Serial &serial; // 串口对象,引用外部变量,用于和能量机关共享同一个变量
const uint8_t &use_classifier; // 标记是否启用CNN分类器引用外部变量自动变化
bool stateSearchingTarget(cv::Mat &src); // searching state主函数
bool stateTrackingTarget(cv::Mat &src); // tracking state主函数
bool stateStandBy(); // stand by state主函数已弃用
public:
void run(cv::Mat &src); // 自瞄主函数
bool sendBoxPosition(); // 和主控板通讯
};
/******************* 灯条类定义 ***********************/
class LightBlob { class LightBlob {
public: public:
cv::RotatedRect rect; cv::RotatedRect rect; //灯条位置
double length; double length; //灯条长度
uint8_t BlobColor; uint8_t BlobColor; //灯条颜色
LightBlob(cv::RotatedRect &r) : rect(r) { LightBlob(cv::RotatedRect &r) : rect(r) {
length = max(rect.size.height, rect.size.width); length = max(rect.size.height, rect.size.width);
}; };
bool operator<(LightBlob &l2) { return this->rect.center.x < l2.rect.center.x; }
bool operator<=(LightBlob &l2) { return this->rect.center.x <= l2.rect.center.x; }
bool operator>(LightBlob &l2) { return this->rect.center.x > l2.rect.center.x; }
bool operator>=(LightBlob &l2) { return this->rect.center.x >= l2.rect.center.x; }
}; };
#endif /* _ARMOR_FINDER_H_ */ #endif /* _ARMOR_FINDER_H_ */

View File

@@ -6,16 +6,12 @@
#define _SHOW_IMAGES_H_ #define _SHOW_IMAGES_H_
#include <opencv2/core.hpp> #include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <armor_finder/armor_finder.h> #include <armor_finder/armor_finder.h>
#include <map>
extern std::map<int, string> id2name; //
void showArmorBoxVector(std::string windows_name, const cv::Mat &src, const std::vector<cv::Rect2d> &armor_box); 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 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 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 showArmorBoxClass(std::string window_names, const cv::Mat &src, vector<cv::Rect2d> boxes[10]);
void showCuoWeiDu(const cv::Mat &src, const std::vector<LightBlob> &light_blobs);
#endif /* _SHOW_IMAGES_H_ */ #endif /* _SHOW_IMAGES_H_ */

View File

@@ -8,11 +8,23 @@
#include <opencv2/highgui.hpp> #include <opencv2/highgui.hpp>
#include <armor_finder/armor_finder.h> #include <armor_finder/armor_finder.h>
ArmorFinder::ArmorFinder(uint8_t &color, Serial &u, string paras_folder, const uint8_t &use) : std::map<int, string> id2name = {
{-1, "OO"},{ 0, "NO"},
{ 1, "B1"},{ 2, "B2"},{ 3, "B3"},{ 4, "B4"},{ 5, "B5"},{ 6, "B7"},{ 7, "B8"},
{ 8, "R1"},{ 9, "R2"},{10, "R3"},{11, "R4"},{12, "R5"},{13, "R7"},{14, "R8"},
}; //装甲板id到名称的map
std::map<string, int> name2id = {
{"OO", -1},{"NO", 0},
{"B1", 1},{"B2", 2},{"B3", 3},{"B4", 4},{"B5", 5},{"B7", 6},{"B8", 7},
{"R1", 8},{"R2", 9},{"R3", 10},{"R4", 11},{"R5", 12},{"R7", 13},{"R8", 14},
}; //装甲板名称到id的map
ArmorFinder::ArmorFinder(uint8_t &color, Serial &u, const string &paras_folder, const uint8_t &use) :
serial(u), serial(u),
enemy_color(color), enemy_color(color),
state(STANDBY_STATE), state(STANDBY_STATE),
classifier(std::move(paras_folder)), classifier(paras_folder),
contour_area(0), contour_area(0),
use_classifier(use), use_classifier(use),
boxid(-1) boxid(-1)
@@ -20,28 +32,26 @@ ArmorFinder::ArmorFinder(uint8_t &color, Serial &u, string paras_folder, const u
} }
void ArmorFinder::run(cv::Mat &src) { void ArmorFinder::run(cv::Mat &src) {
static int tracking_cnt = 0; static int tracking_cnt = 0; // 记录追踪帧数,用于定时退出追踪
cv::Mat src_use; cv::Mat src_use = src.clone(); // 实际参与计算的图像对象
src_use = src.clone();
cv::cvtColor(src_use, src_gray, CV_RGB2GRAY);
if(show_armor_box){ if(show_armor_box){ // 根据条件显示当前目标装甲板
showArmorBox("box", src, armor_box, boxid); showArmorBox("box", src, armor_box, boxid);
cv::waitKey(1); cv::waitKey(1);
} }
stateSearchingTarget(src_use); // stateSearchingTarget(src_use);
return; // return;
switch (state){ switch (state){
case SEARCHING_STATE: case SEARCHING_STATE:
if(stateSearchingTarget(src_use)){ if(stateSearchingTarget(src_use)){
if((armor_box & cv::Rect2d(0, 0, 640, 480)) == armor_box) { if((armor_box & cv::Rect2d(0, 0, 640, 480)) == armor_box) { // 判断装甲板区域是否脱离图像区域
if(!classifier && use_classifier){ if(!classifier || !use_classifier){ /* 如果分类器不可用或者不使用分类器 */
cv::Mat roi = src_use.clone()(armor_box), roi_gray; cv::Mat roi = src_use.clone()(armor_box), 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 = TrackerToUse::create(); // 成功搜寻到装甲板创建tracker对象
tracker->init(src_use, armor_box); tracker->init(src_use, armor_box);
state = TRACKING_STATE; state = TRACKING_STATE;
tracking_cnt = 0; tracking_cnt = 0;
@@ -50,7 +60,7 @@ void ArmorFinder::run(cv::Mat &src) {
} }
break; break;
case TRACKING_STATE: case TRACKING_STATE:
if(++tracking_cnt>100 || !stateTrackingTarget(src_use)){ if(++tracking_cnt>100 || !stateTrackingTarget(src_use)){ // 最多追踪100帧图像
state = SEARCHING_STATE; state = SEARCHING_STATE;
LOGM(STR_CTR(WORD_LIGHT_YELLOW ,"into search!")); LOGM(STR_CTR(WORD_LIGHT_YELLOW ,"into search!"));
} }

View File

@@ -0,0 +1,341 @@
//
// Created by xinyang on 19-3-27.
//
#include <armor_finder/armor_finder.h>
#include <opencv2/highgui.hpp>
#include <show_images/show_images.h>
#include <options/options.h>
#include <log.h>
#include "image_process.h"
typedef std::vector<LightBlob> LightBlobs;
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;
}
/// Todo: 下面的函数可以有性能优化,暂时未做。
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;
}
///Todo: 性能优化后的函数。(暂时还有点问题)
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>(c, r)) {
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>(c, r)) {
cnt++;
}
}
}
return double(cnt) / rotrect.size.area();
}
static bool isValidLightBlob(const cv::Mat &bin, const cv::RotatedRect &rect) {
return (lw_rate(rect) > 1.8) &&
// (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);
}
static bool findLightBlobs(const cv::Mat &src, LightBlobs &light_blobs) {
static cv::Mat src_gray;
if (src.type() == CV_8UC3) {
cvtColor(src, src_gray, CV_BGR2GRAY);
} else if (src.type() == CV_8UC1) {
src_gray = src.clone();
}
std::vector<std::vector<cv::Point> > light_contours;
cv::findContours(src_gray, 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_gray, rect)) {
light_blobs.emplace_back(rect);
}
}
return light_blobs.size() >= 2;
}
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;
}
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;
}
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);
}
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);
}
/* 判断两个灯条的错位度,不知道英文是什么!!! */
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;
}
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);
}
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);
}
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;
}
static bool findArmorBoxes(LightBlobs &light_blobs, std::vector<cv::Rect2d> &armor_boxes, uint8_t enemy_color) {
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;
}
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;
}
}
}
static string prior_blue[] = {
"B8", "B1", "B3", "B4", "B5", "B7", "B2",
"R8", "R1", "R3", "R4", "R5", "R7", "R2",
};
static string prior_red[] = {
"B8", "B1", "B3", "B4", "B5", "B7", "B2",
"R8", "R1", "R3", "R4", "R5", "R7", "R2",
};
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); // 重置目标装甲板位置
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, 190, 255, CV_THRESH_BINARY); // 二值化对应通道
imagePreProcess(src_bin); // 开闭运算
if (!findLightBlobs(src_bin, light_blobs)) {
return false;
}
if (show_light_blobs) {
showContours("blobs_gray", src_bin, light_blobs);
cv::waitKey(1);
}
get_blob_color(src, light_blobs);
if (show_light_blobs) {
showContours("light_blobs", src, light_blobs);
cv::waitKey(1);
}
if (!findArmorBoxes(light_blobs, armor_boxes, enemy_color)) {
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("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

@@ -1,388 +0,0 @@
//
// Created by xinyang on 19-3-27.
//
#include <armor_finder/armor_finder.h>
#include <opencv2/highgui.hpp>
#include "image_process/image_process.h"
#include <log.h>
#include <show_images/show_images.h>
#include <options/options.h>
typedef std::vector<LightBlob> LightBlobs;
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;
}
/// Todo: 下面的函数可以有性能优化,暂时未做。
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;
}
///Todo: 性能优化后的函数。(暂时还有点问题)
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[3].y; r++){
// int val[]={
// linePointX(corners[0],corners[1], r),
// linePointX(corners[0],corners[2], r),
// linePointX(corners[1],corners[3], r),
// linePointX(corners[2],corners[3], r),
// };
// for(int c=val[1]; c<val[2]; c++){
// if(bin.at<uint8_t >(c, r)){
// cnt++;
// }
// }
// }
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 >(c, r)){
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 >(c, r)){
cnt++;
}
}
}
return double(cnt) / rotrect.size.area();
}
static bool isValidLightBlob(const cv::Mat &bin, const cv::RotatedRect &rect){
return (lw_rate(rect) > 1.8) &&
// (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);
}
static void pipelineLightBlobPreprocess(cv::Mat &src) {
src -= 150;
src *= 3.5;
src -= 150;
src *= 3.5;
}
static bool findLightBlobs(const cv::Mat &src, LightBlobs &light_blobs) {
static cv::Mat src_gray;
if(src.type() == CV_8UC3){
cvtColor(src, src_gray, CV_BGR2GRAY);
}else if(src.type() == CV_8UC1){
src_gray = src.clone();
}
std::vector<std::vector<cv::Point> > light_contours;
cv::findContours(src_gray, 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_gray, rect)){
light_blobs.emplace_back(rect);
}
}
return light_blobs.size() >= 2;
}
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;
}
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;
}
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);
}
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);
}
/* 判断两个灯条的错位度,不知道英文是什么!!! */
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;
}
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);
}
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);
}
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;
}
static bool findArmorBoxes(LightBlobs &light_blobs, std::vector<cv::Rect2d> &armor_boxes, uint8_t enemy_color) {
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;
}
bool judge_light_color(std::vector<LightBlob> &light, std::vector<LightBlob> &color, std::vector<LightBlob> &result) {
for (auto &i:color) {
for (auto &j:light) {
cv::Rect2d a = i.rect.boundingRect2f();
cv::Rect2d b = j.rect.boundingRect2f();
cv::Rect2d ab = a & b;
if (ab.area() / fmin(a.area(), b.area()) >= 0.2) {
result.emplace_back(j);
break;
}
}
}
return !result.empty();
}
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;
}
}
}
int prior_blue[] = {6, 0, 2, 3, 4, 5, 1, 13, 7, 9, 10, 11, 12, 8};
int prior_red[]= {13, 7, 9, 10, 11, 12, 8, 6, 0, 2, 3, 4, 5, 1};
bool ArmorFinder::stateSearchingTarget(cv::Mat &src) {
cv::Mat split, src_bin/*, edge*/;
LightBlobs light_blobs, light_blobs_, light_blobs_real;
std::vector<cv::Rect2d> armor_boxes, boxes_number[14];
armor_box = cv::Rect2d(0,0,0,0);
cv::cvtColor(src, src_gray, CV_BGR2GRAY);
// cv::Canny(src_gray, edge, 100, 150);
// src_gray -= edge;
// cv::imshow("minus", src_gray);
// pipelineLightBlobPreprocess(src_gray);
cv::threshold(src_gray, src_bin, 170, 255, CV_THRESH_BINARY);
imagePreProcess(src_bin);
// imshow("gray bin", src_bin);
if(!findLightBlobs(src_bin, light_blobs)){
return false;
}
if(show_light_blobs){
showContours("blobs_gray", src_bin, light_blobs);
cv::waitKey(1);
}
// imageColorSplit(src, split, enemy_color);
//// imshow("split123",split);
// imagePreProcess(split);
//// imshow("split",split);
// cv::threshold(split, src_bin, 170, 255, CV_THRESH_BINARY);
// if(!findLightBlobs(src_bin, light_blobs_)){
// return false;
// }
// if(show_light_blobs){
// showContours("blobs_split", src_bin, light_blobs_);
// cv::waitKey(1);
// }
//
// if(!judge_light_color(light_blobs, light_blobs_, light_blobs_real)){
// return false;
// }
light_blobs_real = light_blobs;
get_blob_color(src, light_blobs_real);
if(show_light_blobs){
showContours("light_blobs", src, light_blobs_real);
// showCuoWeiDu(src, light_blobs_real);
cv::waitKey(1);
}
if(!findArmorBoxes(light_blobs_real, armor_boxes, enemy_color)){
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);
if(c){
boxes_number[c-1].emplace_back(box);
}
}
if(enemy_color == ENEMY_BLUE) {
for(auto id : prior_blue){
if(!boxes_number[id].empty()){
armor_box = boxes_number[id][0];
boxid = id;
break;
}
}
}else if(enemy_color == ENEMY_RED) {
for(auto id : prior_red){
if(!boxes_number[id].empty()){
armor_box = boxes_number[id][0];
boxid = id;
break;
}
}
}else{
LOGE("enemy_color ERROR!");
}
if(armor_box == cv::Rect2d(0,0,0,0)){
return false;
}
if(show_armor_boxes){
showArmorBoxClass("class", src, boxes_number);
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;
}
if(split.size() == cv::Size(320, 240)){
armor_box.x *= 2;
armor_box.y *= 2;
armor_box.width *= 2;
armor_box.height *= 2;
}
return sendBoxPosition();
}

View File

@@ -1,33 +1,17 @@
#include <show_images/show_images.h> #include <show_images/show_images.h>
#include <opencv2/highgui.hpp>
#include <log.h> #include <log.h>
using namespace cv; using namespace cv;
std::map<int, string> id2name = { /**************************
{-1, "NO"}, * 显示多个装甲板区域 *
{ 0, "B1"}, **************************/
{ 1, "B2"},
{ 2, "B3"},
{ 3, "B4"},
{ 4, "B5"},
{ 5, "B7"},
{ 6, "B8"},
{ 7, "R1"},
{ 8, "R2"},
{ 9, "R3"},
{10, "R4"},
{11, "R5"},
{12, "R7"},
{13, "R8"},
};
void showArmorBoxVector(std::string windows_name, const cv::Mat &src, const std::vector<cv::Rect2d> &armor_box) { void showArmorBoxVector(std::string windows_name, const cv::Mat &src, const std::vector<cv::Rect2d> &armor_box) {
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();
} }
@@ -37,26 +21,30 @@ void showArmorBoxVector(std::string windows_name, const cv::Mat &src, const std:
imshow(windows_name, image2show); imshow(windows_name, image2show);
} }
void showArmorBoxClass(std::string window_names, const cv::Mat &src, vector<cv::Rect2d> boxes[10]){ /**************************
* 显示多个装甲板区域及其类别 *
**************************/
void showArmorBoxClass(std::string window_names, const cv::Mat &src, vector<cv::Rect2d> boxes[10]) {
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 = 0; i < 14; 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, Scalar(0, 255, 0), 1);
if(i == -1) if (i == -1)
putText(image2show, id2name[i], Point(box.x+2, box.y+2), cv::FONT_HERSHEY_TRIPLEX, 1, Scalar(0,255,0)); putText(image2show, id2name[i], Point(box.x + 2, box.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
else if(0<=i && i<7) Scalar(0, 255, 0));
putText(image2show, id2name[i], Point(box.x+2, box.y+2), cv::FONT_HERSHEY_TRIPLEX, 1, Scalar(255,0,0)); else if (1 <= i && i < 8)
else if(7<=i && i<14) putText(image2show, id2name[i], Point(box.x + 2, box.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
putText(image2show, id2name[i], Point(box.x+2, box.y+2), cv::FONT_HERSHEY_TRIPLEX, 1, Scalar(0,0,255)); Scalar(255, 0, 0));
else 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); LOGE_INFO("Invalid box id:%d!", i);
} }
} }
@@ -64,84 +52,56 @@ void showArmorBoxClass(std::string window_names, const cv::Mat &src, vector<cv::
imshow(window_names, image2show); 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, cv::Rect2d armor_box, int boxid) {
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();
} }
rectangle(image2show, armor_box, Scalar(0, 255, 0), 1); rectangle(image2show, armor_box, Scalar(0, 255, 0), 1);
if(boxid == -1) if (boxid == -1)
putText(image2show, id2name[boxid], Point(armor_box.x+2, armor_box.y+2), cv::FONT_HERSHEY_TRIPLEX, 1, Scalar(0,255,0)); putText(image2show, id2name[boxid], Point(armor_box.x + 2, armor_box.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
else if(0<=boxid && boxid<7) Scalar(0, 255, 0));
putText(image2show, id2name[boxid], Point(armor_box.x+2, armor_box.y+2), cv::FONT_HERSHEY_TRIPLEX, 1, Scalar(255,0,0)); else if (1 <= boxid && boxid < 8)
else if(7<=boxid && boxid<14) putText(image2show, id2name[boxid], Point(armor_box.x + 2, armor_box.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
putText(image2show, id2name[boxid], Point(armor_box.x+2, armor_box.y+2), cv::FONT_HERSHEY_TRIPLEX, 1, Scalar(0,0,255)); Scalar(255, 0, 0));
else else if (8 <= boxid && boxid < 15)
putText(image2show, id2name[boxid], Point(armor_box.x + 2, armor_box.y + 2), cv::FONT_HERSHEY_TRIPLEX, 1,
Scalar(0, 0, 255));
else if (boxid != 0)
LOGE_INFO("Invalid box id:%d!", boxid); LOGE_INFO("Invalid box id:%d!", boxid);
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 showContours(std::string windows_name, const cv::Mat &src, const std::vector<LightBlob> &light_blobs) {
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(const auto &light_blob:light_blobs) for (const auto &light_blob:light_blobs) {
{
Scalar color; Scalar color;
if(light_blob.BlobColor == BLOB_RED) if (light_blob.BlobColor == BLOB_RED)
color = Scalar(0,0,255); color = Scalar(0, 0, 255);
else if(light_blob.BlobColor == BLOB_BLUE) else if (light_blob.BlobColor == BLOB_BLUE)
color = Scalar(255,0,0); color = Scalar(255, 0, 0);
else else
color = Scalar(0,255,0); 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++) {
cv::line(image2show, vertices[j], vertices[(j + 1) % 4], color, 2); cv::line(image2show, vertices[j], vertices[(j + 1) % 4], color, 2);
} }
} }
imshow(windows_name, image2show); imshow(windows_name, image2show);
} }
void drawCuoWeiDu(cv::Mat &src, 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;
}
Point2f orientation(cos(angle), sin(angle));
Vector2f p2p(light_blob_j.rect.center.x-light_blob_i.rect.center.x, light_blob_i.rect.center.y-light_blob_j.rect.center.y);
cv::line(
src,
(light_blob_j.rect.center+light_blob_i.rect.center)/2.0,
(light_blob_j.rect.center+light_blob_i.rect.center)/2.0 + 100*orientation,
Scalar(0,255,0),
2
);
}
void showCuoWeiDu(const cv::Mat &src, const std::vector<LightBlob> &light_blobs){
Mat image2show = src.clone();
for (int i = 0; i < light_blobs.size() - 1; ++i) {
for (int j = i + 1; j < light_blobs.size(); ++j) {
drawCuoWeiDu(image2show, light_blobs[i], light_blobs[j]);
}
}
imshow("CuoWeiDu", image2show);
}

View File

@@ -14,7 +14,6 @@ const int SRC_WIDTH_CAMERA = 640;
const int SRC_HEIGHT_CAMERA = 480; const int SRC_HEIGHT_CAMERA = 480;
const int SRC_WIDTH = 320; const int SRC_WIDTH = 320;
const int SRC_HEIGHT = 240; const int SRC_HEIGHT = 240;
const double PI = 3.1415926;
const int CLOCKWISE = 1; const int CLOCKWISE = 1;
const int ANTICLOCKWISE = -1; const int ANTICLOCKWISE = -1;
const float ATTACK_DISTANCE = 718;//cm const float ATTACK_DISTANCE = 718;//cm

View File

@@ -9,6 +9,7 @@
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp> #include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp> #include <opencv2/imgproc/imgproc.hpp>
#include <constants.h>
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include <sys/timeb.h> #include <sys/timeb.h>

View File

@@ -2,61 +2,58 @@
// Created by xixiliadorabarry on 1/24/19. // Created by xixiliadorabarry on 1/24/19.
// //
#include <iostream> #include <iostream>
#include <thread>
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include <fstream>
#include <energy/energy.h>
#include <serial/serial.h> #include <serial/serial.h>
#include <energy/param_struct_define.h>
#include <energy/constant.h>
#include <camera/camera_wrapper.h> #include <camera/camera_wrapper.h>
#include <camera/video_wrapper.h> #include <camera/video_wrapper.h>
#include <camera/wrapper_head.h> #include <camera/wrapper_head.h>
#include <energy/energy.h>
#include <armor_finder/armor_finder.h> #include <armor_finder/armor_finder.h>
#include <options/options.h> #include <options/options.h>
#include <additions/additions.h> #include <additions/additions.h>
#include <thread>
#define DO_NOT_CNT_TIME #define DO_NOT_CNT_TIME
#include <log.h> #include <log.h>
using namespace cv; using namespace cv;
using namespace std; using namespace std;
mcu_data mcuData = { mcu_data mcuData = { // 单片机端回传结构体
0, 0, // 当前云台yaw角
0, 0, // 当前云台pitch角
SMALL_ENERGY_STATE, ARMOR_STATE, // 当前状态,自瞄-大符-小符
0, 0, // 云台角度标记位
1, 1, // 是否启用数字识别
ENEMY_BLUE, ENEMY_RED, // 敌方颜色
}; };
WrapperHead *video_gimble = nullptr; WrapperHead *video_gimble = nullptr; // 云台摄像头视频源
WrapperHead *video_chassis = nullptr; WrapperHead *video_chassis = nullptr; // 底盘摄像头视频源
Serial serial(115200);
uint8_t last_state = mcuData.state;
Serial serial(115200); // 串口对象
uint8_t last_state = mcuData.state; // 上次状态,用于初始化
// 自瞄主程序对象
ArmorFinder armorFinder(mcuData.enemy_color, serial, PROJECT_DIR"/tools/para/", mcuData.use_classifier); ArmorFinder armorFinder(mcuData.enemy_color, serial, PROJECT_DIR"/tools/para/", mcuData.use_classifier);
// 能量机关主程序对象
Energy energy(serial, mcuData.enemy_color); Energy energy(serial, mcuData.enemy_color);
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
process_options(argc, argv); process_options(argc, argv); // 处理命令行参数
thread receive(uartReceive, &serial); thread receive(uartReceive, &serial); // 开启串口接收线程
int from_camera = 1; int from_camera = 1; // 根据条件选择视频源
if (!run_with_camera) { if (!run_with_camera) {
cout << "Input 1 for camera, 0 for video files" << endl; cout << "Input 1 for camera, 0 for video files" << endl;
cin >> from_camera; cin >> from_camera;
} }
while (true) { while (true) {
// 打开视频源
if (from_camera) { if (from_camera) {
video_gimble = new CameraWrapper(0/*, "armor"*/); video_gimble = new CameraWrapper(0/*, "armor"*/);
video_chassis = new CameraWrapper(1/*, "energy"*/); video_chassis = new CameraWrapper(1/*, "energy"*/);
} else { } else {
video_gimble = new VideoWrapper("/home/sun/项目/energy_video/energy_test.avi"); video_gimble = new VideoWrapper("/home/sun/项目/energy_video/official_r_l.mp4");
video_chassis = new VideoWrapper("/home/sun/项目/energy_video/energy_test.avi"); video_chassis = new VideoWrapper("/home/sun/项目/energy_video/energy_test.avi");
} }
if (video_gimble->init()) { if (video_gimble->init()) {
@@ -74,6 +71,7 @@ int main(int argc, char *argv[]) {
video_chassis = nullptr; video_chassis = nullptr;
} }
// 跳过前10帧噪声图像。
Mat gimble_src, chassis_src; Mat gimble_src, chassis_src;
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
if (video_gimble) { if (video_gimble) {
@@ -84,7 +82,7 @@ int main(int argc, char *argv[]) {
} }
} }
bool ok = true; bool ok = true;
cout<<"start running"<<endl; cout << "start running" << endl;
do { do {
CNT_TIME("Total", { CNT_TIME("Total", {
if (mcuData.state == BIG_ENERGY_STATE) {//大符模式 if (mcuData.state == BIG_ENERGY_STATE) {//大符模式
@@ -102,23 +100,20 @@ int main(int argc, char *argv[]) {
} }
energy.runBig(gimble_src, chassis_src);//击打大符 energy.runBig(gimble_src, chassis_src);//击打大符
last_state = mcuData.state;//更新上一帧状态 last_state = mcuData.state;//更新上一帧状态
} } else if (mcuData.state != BIG_ENERGY_STATE) {//自瞄或小符模式
else if (mcuData.state != BIG_ENERGY_STATE) {//自瞄或小符模式
last_state = mcuData.state; last_state = mcuData.state;
ok = checkReconnect(video_gimble->read(gimble_src)); ok = checkReconnect(video_gimble->read(gimble_src));
if (save_video) saveVideos(gimble_src); if (save_video) saveVideos(gimble_src);
if (show_origin) showOrigin(gimble_src); if (show_origin) showOrigin(gimble_src);
if (mcuData.state == ARMOR_STATE){ if (mcuData.state == ARMOR_STATE) {
CNT_TIME("Armor Time", { CNT_TIME("Armor Time", {
armorFinder.run(gimble_src); armorFinder.run(gimble_src);
}); });
} } else if (mcuData.state == SMALL_ENERGY_STATE) {
else if(mcuData.state == SMALL_ENERGY_STATE){
// energy.runSmall(gimble_src); // energy.runSmall(gimble_src);
energy.runBig(gimble_src); energy.runBig(gimble_src);
} }
} }
cv::waitKey(3);
}); });
} while (ok); } while (ok);

View File

@@ -7,15 +7,6 @@
#include <stdint.h> #include <stdint.h>
#include <serial/serial.h> #include <serial/serial.h>
#include <opencv2/videoio.hpp>
#include <camera/wrapper_head.h>
#define ENEMY_BLUE 0
#define ENEMY_RED 1
#define BIG_ENERGY_STATE 'b'
#define SMALL_ENERGY_STATE 's'
#define ARMOR_STATE 'a'
struct mcu_data{ struct mcu_data{
float curr_yaw; float curr_yaw;

View File

@@ -0,0 +1,17 @@
//
// Created by xinyang on 19-7-8.
//
#ifndef _CONSTANTS_H_
#define _CONSTANTS_H_
#define PI (3.14159265459)
#define ENEMY_BLUE 0
#define ENEMY_RED 1
#define BIG_ENERGY_STATE 'b'
#define SMALL_ENERGY_STATE 's'
#define ARMOR_STATE 'a'
#endif /* _CONSTANTS_H */

View File

@@ -11,11 +11,10 @@ extern bool show_armor_box;
extern bool show_armor_boxes; extern bool show_armor_boxes;
extern bool show_light_blobs; extern bool show_light_blobs;
extern bool show_origin; extern bool show_origin;
extern bool save_labelled;
extern bool run_with_camera; extern bool run_with_camera;
extern bool save_video; extern bool save_video;
extern bool collect_data;
extern bool wait_uart; extern bool wait_uart;
extern bool save_labelled_boxes;
void process_options(int argc, char *argv[]); void process_options(int argc, char *argv[]);

View File

@@ -3,17 +3,17 @@
// //
#include <cstring> #include <cstring>
#include <iostream>
#include <fstream> #include <fstream>
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp> #include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp> #include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/videoio/videoio_c.h>
#include <additions/additions.h> #include <additions/additions.h>
#include <camera/camera_wrapper.h> #include <camera/camera_wrapper.h>
#include <log.h>
#include <opencv2/videoio/videoio_c.h>
#include <iostream>
#include <energy/energy.h> #include <energy/energy.h>
#include <armor_finder/armor_finder.h> #include <armor_finder/armor_finder.h>
#include <log.h>
#define RECEIVE_LOG_LEVEL LOG_MSG #define RECEIVE_LOG_LEVEL LOG_MSG

View File

@@ -76,7 +76,7 @@ bool CameraWrapper::init() {
#elif defined(Linux) #elif defined(Linux)
CameraSetAeState(h_camera, false); CameraSetAeState(h_camera, false);
CameraSetExposureTime(h_camera, 10*1000); CameraSetExposureTime(h_camera, 10*1000);
CameraSetAnalogGain(h_camera, 30); CameraSetAnalogGain(h_camera, 50);
if(mode == 0){ if(mode == 0){
CameraSetGain(h_camera, 100, 100, 100); CameraSetGain(h_camera, 100, 100, 100);
CameraSetLutMode(h_camera, LUTMODE_PRESET); CameraSetLutMode(h_camera, LUTMODE_PRESET);
@@ -111,11 +111,8 @@ bool CameraWrapper::init() {
bool CameraWrapper::read(cv::Mat& src) { bool CameraWrapper::read(cv::Mat& src) {
// return readRaw(src); //suit for using bayer hacking in armor_finder to replace process, fast and it can filter red and blue. if(mode==0)return readProcessed(src);
if(mode==0)return readProcessed(src); // processed color image, but this runs slowly, about half fps of previous one.
if(mode==1)return readRaw(src); if(mode==1)return readRaw(src);
} }
bool CameraWrapper::readRaw(cv::Mat &src) { bool CameraWrapper::readRaw(cv::Mat &src) {

View File

@@ -10,11 +10,10 @@ bool show_armor_box = false;
bool show_armor_boxes = false; bool show_armor_boxes = false;
bool show_light_blobs = false; bool show_light_blobs = false;
bool show_origin = false; bool show_origin = false;
bool save_labelled = false;
bool run_with_camera = false; bool run_with_camera = false;
bool save_video = false; bool save_video = false;
bool collect_data = false;
bool wait_uart = false; bool wait_uart = false;
bool save_labelled_boxes = false;
void process_options(int argc, char *argv[]){ void process_options(int argc, char *argv[]){
if(argc >= 2){ if(argc >= 2){
@@ -24,10 +23,9 @@ void process_options(int argc, char *argv[]){
LOGM("--show-armor-boxes: show the candidate aim boxes."); LOGM("--show-armor-boxes: show the candidate aim boxes.");
LOGM("--show-light-blobs: show the candidate light blobs."); LOGM("--show-light-blobs: show the candidate light blobs.");
LOGM("--show-origin: show the origin image."); LOGM("--show-origin: show the origin image.");
LOGM("--save-label: save the image when box found.");
LOGM("--run-with-camera: start the program with camera directly without asking."); LOGM("--run-with-camera: start the program with camera directly without asking.");
LOGM("--save-video: save the video."); LOGM("--save-video: save the video.");
LOGM("--collect-data: collect data sent from mcu."); LOGM("--save-labelled-boxes: save labelled armor boxes.");
}else if(strcmp(argv[i], "--show-armor-box") == 0){ }else if(strcmp(argv[i], "--show-armor-box") == 0){
show_armor_box = true; show_armor_box = true;
LOGM("Enable show armor box"); LOGM("Enable show armor box");
@@ -49,21 +47,18 @@ void process_options(int argc, char *argv[]){
LOGM("Enable show light blobs"); LOGM("Enable show light blobs");
show_origin = true; show_origin = true;
LOGM("Enable show origin"); LOGM("Enable show origin");
}else if(strcmp(argv[i], "--save-labeled") == 0){
save_labelled = true;
LOGM("Enable save labeled");
}else if(strcmp(argv[i], "--run-with-camera") == 0){ }else if(strcmp(argv[i], "--run-with-camera") == 0){
run_with_camera = true; run_with_camera = true;
LOGM("Run with camera!"); LOGM("Run with camera!");
}else if(strcmp(argv[i], "--save-video") == 0){ }else if(strcmp(argv[i], "--save-video") == 0){
save_video = true; save_video = true;
LOGM("Save video!"); LOGM("Save video!");
}else if(strcmp(argv[i], "--collect-data") == 0){
collect_data = true;
LOGM("Enable data collection!");
}else if(strcmp(argv[i], "--wait-uart") == 0){ }else if(strcmp(argv[i], "--wait-uart") == 0){
wait_uart = true; wait_uart = true;
LOGM("Wait uart until available!"); LOGM("Wait uart until available!");
}else if(strcmp(argv[i], "--save-labelled-boxes") == 0){
save_labelled_boxes = true;
LOGM("labelled armor boxes will be saved!");
}else{ }else{
LOGW("Unknown option: %s. Use --help to see options.", argv[i]); LOGW("Unknown option: %s. Use --help to see options.", argv[i]);
} }

View File

@@ -70,8 +70,8 @@ def train(dataset, show_bar=False):
nodes, vars = forward.forward(x, 0.01) nodes, vars = forward.forward(x, 0.01)
y = nodes[-1] y = nodes[-1]
# ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1)) ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))
ce = tf.nn.weighted_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1), pos_weight=1) # ce = tf.nn.weighted_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1), pos_weight=1)
cem = tf.reduce_mean(ce) cem = tf.reduce_mean(ce)
loss= cem + tf.add_n(tf.get_collection("losses")) loss= cem + tf.add_n(tf.get_collection("losses"))
@@ -114,7 +114,7 @@ def train(dataset, show_bar=False):
vars_val = sess.run(vars) vars_val = sess.run(vars)
save_para("/home/xinyang/Desktop/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!")
# 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
@@ -204,5 +204,5 @@ def train(dataset, show_bar=False):
if __name__ == "__main__": if __name__ == "__main__":
dataset = generate.DataSet("/home/xinyang/Desktop/box_cut") dataset = generate.DataSet("/home/xinyang/Workspace/dataset/box_cut")
train(dataset, show_bar=True) train(dataset, show_bar=True)

View File

@@ -1,7 +1,7 @@
6 6
2.196893 1.0992107
0.07216131 -0.074966855
0.30069783 0.6112759
-0.4587247 0.15176532
0.25476167 0.7093666
-0.07236218 0.0066502886

View File

@@ -2,453 +2,453 @@
6 6
5 5
5 5
0.44015908 -0.5127243
-0.2615819 -0.35076743
-0.7202753 -0.94582695
-0.6970971 -1.1496089
-1.4688265 -0.21747248
0.041381914 -0.697151
-0.4771021 -0.31303257
-0.66656536 -0.84063727
-0.48385224 -0.60029787
-1.4722625 -0.08752324
-0.27656743 -0.6912181
-0.9269907 -0.48108417
-0.67948955 -0.877474
-0.25132853 -0.56862247
-0.9113727 0.15221412
-0.2557801 -0.80212265
-0.60230213 -0.460906
-0.1460812 -0.67574793
0.27652547 -0.573153
0.05081466 -0.20908366
-0.041295715 -0.6616608
0.12629044 -0.30440795
0.6560201 -0.55335987
1.2785738 -0.72610176
1.2724568 -0.6385564
0.96436024 0.76122427
0.8186016 0.81860757
0.88649714 0.5464134
0.75382483 0.58383447
0.73065615 0.4142986
0.6149405 0.77620906
0.60412383 0.9103861
0.6761081 0.6147042
0.57785183 0.6851236
0.76593316 0.5385627
0.038173575 0.72658443
0.34317255 0.7194319
0.4631205 0.7030224
0.47925335 0.5585485
0.563723 0.36230496
-0.111236684 0.51258016
-0.02848622 0.6475413
0.10297996 0.48098332
0.30407003 0.35653463
0.248617 0.42475638
-0.27458128 0.26459572
-0.39390934 0.30253762
-0.14871475 0.2607581
0.16967124 0.083096296
0.24545498 0.26166555
-1.029415 -0.9131472
-0.29149657 -1.5060923
0.04355961 -1.3316747
0.0037662752 -0.8584581
0.29983765 -0.4393547
-0.77363306 -0.51872504
-0.16461371 -0.93602306
0.12952146 -0.7819688
0.24172097 -0.4840393
0.57778966 -0.27869374
-0.59511507 0.11241833
-0.09913258 -0.22918689
0.42451194 -0.23048288
0.28742495 -0.050663527
0.40570587 -0.17580733
-0.6389509 0.57349825
-0.26765737 0.5720818
-0.008538765 0.55744994
-0.16448489 0.12896755
-0.108952306 0.007070846
-1.0954283 1.2535337
-0.7077157 1.1082574
-0.51456565 0.83476424
-0.8886615 0.28564626
-0.9622352 -0.05619757
0.60970205 -0.681288
0.76268256 -0.680671
0.55864525 -0.8557866
0.55142695 -0.5097621
0.20495823 -0.23541005
0.6414269 -0.49887782
0.6300521 -0.64544016
0.65805984 -0.6693754
0.44780147 -0.47900042
0.3747945 -0.30171666
0.5441177 -0.29214832
0.5725899 -0.5003537
0.4964406 -0.58870244
0.45946532 -0.51416445
0.43612415 -0.23301734
0.3597355 -0.53337747
0.37553644 -0.4110472
0.44157314 -0.5953254
0.387358 -0.53674793
0.40075454 -0.3959848
0.17919225 -0.7821416
0.15043777 -0.59215885
0.40608513 -0.7776034
0.5315383 -0.63905334
0.70023865 -0.2501917
-0.39882216 -0.731315
-0.22897638 -0.7205139
0.07692382 -0.73552233
0.46537802 -0.8656195
0.2471119 -0.6493437
-0.28952354 -0.48103082
-0.18228096 -0.64334613
0.17880945 -0.43961945
0.25431904 -0.6016135
0.3143998 -0.40041798
-0.39884818 -0.27768084
-0.15753536 -0.2570607
0.06485958 -0.2724738
-0.2133111 -0.2884815
-0.05121911 -0.14519088
-0.61350924 -0.47138828
-0.5361917 -0.3118455
-0.37863305 -0.3317675
-0.66671985 -0.4970204
-0.5644232 -0.17755331
-0.6748531 -0.61731154
-1.03323 -0.7118463
-1.2689675 -0.6186997
-1.4129945 -0.41463384
-1.1743933 -0.27342835
-0.06001543 0.11280696
-0.14319007 -0.027138332
-0.16163512 -0.6500771
-0.0396769 -1.3383414
-0.1525588 -1.6513624
-0.072800726 0.15870772
-0.13891631 0.10310151
-0.19958425 -0.4998225
-0.11522951 -1.3604605
-0.021397796 -1.8239882
-0.13518313 0.41981518
-0.06954514 0.23697153
-0.074013405 -0.1876976
-0.25381202 -0.75823486
-0.074712805 -1.4496676
-0.14324121 0.7480236
-0.13240005 0.53772146
0.03974622 0.32832542
0.0386375 -0.20044523
0.0858599 -0.744269
-0.1719485 0.5854269
0.07882476 0.7915991
-0.082135156 0.46373495
-0.041621048 0.19664662
-0.094962135 -0.24780232
1.2879299 0.6508635
0.3068063 0.577399
-1.1773561 -0.7515515
-1.5354381 -2.703382
-2.1768477 -3.039032
0.66036284 0.8525215
-0.49844337 0.6836974
-1.782708 -0.3311209
-1.9710878 -1.7767388
-2.462608 -2.5821877
0.17707823 0.8349875
-0.87392896 0.798852
-2.051351 0.086425625
-1.6899666 -0.67867047
-1.6679516 -1.8428398
0.022324406 1.2035539
-0.8198553 1.1889999
-1.4777138 0.7316317
-1.1360523 -0.3872895
-0.08169238 -1.4929688
0.36327407 1.2547168
-0.19396476 1.3532602
-0.38634166 0.7932933
0.5004826 -0.62973267
2.1292248 -1.9478854
0.772124 0.21208195
0.6520143 0.18403792
0.6104394 0.054463003
0.54212964 -0.15276414
0.49670208 0.20949952
0.3376192 0.23891807
0.37325495 0.17854711
0.4384262 -0.06374925
0.49389806 0.1451161
0.5105715 0.034864046
-0.21768741 0.26884222
-0.2625075 0.21525136
0.021104362 -0.06312853
0.014687131 0.0147968
0.007237775 0.11538528
-0.7143952 0.056850336
-0.56526405 -0.0066543873
-0.3097984 -0.11392982
-0.26630577 -0.39074197
-0.048004664 -0.009082649
-0.9913299 -0.07041612
-0.654891 -0.27938405
-0.3763111 -0.53290427
-0.044422667 -0.46564633
-0.4123894 -0.1038565
0.16750373 -2.7360635
0.61826766 -2.2902381
0.91776484 -1.5043008
1.0351493 -0.47565868
1.0686466 0.43513355
0.5438755 -1.887743
1.3297509 -1.3883648
1.6691188 -0.72364897
1.5771018 0.2942578
1.6140286 0.5935792
0.8386884 -0.80072504
1.4914865 -0.3620903
1.7180405 0.30662987
1.553264 0.6962239
1.6037419 0.8277674
0.87034816 0.31633973
1.3344289 0.69582015
1.475369 1.1589135
1.0393218 1.0656666
0.99507225 0.8970892
0.43426043 0.8714312
0.76878655 1.6066691
0.83099675 1.6423852
0.4372083 1.3843498
-0.03305005 0.70298105
0.45626023 0.16647044
0.50493777 -0.19141927
0.39258057 0.06161116
0.15306357 -0.13610205
-0.05358956 0.022933247
0.28183588 0.3518144
0.2819697 0.22493687
0.26767746 0.3335425
0.3076198 0.17380953
-0.0959618 0.489461
0.103274405 0.29505125
0.052774247 0.23336394
0.10074409 0.3280449
0.2757665 0.48822153
-0.010733735 0.6122305
-0.024759881 0.40447977
0.08207693 0.27890772
0.1011946 0.3578474
0.028895097 0.52127045
0.019118605 0.38970685
-0.11530524 0.18272732
-0.24842119 0.18300931
-0.07197208 0.2970602
0.13267942 0.13007997
0.020294672 0.3009802
0.4588099 0.21420936
0.41810644 0.18111303
0.88007724 -0.006488328
0.9788357 0.0036541307
0.9979609 0.009143832
0.6985352 0.5293987
0.9033048 0.61027414
1.3437003 0.5113341
1.3382984 0.4642546
1.0678436 0.35471886
0.9530294 0.84580845
0.9335025 0.703846
1.0252684 0.7211845
0.9498762 0.97343826
0.6784468 0.768236
0.76646155 0.92116314
0.7713496 0.91014177
0.66539836 0.8906536
0.3956565 0.7103699
-0.0023110735 0.81534237
0.36541164 0.59721285
0.056837842 0.76894915
-0.1294126 0.9786482
-0.64489746 0.56162304
-0.7045176 0.58830947
0.012467409 1.4212193
-0.06926388 1.2045107
0.12865426 0.12655553
-0.19156362 -1.0669162
-0.0143867675 -2.0093904
-0.14750443 1.4223398
-0.17903289 1.0714712
-0.12134483 -0.052089177
-0.09849269 -1.0957986
-0.1265138 -2.114745
-0.121945545 1.5610827
-0.016874207 1.0007412
-0.09141961 0.30377847
-0.03623762 -0.59364986
-0.14140157 -1.6301248
-0.032881275 1.5753381
-0.11026187 1.3631456
0.0100520095 0.9847575
-0.115708 0.09240083
-0.14582232 -1.071189
-0.20724125 1.6423446
-0.10650144 1.5190983
0.05327495 1.1077387
-0.14452165 0.34539416
-0.18657139 -0.61813635
0.9759488 -0.7005647
0.06797629 -0.54221815
-0.6424526 -1.5592585
-0.7295271 -2.4405499
-2.1513712 -2.1811392
0.51016515 -0.627011
-0.5012981 -0.31241018
-1.2636292 -1.1484959
-1.0931056 -1.7542328
-2.8768973 -1.6388324
0.11379174 -0.45500362
-0.7858709 -0.024473518
-1.2452412 -0.3944269
-0.99758494 -0.75780237
-2.3904347 -1.0935078
-0.075892836 -0.2103359
-0.6556771 0.38125098
-0.82328016 0.00046585256
-0.48217687 -0.36479756
-0.77905804 -1.1601311
0.3033478 0.19282074
-0.060466953 0.4312236
0.072058916 0.252357
0.86042064 -0.33207127
1.3924751 -1.2589971
0.67556983 -0.7244115
0.1908398 -0.7344274
0.09444006 -0.5687022
0.06265686 -0.37509185
-0.28131226 0.13250336
0.073449805 -0.6894008
-0.13604718 -0.3669812
-0.3139295 -0.43533182
-0.37795955 -0.2783045
-0.47380728 -0.11804902
-0.43103498 -0.68226725
-0.804617 -0.6880633
-0.70013463 -0.57178533
-0.61713195 -0.5920177
-0.60528046 -0.09155524
-0.89829373 -0.7462904
-1.1529391 -0.8839723
-1.0678611 -0.7533695
-0.8617194 -0.6023744
-0.90371394 -0.37469205
-1.1109782 -1.085584
-1.2232842 -1.1513206
-1.1584836 -1.1520022
-1.0506513 -0.87824655
-0.95515406 -0.5624067
-0.7661839 -1.6576195
-0.5776984 -1.4470688
-0.4494758 -0.8884038
-0.60188085 -0.2505403
-0.29663667 0.17347772
-0.49400347 -1.1138643
-0.276762 -1.0841924
-0.19688497 -0.5865495
-0.19068864 0.029103624
-0.101883315 0.34480488
-0.44627395 -0.4835728
0.023737198 -0.3733231
-0.002635871 0.13488956
-0.14802596 0.30707127
-0.0777249 0.51268774
-0.52466774 0.035971884
-0.5440437 0.3245176
-0.437515 0.60676646
-0.87626624 0.69677067
-0.9086201 0.41149148
-0.9667058 0.5813579
-1.0027927 1.0202353
-1.23929 1.03151
-1.513544 0.7790667
-1.5482179 0.46908122
-0.07866849 0.36013788
-0.22657336 0.27479073
-0.4241554 0.2624006
-0.6561498 -0.020600509
-0.8929337 0.35767564
-0.31690583 0.64802307
-0.42029023 0.50982404
-0.6620226 0.6158538
-0.53444666 0.38689435
-0.8224304 0.3291019
-0.5535824 0.8272585
-0.72263557 0.69756824
-0.7589949 0.63423824
-0.7107847 0.65290684
-0.79393065 0.5858387
-0.7419499 0.6370019
-0.9067372 0.6784572
-0.8085271 0.43127632
-0.7942699 0.44825375
-0.8814587 0.46886912
-0.8113622 0.5687188
-0.816829 0.45616633
-0.59503084 0.37996903
-0.6020855 0.29647112
-0.59153247 0.2043913
0.2328816 -0.24145731
0.058455627 -0.46544155
0.35925868 -0.62147945
0.93043673 -0.8826915
0.96835476 -0.7966154
0.55263966 0.08726857
0.550377 0.09046432
0.6435757 -0.29822
0.8017134 -0.37579864
0.9625085 -0.52853876
0.51592493 0.32306126
0.47526795 0.15829168
0.3429181 0.10857028
0.3358717 -0.013951714
0.3496695 -0.35195756
0.39214912 0.23894385
0.13631415 0.18110916
-0.2063166 0.12564722
-0.37639305 0.065700814
-0.24261068 0.0819493
-0.0990127 0.07809689
-0.73492914 0.1876159
-1.2090002 -0.16780216
-1.3132827 -0.24810323
-1.1944927 -0.29170018
-0.11983766 -0.14610599
-0.05122047 0.34555063
-0.25813514 0.058622867
0.030627063 -0.59602225
-0.09024451 -0.95331144
0.0011977615 -0.033994026
-0.03363351 0.20366722
-0.098981306 0.035348356
-0.020513052 -0.65933955
-0.16713202 -0.6995426
0.059736907 0.1555722
-0.19797234 0.6422814
-0.04968633 0.52531075
-0.06846121 0.0053241914
0.06014312 -0.25184304
-0.15752262 0.39133748
0.05522959 0.9488818
0.0477386 0.8056857
-0.18798226 0.71539056
0.034906518 0.30902287
-0.12586041 0.46792307
-0.034278292 0.96752924
-0.20553574 1.2117271
-0.017096782 0.8794963
-0.18171601 0.6939028

View File

@@ -1,11 +1,11 @@
10 10
-0.20609309 0.14412592
-0.22031759 -0.07423735
0.1367356 -0.049142662
0.3687642 0.19558677
0.41563538 0.12699787
0.56676525 0.10220198
-0.18027179 1.1084645
0.23183917 -0.102667846
-0.42312288 0.9059092
-0.071102634 0.65017

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +1,17 @@
16 16
0.58729273 0.25629708
-0.46309644 -0.032522578
-0.16430101 -0.14084667
0.43460655 0.5625487
-0.12165885 1.7736332
-0.23968913 -0.89979994
2.1033192 -0.8327153
-0.19900312 -0.0015706721
-0.0075173783 1.0403447
0.05968375 0.21188897
-0.13455966 -0.21003345
-0.203078 -0.123272754
3.4187536 -0.15712602
-0.17911159 2.9992483
0.2670588 0.9306246
-0.58640796 -0.21879409

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +1,16 @@
15 15
3.3147552 2.9608855
0.06590654 0.48027807
-0.37396204 0.6098448
-0.22522521 0.6845462
-0.9601034 -2.3924253
-0.9866448 -0.51168174
-0.091494516 0.11268586
0.08088531 0.605966
-0.87962383 -1.7118223
-0.5273214 -0.9332867
-0.18194006 -0.60581064
-0.035499398 0.47835764
-1.7873636 -1.8917097
0.48932117 -0.15730774
0.20472674 -0.5549108

View File

@@ -1,242 +1,242 @@
16 16
15 15
0.032564595 0.067641154
0.2617493 0.10578058
-0.32648245 0.16411996
-0.09931708 0.20287563
-0.24592394 0.24025424
-0.046472594 0.109507106
0.33926198 0.12222239
-0.12294629 0.071233526
0.35003394 -0.2886257
-0.21551898 -0.10079892
-0.017696692 -0.06812541
-0.14498983 -0.16702725
-0.1035376 -0.15010971
0.38845813 -0.19164395
-0.025425002 -0.07202363
0.009146354 -0.035642263
-0.10837719 -0.05917981
-0.26169685 0.0028539933
0.24757256 -0.05592549
0.12278806 0.075735435
0.173229 0.025915435
-0.13405079 -0.04963067
-0.12579814 -0.026535112
-0.055770937 -0.020446347
-0.18405183 -0.011010364
0.28358203 0.023280753
0.07445254 0.26113504
0.23714246 -0.012730428
-0.13335316 -0.017266534
0.010074598 -0.02555099
8.8978056e-36 6.6849823e-28
-3.2673058e-35 -4.636168e-36
-5.345727e-35 -2.6241106e-35
-1.2187582e-35 -1.4760121e-35
2.1464323e-35 -6.7957636e-35
6.242724e-35 -1.0416158e-34
-1.5923025e-35 1.6918945e-35
8.5710344e-35 -4.6718995e-36
-1.0859142e-34 -4.7667602e-35
3.2036078e-35 1.041564e-21
9.889982e-35 8.2043017e-32
9.5151974e-35 5.477604e-35
-2.9864197e-35 -3.8711388e-35
4.3109238e-35 6.7359426e-33
-3.5075268e-35 6.3444426e-35
0.056317 0.14113876
-0.041549474 -0.010778272
-0.07867665 0.22688301
-0.18685594 -0.09793554
0.0036230602 -0.00012759774
0.26440525 -0.05420959
-0.040618088 -0.10284228
-0.011269322 -0.0711143
-0.037696317 -0.019644944
0.01897098 0.33476868
-0.12073718 -0.026679255
0.017303245 0.017077312
0.33418366 -0.08714616
0.0023682562 -0.18292294
0.02849121 -0.008373551
5.652079e-35 0.010505794
-2.3405746e-35 0.37707043
7.754459e-35 -0.18333085
-7.9132345e-35 -0.08041537
-3.652418e-35 -0.2416076
2.7482412e-35 -0.1522789
-5.490258e-35 0.43256167
-4.0657551e-35 -0.0788787
-8.77158e-35 0.34045488
-1.6310674e-35 -0.18690895
6.9110407e-35 -0.14016004
2.8374646e-35 -0.17618605
7.249574e-35 -0.05683832
-8.326536e-36 0.24356408
-4.2208914e-35 -0.16643535
3.380163e-07 -0.10966306
0.00018250165 -0.06567155
-4.091571e-13 -0.15500161
-5.742375e-20 0.3614948
1.9097627e-29 -0.09623325
-1.0989738e-34 0.21963693
4.988384e-06 -0.04084352
-6.4157313e-25 -0.075387344
0.0046886215 -0.10502286
-4.15727e-06 -0.0677372
8.565781e-06 0.27728274
1.3159001e-08 -0.07640978
-6.0661813e-27 0.104514964
0.003999361 -0.10400845
4.6603424e-12 -0.12442972
0.05875436 -0.036030225
0.1978433 0.25929874
0.2357523 -0.059436407
0.26039347 -0.10930109
0.29742035 0.3742339
0.23000301 -0.05711202
0.22130986 -0.40452525
0.32969925 0.11595321
-0.25387922 0.17990495
-0.21843708 -0.035048593
-0.35505614 -0.15141624
-0.18760061 0.30273277
-0.26636004 -0.011792107
-0.3437664 -0.4227198
-0.31676972 0.053774044
-2.9646424e-21 1.1876719e-34
1.6212045e-32 3.7372937e-35
-4.972171e-35 -5.644917e-35
3.321333e-35 1.4523778e-35
-3.0660306e-36 -1.6516261e-35
-1.2462985e-35 -1.368295e-35
-6.15827e-35 6.519924e-36
-7.708171e-35 -1.058873e-34
-8.6527984e-35 7.093214e-35
-9.63909e-35 -7.7837143e-35
-4.329017e-36 -8.806991e-35
-1.6798441e-35 4.964243e-35
6.4576066e-36 9.1717344e-35
1.0103299e-34 9.3002685e-35
5.888647e-35 -2.2625807e-35
-7.013437e-07 -0.062388267
-4.0569785e-06 0.009545127
-1.6326982e-07 -0.025250942
-5.024649e-09 0.015120846
1.0218174e-08 -0.053508114
-5.870887e-17 -0.09033931
2.4735778e-05 -0.00907598
-1.8678125e-28 0.42657125
-5.81377e-18 0.020611048
4.2194547e-08 -0.056661103
-8.974654e-09 -0.13732637
-8.819107e-18 -0.24770766
-4.0505355e-36 0.005481845
1.4275389e-15 -0.07748723
2.5213077e-35 0.34712294
0.0455311 -0.11283319
-0.16154826 -0.16540128
-0.12516226 0.29195973
-0.15351692 -0.029924994
-0.15327676 -0.058724944
-0.101601385 -0.10992806
-0.09675424 0.197207
-0.009882243 -0.07528951
0.14380045 -0.19605869
0.17609678 0.27547538
0.15136641 -0.013697551
0.18814708 -0.055077918
0.14553012 -0.07406024
0.08837449 0.22788925
-0.033248488 -0.081390664
-5.5479194e-13 0.12524118
-1.301003e-35 -0.31053254
6.407329e-35 -0.13906848
1.9132001e-35 -0.20176046
9.564731e-15 -0.14459138
-4.683806e-19 -0.3867697
1.8975264e-24 -0.3457261
2.1182613e-16 -0.3772227
-3.6244807e-35 0.23137245
8.7545505e-28 0.25195408
6.0832183e-21 0.3451284
-8.545767e-31 0.16130213
5.2584422e-14 0.23533006
2.1925994e-22 0.23638043
-3.8261837e-20 0.2719846
-1.0880043e-34 1.8297665e-07
-6.6652585e-35 3.360339e-23
-6.389439e-35 -1.284517e-14
3.2505208e-35 1.0518133e-13
-4.973718e-35 -2.2031767e-08
-3.3143227e-35 -4.546128e-36
-8.6873607e-35 1.2173993e-14
-7.993331e-35 -6.947489e-35
-7.852833e-36 -8.3585253e-35
-6.3270696e-35 6.3733985e-36
5.258114e-35 4.228411e-37
2.1151958e-35 -5.4181e-35
7.3324824e-35 -6.841722e-35
7.1793427e-35 5.6347666e-35
-9.0051764e-35 -4.7285032e-35
0.3847243 -6.334689e-35
-0.008498104 1.7633159e-35
0.030268772 6.9929964e-35
-0.13264672 7.5054075e-35
0.030948505 6.711354e-35
-0.07938414 4.832629e-35
-0.04668712 5.29919e-35
-0.16404602 -4.058533e-35
0.07313376 2.0259362e-36
0.1522345 6.813992e-35
0.00048681977 -2.0522695e-35
0.01413009 1.0627943e-34
-0.09327267 8.187743e-35
-0.055540953 7.9783384e-35
-0.100918815 -9.2240445e-35
-0.06997617 0.51590675
-0.100417346 -0.05236788
-0.11185439 -0.07348578
-0.108010836 -0.07904794
-0.1542093 0.036673676
-0.026418801 -0.047585975
-0.0976361 0.010659185
0.2631115 -0.05747693
0.110037416 -0.1176608
-0.038920112 0.005955786
0.03310242 -0.04482761
-0.07849237 -0.06267186
0.087744445 0.029963115
-0.016706102 0.035390142
0.42764086 -0.16633497
-0.063509755 0.04267569
-0.20127158 0.06314773
0.3405362 -0.011022474
0.10242782 -0.17234531
-0.25828084 -0.014564765
-0.18461828 0.44928247
0.18166192 -0.06437395
-0.13771532 0.021410124
-0.14198124 -0.073853776
0.4270196 -0.14323992
0.16850737 -0.20758016
-0.13088605 -0.08453873
-0.18872121 0.37983018
0.22758731 -0.045325596
-0.07991603 -0.08424267
-0.06114433 -2.2948552e-16
0.22688313 1.0171164e-21
0.013428835 5.3094257e-22
-0.12416983 1.1943568e-14
0.32349384 -7.934534e-14
-0.081210054 -4.1972283e-35
-0.33148897 -6.0988935e-31
-0.1045747 8.206015e-32
0.20436902 1.8966156e-15
0.018065251 2.540294e-17
-0.15008682 -9.855207e-18
0.3795789 1.5472988e-13
-0.022265602 -9.217107e-35
-0.2928385 -2.7734643e-16
0.012199368 -4.306558e-35