#include "control_module.h" | #include "control_module.h" | ||||
ControlModule::ControlModule(/* args */) | |||||
ControlModule::ControlModule(){ | |||||
} | |||||
ControlModule::ControlModule(float forwardSpeed, float rotateSpeed, float moveSideSpeed) | |||||
{ | { | ||||
this->forwardSpeed = forwardSpeed; | |||||
this->rotateSpeed = rotateSpeed; | |||||
this->moveSideSpeed = moveSideSpeed; | |||||
} | } | ||||
ControlModule::~ControlModule() | ControlModule::~ControlModule() | ||||
{ | { | ||||
} | |||||
void ControlModule::moveForward(){ | |||||
for(int i = 0; motors; i++){ | |||||
} | |||||
}; | |||||
void ControlModule::moveSide(){ | |||||
} | |||||
void ControlModule::rotate(){ | |||||
} | } |
class ControlModule | class ControlModule | ||||
{ | { | ||||
private: | private: | ||||
/* data */ | |||||
float motors[4]; //LeftFront; RightFront; LeftBack; RightBack | |||||
float forwardSpeed; | |||||
float rotateSpeed; | |||||
float moveSideSpeed; | |||||
public: | public: | ||||
ControlModule(/* args */); | ControlModule(/* args */); | ||||
ControlModule(float forwardSpeed, float rotateSpeed, float moveSideSpeed); | |||||
~ControlModule(); | ~ControlModule(); | ||||
void moveForward(); | |||||
void rotate(); | |||||
void moveSide(); | |||||
}; | }; |
#include "input.h" | #include "input.h" | ||||
// TODO: Wenn ihr in die Zeile den Pfad zum Testvideo statt der 0 packt, benmutzt er das Testvideo. | // TODO: Wenn ihr in die Zeile den Pfad zum Testvideo statt der 0 packt, benmutzt er das Testvideo. | ||||
//Input::Input(int videoHeight, int videoWidth) : cap("C:\\Users\\User\\Desktop\\Studium\\02_Master_MSY\\2. Semester Winter 22 23\\Projekt\\Line-Following-Robot\\AutonomousMode\\Test_data\\video1.h264"), videoHeight(videoHeight), videoWidth(videoWidth) | |||||
Input::Input(int videoHeight, int videoWidth) : cap(0), videoHeight(videoHeight), videoWidth(videoWidth) | |||||
Input::Input(int videoHeight, int videoWidth) : cap("C:\\Line-Following-Robot\\AutonomousMode\\Test_data\\video1.h264"), videoHeight(videoHeight), videoWidth(videoWidth) | |||||
//Input::Input(int videoHeight, int videoWidth) : cap(0), videoHeight(videoHeight), videoWidth(videoWidth) | |||||
{ | { | ||||
this->cap.set(CAP_PROP_FRAME_HEIGHT, videoHeight); | this->cap.set(CAP_PROP_FRAME_HEIGHT, videoHeight); | ||||
this->cap.set(CAP_PROP_FRAME_WIDTH, videoWidth); | this->cap.set(CAP_PROP_FRAME_WIDTH, videoWidth); |
#include "processing.h" | #include "processing.h" | ||||
Processing::Processing(/* args */) | Processing::Processing(/* args */) | ||||
{ | { | ||||
} | } | ||||
indicesToDelete.push_back(i); | indicesToDelete.push_back(i); | ||||
continue; | continue; | ||||
} | } | ||||
} | } | ||||
//reverse the vector with the indices so the order isn't messed up when deleting: | //reverse the vector with the indices so the order isn't messed up when deleting: | ||||
return true; | return true; | ||||
} | } | ||||
int Processing::calcAngles(FrameData &data, int imageColums, int imageRows, bool turnLeft) | |||||
{ | |||||
int angle = 0; | |||||
if(data.contours.size() > 0) | |||||
{ | |||||
int index; | |||||
if(turnLeft){ | |||||
// get the most left/right contour | |||||
int leftmostEdge = imageColums; | |||||
for (int i = 0; i < data.leftEdges.size(); i++) | |||||
{ | |||||
int edge = data.leftEdges[i].x; | |||||
if (edge <= leftmostEdge) | |||||
{ | |||||
leftmostEdge = edge; | |||||
index = i; | |||||
} | |||||
} | |||||
}else | |||||
{ | |||||
int rightmostEdge = 0; | |||||
for (int i = 0; i < data.leftEdges.size(); i++) | |||||
{ | |||||
int edge = data.leftEdges[i].x; | |||||
if (edge >= rightmostEdge) | |||||
{ | |||||
rightmostEdge = edge; | |||||
index = i; | |||||
} | |||||
} | |||||
} | |||||
// Find the Top-Left and Buttom-Left Point of the Contour | |||||
std::vector<cv::Point> leftMostContour = data.contours[index]; | |||||
int xleftButtom = imageColums; | |||||
int xleftTop = imageColums; | |||||
int yButtom = data.boundingBoxes[index].y; | |||||
int yTop = data.boundingBoxes[index].height; | |||||
for (int i = 0; i < leftMostContour.size(); i++){ | |||||
if(leftMostContour[i].y == 0 && leftMostContour[i].x < xleftButtom) | |||||
{ | |||||
xleftButtom = leftMostContour[i].x; | |||||
}else if(leftMostContour[i].y > yTop -4 && leftMostContour[i].x < xleftTop){ | |||||
xleftTop = leftMostContour[i].x; | |||||
} | |||||
} | |||||
// calculate angle | |||||
int deltaX = abs(xleftButtom - xleftTop); | |||||
int deltaY = yTop; | |||||
angle = VectorOfLines::calcAngle(deltaX, deltaY); | |||||
} | |||||
return angle; | |||||
} | |||||
void Processing::processImage(Mat& inputPicture, int thresholdBinary, int gaussKernelSize) | void Processing::processImage(Mat& inputPicture, int thresholdBinary, int gaussKernelSize) | ||||
{ | { | ||||
auto iterator = data.contours.begin(); | auto iterator = data.contours.begin(); | ||||
while(iterator != data.contours.end()) | while(iterator != data.contours.end()) | ||||
{ | { | ||||
if (contourArea(*iterator) < 3500) | |||||
if (contourArea(*iterator) < 7000) | |||||
{ | { | ||||
iterator = data.contours.erase(iterator); | iterator = data.contours.erase(iterator); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
//Check for intersection with lines: | //Check for intersection with lines: | ||||
Rect boundingBox = boundingRect(*iterator); | Rect boundingBox = boundingRect(*iterator); | ||||
boundingBox.x += roi.x; | boundingBox.x += roi.x; | ||||
boundingBox.y += roi.y; | boundingBox.y += roi.y; |
#include <utils.h> | #include <utils.h> | ||||
#include <vector> | #include <vector> | ||||
using namespace cv; | using namespace cv; | ||||
using namespace std; | using namespace std; | ||||
void processImage(Mat& inputPicture, int thresholdBinary, int gaussKernelSize); | void processImage(Mat& inputPicture, int thresholdBinary, int gaussKernelSize); | ||||
void filterReflections(FrameData& frameData); | void filterReflections(FrameData& frameData); | ||||
FrameData calculateLineSegments(Mat& inputPicture, const cv::Rect& roi); | FrameData calculateLineSegments(Mat& inputPicture, const cv::Rect& roi); | ||||
int calcAngles(FrameData &data, int imageColums, int imageRows, bool turnLeft); | |||||
}; | }; |
#include "utils.h" | #include "utils.h" | ||||
#define PI 3.14159265359 | |||||
LFRPoint::LFRPoint(/* args */) : x(0.0), y(0.0) | LFRPoint::LFRPoint(/* args */) : x(0.0), y(0.0) | ||||
{ | { | ||||
} | } | ||||
} | } | ||||
return middleLines; | return middleLines; | ||||
} | |||||
int VectorOfLines::calcAngle(int deltaX, int deltaY){ | |||||
int refAngle = 0; | |||||
if(deltaX > 10E-12){ | |||||
refAngle = atan(deltaY/deltaX) * 180/PI; | |||||
// convert from img coordinates to regbot coordinates | |||||
refAngle = -(refAngle); | |||||
if (refAngle > 90) | |||||
refAngle = refAngle - 180; | |||||
cout << refAngle << "\n"; | |||||
}else{ | |||||
refAngle = -90; | |||||
} | |||||
return refAngle; | |||||
} | } |
float calcZeroPoint(cv::Point x, float m); | float calcZeroPoint(cv::Point x, float m); | ||||
static double calcDistance(Point p0, Point p1); | static double calcDistance(Point p0, Point p1); | ||||
vector<Vec4i> findMiddleLine(vector<Vec4i> &lines); | vector<Vec4i> findMiddleLine(vector<Vec4i> &lines); | ||||
static int calcAngle(int deltaX, int deltaY); | |||||
}; | }; | ||||
std::vector<cv::Rect> boundingBoxes; | std::vector<cv::Rect> boundingBoxes; | ||||
std::vector<cv::Point> leftEdges; | std::vector<cv::Point> leftEdges; | ||||
std::vector<cv::Point> middlePoints; | std::vector<cv::Point> middlePoints; | ||||
std::vector<double> angles; | |||||
FrameData(): contours(), boundingBoxes(), leftEdges(), middlePoints() {} | FrameData(): contours(), boundingBoxes(), leftEdges(), middlePoints() {} | ||||
}; | }; |
{ | { | ||||
Mat originalImage = input.readWebcam(); | Mat originalImage = input.readWebcam(); | ||||
Point roiOrigin(0, int(originalImage.rows*(7.5/12.0))); | |||||
Rect roi(roiOrigin.x, roiOrigin.y, originalImage.cols, originalImage.rows/12); | |||||
Point roiOrigin(0, int(originalImage.rows*(3.25/6.0))); | |||||
Rect roi(roiOrigin.x, roiOrigin.y, originalImage.cols, originalImage.rows/6); | |||||
//Mat processedImage = originalImage(roi); | //Mat processedImage = originalImage(roi); | ||||
Mat processedImage = originalImage; | Mat processedImage = originalImage; | ||||
//processedImage = processedImage(roi); | //processedImage = processedImage(roi); | ||||
FrameData data = processing.calculateLineSegments(processedImage, roi); | FrameData data = processing.calculateLineSegments(processedImage, roi); | ||||
processing.filterReflections(data); | processing.filterReflections(data); | ||||
this->provideOutput(originalImage, processedImage, data, roi); | |||||
int angle = processing.calcAngles(data, originalImage.cols, originalImage.rows, false); | |||||
this->provideOutput(originalImage, processedImage, data, roi, angle); | |||||
} | } | ||||
if(this->videoFlag) {destroyWindow("Display window");} | if(this->videoFlag) {destroyWindow("Display window");} | ||||
input.freeWebcam(); | input.freeWebcam(); | ||||
return; | return; | ||||
} | } | ||||
void LFR::provideOutput(Mat originalImage, Mat processedImage, const FrameData& frameData, const Rect& roi) | |||||
void LFR::provideOutput(Mat originalImage, Mat processedImage, const FrameData& frameData, const Rect& roi, const int angle) | |||||
{ | { | ||||
for(int i = 0; i < frameData.contours.size(); i++) | for(int i = 0; i < frameData.contours.size(); i++) | ||||
{ | { | ||||
rectangle(originalImage, center, Scalar(0,0,255)); | rectangle(originalImage, center, Scalar(0,0,255)); | ||||
Rect leftRect(Point(frameData.leftEdges[i].x-2, frameData.leftEdges[i].y-2), Point(frameData.leftEdges[i].x+2, frameData.leftEdges[i].y+2)); | Rect leftRect(Point(frameData.leftEdges[i].x-2, frameData.leftEdges[i].y-2), Point(frameData.leftEdges[i].x+2, frameData.leftEdges[i].y+2)); | ||||
rectangle(originalImage, leftRect, Scalar(0,0,255)); | rectangle(originalImage, leftRect, Scalar(0,0,255)); | ||||
int length = 100; | |||||
Point P1 = frameData.middlePoints[i]; | |||||
Point P2; | |||||
P2.x = (int)round(P1.x + length * cos(angle * CV_PI / 180.0)); | |||||
P2.y = (int)round(P1.y + length * sin(angle * CV_PI / 180.0)); | |||||
cv::arrowedLine(originalImage, P1, P2, Scalar(0,0,255), 2, 8); | |||||
} | } | ||||
if(this->videoFlag) | if(this->videoFlag) | ||||
{ | { |
int thresholdBinary; | int thresholdBinary; | ||||
int gaussKernelSize; | int gaussKernelSize; | ||||
void provideOutput(Mat originalImage, Mat processedImage, const FrameData& frameData, const Rect& roi); | |||||
void provideOutput(Mat originalImage, Mat processedImage, const FrameData& frameData, const Rect& roi, const int angle); | |||||
public: | public: | ||||