#include <iostream>
#include <opencv2/opencv.hpp>
#include <string>
#include <ctime>
using namespace std;
typedef struct armor_point {
cv::Point point;
double dis;
} armor_point;
double distance(cv::Point a, cv::Point b) {
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
int LeastSquaresCircleFitting(
vector<cv::Point2d> &m_Points,
cv::Point2d &Centroid,
double &dRadius) //拟合圆函数(三个参数依次为输入点集,圆心,半径)
{
if (!m_Points.empty()) {
int iNum = (int)m_Points.size();
if (iNum < 3) return 1;
double X1 = 0.0;
double Y1 = 0.0;
double X2 = 0.0;
double Y2 = 0.0;
double X3 = 0.0;
double Y3 = 0.0;
double X1Y1 = 0.0;
double X1Y2 = 0.0;
double X2Y1 = 0.0;
vector<cv::Point2d>::iterator iter;
vector<cv::Point2d>::iterator end = m_Points.end();
for (iter = m_Points.begin(); iter != end; ++iter) {
X1 = X1 + (*iter).x;
Y1 = Y1 + (*iter).y;
X2 = X2 + (*iter).x * (*iter).x;
Y2 = Y2 + (*iter).y * (*iter).y;
X3 = X3 + (*iter).x * (*iter).x * (*iter).x;
Y3 = Y3 + (*iter).y * (*iter).y * (*iter).y;
X1Y1 = X1Y1 + (*iter).x * (*iter).y;
X1Y2 = X1Y2 + (*iter).x * (*iter).y * (*iter).y;
X2Y1 = X2Y1 + (*iter).x * (*iter).x * (*iter).y;
}
double C = 0.0;
double D = 0.0;
double E = 0.0;
double G = 0.0;
double H = 0.0;
double a = 0.0;
double b = 0.0;
double c = 0.0;
C = iNum * X2 - X1 * X1;
D = iNum * X1Y1 - X1 * Y1;
E = iNum * X3 + iNum * X1Y2 - (X2 + Y2) * X1;
G = iNum * Y2 - Y1 * Y1;
H = iNum * X2Y1 + iNum * Y3 - (X2 + Y2) * Y1;
a = (H * D - E * G) / (C * G - D * D);
b = (H * C - E * D) / (D * D - G * C);
c = -(a * X1 + b * Y1 + X2 + Y2) / iNum;
double A = 0.0;
double B = 0.0;
double R = 0.0;
A = a / (-2);
B = b / (-2);
R = double(sqrt(a * a + b * b - 4 * c) / 2);
Centroid.x = A;
Centroid.y = B;
dRadius = R;
return 0;
} else
return 1;
return 0;
}
int main() {
// string video_path = "/home/gy/视频/buffv.mp4";
cv::VideoCapture cap;
cap.open("/home/gy/视频/kazam_wrdl4w6n.avi");
clock_t start, finish;
// cv::VideoWriter writer;
// int coder = cv::VideoWriter::fourcc('M','J','P','G');//选择编码格式
// double fps=50.0;//设置视频帧率
// string filename = "/home/zjk/Videos/buff_demo.avi"; //保存的视频文件名称
// writer.open(filename,coder,fps,cv::Size(1350,1080),true);//创建保存视频文件的视频流
// if(!writer.isOpened()){
// cout<<"打开视频文件失败,请确认是否为合法输入"<<endl;
// return -1;
// }
while (true) {
cv::Mat src_frame;
cap >> src_frame;
start = clock();
// cv::resize(src_frame, src_frame, cv::Size(480, 360));
cv::resize(src_frame, src_frame, cv::Size(560, 420));
cv::Mat input;
vector<cv::Mat> bgr_images;
cv::split(src_frame, bgr_images);
cv::Mat b_src_img = bgr_images[0] - bgr_images[2];
cv::Mat g_src_img = bgr_images[0] - bgr_images[1];
cv::Mat gray ;
cv::cvtColor(src_frame, gray, cv::COLOR_BGR2GRAY);
// bitwise_and(b_src_img.clone(),g_src_img.clone(),input);
cv::threshold(b_src_img, b_src_img, 130, 255, cv::THRESH_BINARY);
cv::threshold(g_src_img, g_src_img, 120, 255, cv::THRESH_BINARY_INV);
cv::threshold(gray, gray, 100, 255, cv::THRESH_BINARY);
// cv::imshow("gray", gray);
cv::Mat element1 =
cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));
//设置内核1
cv::Mat element2 = cv::getStructuringElement(cv::MORPH_RECT,
cv::Size(3, 3));
//设置内核2
cv::Mat threshold_img;
cv::bitwise_and(b_src_img, g_src_img, threshold_img);
cv::bitwise_and(threshold_img, gray, threshold_img);
// cv::blur(threshold_img, threshold_img, cv::Size(3,3));
// cv::threshold(b_src_img, threshold_img, 140, 255, cv::THRESH_BINARY);
cv::dilate(threshold_img, threshold_img, element1);
cv::erode(threshold_img, threshold_img, element2);
// cv::dilate(threshold_img, threshold_img, element1);
// cv::imshow("b-r", b_src_img);
// cv::imshow("b-g", g_src_img);
cv::imshow("final_th", threshold_img);
// cv::blur(b_src_img, b_src_img, cv::Size(3, 3));
vector<vector<cv::Point>> contours;
cv::findContours(threshold_img, contours, cv::RETR_EXTERNAL,
cv::CHAIN_APPROX_SIMPLE);
// cv::drawContours(src_frame,contours,-1,cv::Scalar(0,0,255));
cv::Point2d r_center; // R 的中心点
vector<cv::RotatedRect> contours_min_rects; //所有轮廓的最小外接矩形
vector<cv::RotatedRect> armor_min_rects;
vector<cv::RotatedRect> target_min_rects;
vector<cv::RotatedRect> r_min_rects; // R
double r_index = 0.0;
int cnt = 0;
for (unsigned int contour_index = 0; contour_index < contours.size();
contour_index++) {
//寻找最小旋转矩形,放进容器,顺便将面积过大的剔除,长宽比悬殊的剔除
cv::RotatedRect minrect =
minAreaRect(contours[contour_index]); //最小旋转矩形
cv::Rect rect = boundingRect(contours[contour_index]); //获取矩形信息
if ((minrect.center.x < (src_frame.cols)/2 + 10) && ((minrect.center.x > (src_frame.cols)/2 - 10)) && (minrect.center.y < (src_frame.rows)/2 + 30) && (minrect.center.y > (src_frame.rows)/2 - 30) ) {
r_center = minrect.center;//center_radian
cv::circle(src_frame, r_center, 15, cv::Scalar(5, 255, 100));
}
// if (minrect.size.area() <= 50000 && minrect.size.area() > 500) {
if (minrect.size.area() <= 6000.0 && minrect.size.area() > 190) {
float width;
float height;
//判断长宽比
if (minrect.size.width > minrect.size.height) {
width = minrect.size.width;
height = minrect.size.height;
} else {
width = minrect.size.height;
height = minrect.size.width;
}
if (width / height < 4) {
contours_min_rects.push_back(minrect);
if (minrect.size.area() > 150 && minrect.size.area() < 350 &&
minrect.center.y > 200) { // find R
if (height / width > 0.1) {
// cv::R_minRects.push_back(minrect);
r_center = minrect.center;
cv::circle(src_frame, r_center, 15, cv::Scalar(5, 255, 100));
r_index = contour_index;
// std::cout<<cnt++<<std::endl;
}
} else {
if (minrect.size.area() > 300 && minrect.size.area() < 4350 &&
(height / width) < 0.7) {
armor_min_rects.push_back(minrect);
}
}
}
}
}
bool find_ok = false;
for (int i = 0; i < armor_min_rects.size() - 1; i++) {
for (int j = i + 1; j < armor_min_rects.size(); j++) {
double dis =
distance(armor_min_rects[i].center, armor_min_rects[j].center);
if (dis < 120) {
target_min_rects.push_back(armor_min_rects[i]);
target_min_rects.push_back(armor_min_rects[j]);
find_ok = true;
break;
}
// std::cout<<dis<<std::endl;
}
if (find_ok) {
break;
}
}
if (target_min_rects.size() != 2) {
continue;
} else {
cv::RotatedRect rrect_in; //= target_minRects[0];
cv::RotatedRect rrect_out; // = target_minRects[1];
vector<cv::Point2d> points;
double dis1 = distance(r_center, target_min_rects[0].center);
double dis2 = distance(r_center, target_min_rects[1].center);
if (dis1 > dis2) {
rrect_in = target_min_rects[1];
rrect_out = target_min_rects[0];
} else {
rrect_in = target_min_rects[0];
rrect_out = target_min_rects[1];
}
// drawRotatedRect(src_frame, rrect_in, cv::Scalar(0, 250, 0), 1);
// drawRotatedRect(src_frame, rrect_out, cv::Scalar(0, 0, 255), 1);
cv::Point target_center =
cv::Point((int)((rrect_in.center.x + rrect_out.center.x) / 2),
(int)((rrect_in.center.y + rrect_out.center.y) / 2));
cv::circle(src_frame, target_center, 5, cv::Scalar(0, 0, 255), -1);
cv::Point2f in_vet_points[4];
cv::Point2f out_vet_points[4];
rrect_in.points(in_vet_points);
rrect_out.points(out_vet_points);
vector<armor_point> armor_points;
for (int i = 0; i < 4; i++) {
armor_point point;
point.point = in_vet_points[i];
point.dis = distance(target_center, in_vet_points[i]);
armor_points.push_back(point);
}
for (int i = 0; i < 4; i++) {
armor_point point;
point.point = out_vet_points[i];
point.dis = distance(target_center, out_vet_points[i]);
armor_points.push_back(point);
}
sort(armor_points.begin(), armor_points.end(),
[](armor_point a, armor_point b) { return a.dis < b.dis; });
for (int i = 0; i < 4; i++) {
cv::circle(src_frame, armor_points[i].point, 3, cv::Scalar(255, 0,255),-1);
}
int buff_run_radius = (int)distance(r_center, target_center);
points.push_back(target_center);
LeastSquaresCircleFitting(points,r_center,r_index);
cv::circle(src_frame, r_center,120, cv::Scalar(55, 110,255),1); //拟合圆
}
finish = clock();
double abc_Frame =
1000/(double(finish-start)/CLOCKS_PER_SEC*1000);
std::string str = std::to_string(abc_Frame);
string Frame_name = "FPS:";
Frame_name +=str;
// cout<<"视觉识别帧率为:"<<Frame_name<<endl;
putText(src_frame,Frame_name,cv::Point(0,50),cv::FONT_HERSHEY_COMPLEX,1,cv::Scalar(0,0,255));
// // cv::resize(src_frame,src_frame,cv::Size(1350,1080));
// // writer.write(src_frame);//把图像写入视频流
cv::imshow("src_img", src_frame);
// cv::imshow("threshold_img",threshold_img);
cv::waitKey(50);
// if (cv::waitKey(0) == 'q') {
// break;
// }
// cv::imshow("g_src",g_src_img);
// cv::imshow("b_src",b_src_img);
}
// writer.release();
cap.release();
return 0;
}