energy change
This commit is contained in:
@@ -125,7 +125,7 @@ void Energy::FlowStripStruct(cv::Mat &src) {
|
||||
// 此函数对图像进行腐蚀与膨胀操作
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
void Energy::CenterRStruct(cv::Mat &src) {
|
||||
Mat element_dilate_1 = getStructuringElement(MORPH_RECT, Size(8, 6));
|
||||
Mat element_dilate_1 = getStructuringElement(MORPH_RECT, Size(4, 4));
|
||||
Mat element_erode_1 = getStructuringElement(MORPH_RECT, Size(2, 1));
|
||||
Mat element_dilate_2 = getStructuringElement(MORPH_RECT, Size(3, 3));
|
||||
Mat element_erode_2 = getStructuringElement(MORPH_RECT, Size(4 , 4));
|
||||
@@ -134,8 +134,8 @@ void Energy::CenterRStruct(cv::Mat &src) {
|
||||
// imshow("erode_1", src);
|
||||
dilate(src, src, element_dilate_1);
|
||||
// imshow("dilate_1", src);
|
||||
dilate(src, src, element_dilate_2);
|
||||
// dilate(src, src, element_dilate_2);
|
||||
// imshow("dilate_2", src);
|
||||
erode(src,src, element_erode_2);
|
||||
// erode(src,src, element_erode_2);
|
||||
// imshow("erode_2", src);
|
||||
}
|
||||
@@ -79,7 +79,7 @@ void Energy::initEnergyPartParam() {
|
||||
gimbal_energy_part_param_.FAN_CONTOUR_LENGTH_MIN = 80;
|
||||
gimbal_energy_part_param_.FAN_CONTOUR_LENGTH_MAX = 100;
|
||||
gimbal_energy_part_param_.FAN_CONTOUR_WIDTH_MIN = 20;
|
||||
gimbal_energy_part_param_.FAN_CONTOUR_WIDTH_MAX = 50;
|
||||
gimbal_energy_part_param_.FAN_CONTOUR_WIDTH_MAX = 52;
|
||||
gimbal_energy_part_param_.FAN_CONTOUR_HW_RATIO_MAX = 4;
|
||||
gimbal_energy_part_param_.FAN_CONTOUR_HW_RATIO_MIN = 1;
|
||||
gimbal_energy_part_param_.FAN_CONTOUR_AREA_RATIO_MIN = 0.65;
|
||||
@@ -105,7 +105,7 @@ void Energy::initEnergyPartParam() {
|
||||
gimbal_energy_part_param_.CENTER_R_CONTOUR_WIDTH_MAX = 25;
|
||||
gimbal_energy_part_param_.CENTER_R_CONTOUR_HW_RATIO_MAX = 3;
|
||||
gimbal_energy_part_param_.CENTER_R_CONTOUR_HW_RATIO_MIN = 1;
|
||||
gimbal_energy_part_param_.CENTER_R_CONTOUR_AREA_RATIO_MIN = 0.7;
|
||||
gimbal_energy_part_param_.CENTER_R_CONTOUR_AREA_RATIO_MIN = 0.5;
|
||||
gimbal_energy_part_param_.CENTER_R_CONTOUR_INTERSETION_AREA_MIN = 10;
|
||||
|
||||
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_MAX = 3000;
|
||||
@@ -113,7 +113,7 @@ void Energy::initEnergyPartParam() {
|
||||
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_LENGTH_MIN = 60;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_LENGTH_MAX = 100;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MIN = 20;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MAX = 50;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MAX = 52;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MAX = 3;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MIN = 1;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_RATIO_MAX = 0.65;
|
||||
@@ -125,14 +125,14 @@ void Energy::initEnergyPartParam() {
|
||||
|
||||
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_AREA_MAX = 100000;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_AREA_MIN = 0;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MIN = 45;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MAX = 70;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MIN = 12;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MAX = 24;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MIN = 38;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MAX = 60;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MIN = 8;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MAX = 32;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MAX = 12;
|
||||
// gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MIN = 4;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MIN = 2.5;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_AREA_RATIO_MIN = 0.6;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MIN = 1.8;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_AREA_RATIO_MIN = 0.5;
|
||||
gimbal_energy_part_param_.FLOW_STRIP_CONTOUR_INTERSETION_AREA_MIN = 100;
|
||||
|
||||
gimbal_energy_part_param_.TWIN_ANGEL_MAX = 10;
|
||||
@@ -187,7 +187,7 @@ void Energy::initEnergyPartParam() {
|
||||
chassis_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_LENGTH_MIN = 90;
|
||||
chassis_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_LENGTH_MAX = 140;
|
||||
chassis_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MIN = 35;
|
||||
chassis_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MAX = 60;
|
||||
chassis_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MAX = 65;
|
||||
chassis_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MAX = 3;
|
||||
chassis_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MIN = 1;
|
||||
chassis_energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_RATIO_MAX = 0.55;
|
||||
|
||||
@@ -133,7 +133,7 @@ bool Energy::findCenterR(const cv::Mat src) {
|
||||
circle_center_point = centerR.center;
|
||||
circle_center_point.y += target_length / 7.5;//实际最小二乘得到的中心在R的下方
|
||||
|
||||
// RotatedRect cur_rect = minAreaRect(center_R_contour);
|
||||
RotatedRect cur_rect = minAreaRect(center_R_contour);
|
||||
// Size2f cur_size = cur_rect.size;
|
||||
// float length = cur_size.height > cur_size.width ? cur_size.height : cur_size.width;
|
||||
// float width = cur_size.height < cur_size.width ? cur_size.height : cur_size.width;
|
||||
@@ -148,10 +148,11 @@ bool Energy::findCenterR(const cv::Mat src) {
|
||||
// cout << "R intersection: " << contourArea(intersection) << endl;
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// cout << cur_rect.center << endl;
|
||||
return true;
|
||||
}
|
||||
cout << "find center R false!" << endl;
|
||||
// cv::waitKey(0);
|
||||
return false;
|
||||
|
||||
}
|
||||
@@ -160,7 +161,7 @@ bool Energy::findCenterR(const cv::Mat src) {
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// 此函数用于判断找到的矩形候选区是否为含流动条的扇叶
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
bool Energy:: findFlowStripFan(const cv::Mat src) {
|
||||
bool Energy::findFlowStripFan(const cv::Mat src) {
|
||||
if (src.empty())return false;
|
||||
static Mat src_bin;
|
||||
static Mat src_copy;
|
||||
@@ -171,7 +172,7 @@ bool Energy:: findFlowStripFan(const cv::Mat src) {
|
||||
}
|
||||
std::vector<vector<Point> > flow_strip_fan_contours;
|
||||
FlowStripFanStruct(src_bin);//图像膨胀,防止图像断开并更方便寻找
|
||||
// imshow("flow strip fan struct", src_bin);
|
||||
imshow("flow strip fan struct", src_bin);
|
||||
|
||||
findContours(src_bin, flow_strip_fan_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
|
||||
|
||||
@@ -194,11 +195,12 @@ bool Energy:: findFlowStripFan(const cv::Mat src) {
|
||||
// cout << "non zero: " << non_zero_rate << endl;
|
||||
// cout<<cur_contour_area / cur_size.area()<<endl;
|
||||
// }
|
||||
|
||||
// cout << cur_rect.center << endl;
|
||||
return true;
|
||||
}
|
||||
// showFlowStripFan("strip fan", src_bin);
|
||||
cout << "flow strip fan false!" << endl;
|
||||
// waitKey(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -233,9 +235,11 @@ bool Energy::findFlowStrip(const cv::Mat src) {
|
||||
// flow_strip = cv::minAreaRect(flow_strip_contour);
|
||||
// cout << "flow strip area: " << length << '\t' << width << endl;
|
||||
// }
|
||||
// cout << cur_rect.center << endl;
|
||||
return true;
|
||||
}
|
||||
cout << "flow strip false!" << endl;
|
||||
// waitKey(0);
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ bool Energy::isValidFanContour(cv::Mat &src, const vector<cv::Point> &fan_contou
|
||||
if (length < energy_part_param_.FAN_CONTOUR_LENGTH_MIN || width < energy_part_param_.FAN_CONTOUR_WIDTH_MIN ||
|
||||
length > energy_part_param_.FAN_CONTOUR_LENGTH_MAX || width > energy_part_param_.FAN_CONTOUR_WIDTH_MAX) {
|
||||
//cout<<"length width fail."<<endl;
|
||||
// cout << "length: " << length << '\t' << "width: " << width << '\t' << cur_rect.center << endl;
|
||||
return false;
|
||||
//矩形边长不合适
|
||||
}
|
||||
@@ -34,12 +35,14 @@ bool Energy::isValidFanContour(cv::Mat &src, const vector<cv::Point> &fan_contou
|
||||
if (length_width_ratio > energy_part_param_.FAN_CONTOUR_HW_RATIO_MAX ||
|
||||
length_width_ratio < energy_part_param_.FAN_CONTOUR_HW_RATIO_MIN) {
|
||||
//cout<<"length width ratio fail."<<endl;
|
||||
// cout << "HW: " << length_width_ratio << '\t' << cur_rect.center << endl;
|
||||
return false;
|
||||
//长宽比不合适
|
||||
}
|
||||
// cout << cur_contour_area / cur_size.area() << endl;
|
||||
if (cur_contour_area / cur_size.area() < energy_part_param_.FAN_CONTOUR_AREA_RATIO_MIN) {
|
||||
// cout << cur_contour_area / cur_size.area() << endl;
|
||||
// cout << "area ratio: " << cur_contour_area / cur_size.area() << '\t' << cur_rect.center << endl;
|
||||
return false;//轮廓对矩形的面积占有率不合适
|
||||
}
|
||||
double non_zero_rate = nonZeroRateOfRotateRect(src, cur_rect);
|
||||
@@ -71,6 +74,7 @@ bool Energy::isValidArmorContour(const vector<cv::Point> &armor_contour) {
|
||||
if (length < energy_part_param_.ARMOR_CONTOUR_LENGTH_MIN || width < energy_part_param_.ARMOR_CONTOUR_WIDTH_MIN ||
|
||||
length > energy_part_param_.ARMOR_CONTOUR_LENGTH_MAX || width > energy_part_param_.ARMOR_CONTOUR_WIDTH_MAX) {
|
||||
//cout<<"length width fail."<<endl;
|
||||
// cout << "length: " << length << '\t' << "width: " << width << '\t' << cur_rect.center << endl;
|
||||
return false;
|
||||
//矩形边长不合适
|
||||
}
|
||||
@@ -79,11 +83,14 @@ bool Energy::isValidArmorContour(const vector<cv::Point> &armor_contour) {
|
||||
if (length_width_ratio > energy_part_param_.ARMOR_CONTOUR_HW_RATIO_MAX ||
|
||||
length_width_ratio < energy_part_param_.ARMOR_CONTOUR_HW_RATIO_MIN) {
|
||||
//cout<<"length width ratio fail."<<endl;
|
||||
// cout << "HW: " << length_width_ratio << '\t' << cur_rect.center << endl;
|
||||
return false;
|
||||
//长宽比不合适
|
||||
}
|
||||
if (cur_contour_area / cur_size.area() < energy_part_param_.ARMOR_CONTOUR_AREA_RATIO_MIN)
|
||||
if (cur_contour_area / cur_size.area() < energy_part_param_.ARMOR_CONTOUR_AREA_RATIO_MIN) {
|
||||
// cout << "area ratio: " << cur_contour_area / cur_size.area() << '\t' << cur_rect.center << endl;
|
||||
return false;//轮廓对矩形的面积占有率不合适
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -108,6 +115,7 @@ bool Energy::isValidCenterRContour(const vector<cv::Point> ¢er_R_contour) {
|
||||
|| length > energy_part_param_.CENTER_R_CONTOUR_LENGTH_MAX ||
|
||||
width > energy_part_param_.CENTER_R_CONTOUR_WIDTH_MAX) {
|
||||
//cout<<"length width fail."<<endl;
|
||||
// cout << "length: " << length << '\t' << "width: " << width << '\t' << cur_rect.center << endl;
|
||||
return false;
|
||||
//矩形边长不合适
|
||||
}
|
||||
@@ -115,16 +123,19 @@ bool Energy::isValidCenterRContour(const vector<cv::Point> ¢er_R_contour) {
|
||||
if (length_width_ratio > energy_part_param_.CENTER_R_CONTOUR_HW_RATIO_MAX ||
|
||||
length_width_ratio < energy_part_param_.CENTER_R_CONTOUR_HW_RATIO_MIN) {
|
||||
//cout<<"length width ratio fail."<<endl;
|
||||
// cout << "HW: " << length_width_ratio << '\t' << cur_rect.center << endl;
|
||||
return false;
|
||||
//长宽比不合适
|
||||
}
|
||||
if (cur_contour_area / cur_size.area() < energy_part_param_.CENTER_R_CONTOUR_AREA_RATIO_MIN)
|
||||
if (cur_contour_area / cur_size.area() < energy_part_param_.CENTER_R_CONTOUR_AREA_RATIO_MIN) {
|
||||
// cout << "area ratio: " << cur_contour_area / cur_size.area() << '\t' << cur_rect.center << endl;
|
||||
return false;//轮廓对矩形的面积占有率不合适
|
||||
}
|
||||
std::vector<cv::Point2f> intersection;
|
||||
if (rotatedRectangleIntersection(cur_rect, center_ROI, intersection) == 0) {
|
||||
return false;
|
||||
} else if (contourArea(intersection) < energy_part_param_.CENTER_R_CONTOUR_INTERSETION_AREA_MIN) {
|
||||
cout << "R intersection: " << contourArea(intersection) << endl;
|
||||
// cout << "R intersection: " << contourArea(intersection) << '\t' << cur_rect.center << endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -138,8 +149,8 @@ bool Energy::isValidFlowStripFanContour(cv::Mat &src, const vector<cv::Point> &f
|
||||
double cur_contour_area = contourArea(flow_strip_fan_contour);
|
||||
if (cur_contour_area > energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_MAX ||
|
||||
cur_contour_area < energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_MIN) {
|
||||
//cout<<cur_contour_area<<" "<<energy_fan_param_.CONTOUR_AREA_MIN<<" "<<energy_fan_param_.CONTOUR_AREA_MAX<<endl;
|
||||
//cout<<"area fail."<<endl;
|
||||
// cout << "area: " << cur_contour_area << '\t' << endl;
|
||||
return false;
|
||||
//选区面积大小不合适
|
||||
}
|
||||
@@ -153,7 +164,7 @@ bool Energy::isValidFlowStripFanContour(cv::Mat &src, const vector<cv::Point> &f
|
||||
|| length > energy_part_param_.FLOW_STRIP_FAN_CONTOUR_LENGTH_MAX
|
||||
|| width > energy_part_param_.FLOW_STRIP_FAN_CONTOUR_WIDTH_MAX) {
|
||||
// cout<<"length width fail."<<endl;
|
||||
// cout << "length: " << length << '\t' << "width: " << width << endl;
|
||||
// cout << "length: " << length << '\t' << "width: " << width << '\t' << cur_rect.center << endl;
|
||||
return false;
|
||||
//矩形边长不合适
|
||||
}
|
||||
@@ -161,13 +172,14 @@ bool Energy::isValidFlowStripFanContour(cv::Mat &src, const vector<cv::Point> &f
|
||||
if (length_width_ratio > energy_part_param_.FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MAX ||
|
||||
length_width_ratio < energy_part_param_.FLOW_STRIP_FAN_CONTOUR_HW_RATIO_MIN) {
|
||||
//cout<<"length width ratio fail."<<endl;
|
||||
// cout << "HW: " << length_width_ratio << '\t' << cur_rect.center << endl;
|
||||
return false;
|
||||
//长宽比不合适
|
||||
}
|
||||
// cout << cur_contour_area / cur_size.area() << endl;
|
||||
if (cur_contour_area / cur_size.area() < energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_RATIO_MIN
|
||||
|| cur_contour_area / cur_size.area() > energy_part_param_.FLOW_STRIP_FAN_CONTOUR_AREA_RATIO_MAX) {
|
||||
// cout << "rate: " << cur_contour_area / cur_size.area() << endl;
|
||||
// cout << "area ratio: " << cur_contour_area / cur_size.area() << '\t' << cur_rect.center << endl;
|
||||
return false;
|
||||
}
|
||||
// 轮廓对矩形的面积占有率不合适
|
||||
@@ -204,7 +216,7 @@ bool Energy::isValidFlowStripContour(const vector<cv::Point> &flow_strip_contour
|
||||
length > energy_part_param_.FLOW_STRIP_CONTOUR_LENGTH_MAX ||
|
||||
width > energy_part_param_.FLOW_STRIP_CONTOUR_WIDTH_MAX) {
|
||||
// cout<<"length width fail."<<endl;
|
||||
// cout << "length: " << length << '\t' << "width: " << width << endl;
|
||||
// cout << "length: " << length << '\t' << "width: " << width << '\t' << cur_rect.center << endl;
|
||||
return false;
|
||||
//矩形边长不合适
|
||||
}
|
||||
@@ -213,14 +225,19 @@ bool Energy::isValidFlowStripContour(const vector<cv::Point> &flow_strip_contour
|
||||
if (length_width_ratio > energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MAX ||
|
||||
length_width_ratio < energy_part_param_.FLOW_STRIP_CONTOUR_HW_RATIO_MIN) {
|
||||
// cout<<"hw fail."<<endl;
|
||||
// cout << "HW: " << length_width_ratio << '\t' << cur_rect.center << endl;
|
||||
return false;
|
||||
//长宽比不合适
|
||||
}
|
||||
if (cur_contour_area / cur_size.area() < energy_part_param_.FLOW_STRIP_CONTOUR_AREA_RATIO_MIN)
|
||||
if (cur_contour_area / cur_size.area() < energy_part_param_.FLOW_STRIP_CONTOUR_AREA_RATIO_MIN) {
|
||||
// cout << "area ratio: " << cur_contour_area / cur_size.area() << '\t' << cur_rect.center << endl;
|
||||
return false;//轮廓对矩形的面积占有率不合适
|
||||
}
|
||||
std::vector<cv::Point2f> intersection;
|
||||
if (rotatedRectangleIntersection(cur_rect, flow_strip_fan, intersection) == 0 ||
|
||||
contourArea(intersection) < energy_part_param_.FLOW_STRIP_CONTOUR_INTERSETION_AREA_MIN) {
|
||||
if (rotatedRectangleIntersection(cur_rect, flow_strip_fan, intersection) == 0) {
|
||||
return false;
|
||||
} else if (contourArea(intersection) < energy_part_param_.FLOW_STRIP_CONTOUR_INTERSETION_AREA_MIN) {
|
||||
// cout << "intersection: " << contourArea(intersection) << '\t' << cur_rect.center << endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
6
main.cpp
6
main.cpp
@@ -64,8 +64,8 @@ int main(int argc, char *argv[]) {
|
||||
video_gimbal = new CameraWrapper(0/*, "armor"*/);
|
||||
video_chassis = new CameraWrapper(1/*, "energy"*/);
|
||||
} else {
|
||||
video_gimbal = new VideoWrapper("/home/sun/项目/energy_video/gimble3.avi");
|
||||
video_chassis = new VideoWrapper("/home/sun/项目/energy_video/gimble3.avi");
|
||||
video_gimbal = new VideoWrapper("/home/sun/项目/energy_video/gimbal106.avi");
|
||||
video_chassis = new VideoWrapper("/home/sun/项目/energy_video/gimbal106.avi");
|
||||
}
|
||||
if (video_gimbal->init()) {
|
||||
LOGM("video_gimbal source initialization successfully.");
|
||||
@@ -144,7 +144,7 @@ int main(int argc, char *argv[]) {
|
||||
armorFinder.run(gimbal_src);
|
||||
});
|
||||
}
|
||||
// cv::waitKey(1);
|
||||
// cv::waitKey(0);
|
||||
// });
|
||||
} while (ok);
|
||||
delete video_gimbal;
|
||||
|
||||
@@ -37,7 +37,7 @@ void uartReceive(Serial *pSerial) {
|
||||
pSerial->ReadData((uint8_t *) buffer, sizeof(mcuData)+1);
|
||||
if (buffer[sizeof(mcuData)] == '\n') {
|
||||
memcpy(&mcuData, buffer, sizeof(mcuData));
|
||||
LOGM("Get, state:%c, mark:%d!", mcuData.state, (int) mcuData.mark);
|
||||
// LOGM("Get, state:%c, mark:%d!", mcuData.state, (int) mcuData.mark);
|
||||
// LOGM("Get yaw: %f, pitch: %f!", mcuData.curr_yaw, mcuData.curr_pitch);
|
||||
// static int t = time(nullptr);
|
||||
// static int cnt = 0;
|
||||
|
||||
Reference in New Issue
Block a user