This commit is contained in:
parent
0f80eccfd3
commit
b1d50517c6
|
|
@ -126,6 +126,105 @@ void loadMarkerPositions(const std::string& filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void processFrame(const cv::Mat& frame, std::map<int, cv::Point2f>& markerPositions, cv::Mat& transformationMatrix, bool& calibrationDone)
|
||||||
|
{
|
||||||
|
// Apply image processing steps
|
||||||
|
cv::Mat processedFrame = gammaCorrection(frame, 0.4);
|
||||||
|
processedFrame = sharpenImage(processedFrame);
|
||||||
|
processedFrame = upscaleImage(processedFrame, 3.0);
|
||||||
|
processedFrame = reduceNoise(processedFrame);
|
||||||
|
processedFrame = enhanceImage(processedFrame);
|
||||||
|
processedFrame = equalizeHistogram(processedFrame);
|
||||||
|
processedFrame = adaptiveThresholding(processedFrame);
|
||||||
|
|
||||||
|
// Create ArUco marker detector
|
||||||
|
cv::Ptr<cv::aruco::Dictionary> dictionary =
|
||||||
|
cv::aruco::getPredefinedDictionary(cv::aruco::DICT_4X4_50);
|
||||||
|
std::vector<int> markerIds;
|
||||||
|
std::vector<std::vector<cv::Point2f>> markerCorners;
|
||||||
|
std::vector<cv::Vec3d> rvecs, tvecs;
|
||||||
|
|
||||||
|
// Detect markers in the image
|
||||||
|
cv::aruco::detectMarkers(processedFrame, dictionary, markerCorners, markerIds);
|
||||||
|
|
||||||
|
// Draw detected markers
|
||||||
|
if (!markerIds.empty())
|
||||||
|
{
|
||||||
|
cv::aruco::drawDetectedMarkers(processedFrame, markerCorners, markerIds);
|
||||||
|
cv::aruco::estimatePoseSingleMarkers(markerCorners, 0.05, cameraMatrix, distCoeffs, rvecs, tvecs);
|
||||||
|
ROS_INFO("Detected %zu ArUco markers", markerIds.size());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < markerIds.size(); ++i)
|
||||||
|
{
|
||||||
|
ROS_INFO("Marker ID: %d", markerIds[i]);
|
||||||
|
cv::aruco::drawAxis(processedFrame, cameraMatrix, distCoeffs, rvecs[i], tvecs[i], 0.1);
|
||||||
|
|
||||||
|
// Print the rotation and translation vectors
|
||||||
|
ROS_INFO_STREAM("Rotation Vector: " << rvecs[i]);
|
||||||
|
ROS_INFO_STREAM("Translation Vector: " << tvecs[i]);
|
||||||
|
|
||||||
|
// Calculate the distance from the camera to the marker
|
||||||
|
double distance = cv::norm(tvecs[i]);
|
||||||
|
ROS_INFO("Distance from camera: %f meters", distance);
|
||||||
|
|
||||||
|
// Convert rotation vector to rotation matrix
|
||||||
|
cv::Mat rotationMatrix;
|
||||||
|
cv::Rodrigues(rvecs[i], rotationMatrix);
|
||||||
|
|
||||||
|
// Extract Euler angles from the rotation matrix
|
||||||
|
cv::Vec3d eulerAngles;
|
||||||
|
eulerAngles[0] = atan2(rotationMatrix.at<double>(2, 1), rotationMatrix.at<double>(2, 2)); // Roll
|
||||||
|
eulerAngles[1] = atan2(-rotationMatrix.at<double>(2, 0), sqrt(pow(rotationMatrix.at<double>(2, 1), 2) + pow(rotationMatrix.at<double>(2, 2), 2))); // Pitch
|
||||||
|
eulerAngles[2] = atan2(rotationMatrix.at<double>(1, 0), rotationMatrix.at<double>(0, 0)); // Yaw
|
||||||
|
|
||||||
|
ROS_INFO_STREAM("Euler Angles (Roll, Pitch, Yaw): " << eulerAngles);
|
||||||
|
|
||||||
|
// Save the marker position
|
||||||
|
markerPositions[markerIds[i]] = cv::Point2f(tvecs[i][0], tvecs[i][1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute the transformation matrix (example using homography)
|
||||||
|
if (markerIds.size() >= 3) // Need at least 3 points to compute homography
|
||||||
|
{
|
||||||
|
std::vector<cv::Point2f> srcPoints;
|
||||||
|
std::vector<cv::Point3f> dstPoints;
|
||||||
|
for (const auto& marker : markerPositions)
|
||||||
|
{
|
||||||
|
if (fixedMarkerPositions.find(marker.first) != fixedMarkerPositions.end())
|
||||||
|
{
|
||||||
|
srcPoints.push_back(marker.second);
|
||||||
|
dstPoints.push_back(fixedMarkerPositions[marker.first]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (srcPoints.size() >= 3)
|
||||||
|
{
|
||||||
|
transformationMatrix = cv::findHomography(srcPoints, dstPoints);
|
||||||
|
calibrationDone = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ROS_INFO("No ArUco markers detected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void frameProcessingThread(cv::VideoCapture& cap, std::map<int, cv::Point2f>& markerPositions, cv::Mat& transformationMatrix, bool& calibrationDone)
|
||||||
|
{
|
||||||
|
while (ros::ok() && !calibrationDone)
|
||||||
|
{
|
||||||
|
cv::Mat frame;
|
||||||
|
cap >> frame; // Capture a new frame
|
||||||
|
if (frame.empty())
|
||||||
|
{
|
||||||
|
ROS_ERROR("Captured empty frame");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
processFrame(frame, markerPositions, transformationMatrix, calibrationDone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void calibrateArena()
|
void calibrateArena()
|
||||||
{
|
{
|
||||||
// Create ArUco marker detector
|
// Create ArUco marker detector
|
||||||
|
|
@ -157,6 +256,9 @@ void calibrateArena()
|
||||||
|
|
||||||
bool calibrationDone = false;
|
bool calibrationDone = false;
|
||||||
|
|
||||||
|
// Start the frame processing thread
|
||||||
|
std::thread processingThread(frameProcessingThread, std::ref(cap), std::ref(markerPositions), std::ref(transformationMatrix), std::ref(calibrationDone));
|
||||||
|
|
||||||
while (ros::ok() && !calibrationDone)
|
while (ros::ok() && !calibrationDone)
|
||||||
{
|
{
|
||||||
cap >> frame; // Capture a new frame
|
cap >> frame; // Capture a new frame
|
||||||
|
|
@ -166,84 +268,13 @@ void calibrateArena()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply image processing steps
|
// Display the original frame for debugging
|
||||||
frame = gammaCorrection(frame, 0.4);
|
|
||||||
frame = sharpenImage(frame);
|
|
||||||
frame = upscaleImage(frame, 3.0);
|
|
||||||
frame = reduceNoise(frame);
|
|
||||||
frame = enhanceImage(frame);
|
|
||||||
frame = equalizeHistogram(frame);
|
|
||||||
frame = adaptiveThresholding(frame);
|
|
||||||
|
|
||||||
// Detect markers in the image
|
|
||||||
cv::aruco::detectMarkers(frame, dictionary, markerCorners, markerIds);
|
|
||||||
|
|
||||||
// Draw detected markers
|
|
||||||
if (!markerIds.empty())
|
|
||||||
{
|
|
||||||
cv::aruco::drawDetectedMarkers(frame, markerCorners, markerIds);
|
|
||||||
cv::aruco::estimatePoseSingleMarkers(markerCorners, 0.05, cameraMatrix, distCoeffs, rvecs, tvecs);
|
|
||||||
ROS_INFO("Detected %zu ArUco markers", markerIds.size());
|
|
||||||
|
|
||||||
for (size_t i = 0; i < markerIds.size(); ++i)
|
|
||||||
{
|
|
||||||
ROS_INFO("Marker ID: %d", markerIds[i]);
|
|
||||||
cv::aruco::drawAxis(frame, cameraMatrix, distCoeffs, rvecs[i], tvecs[i], 0.1);
|
|
||||||
|
|
||||||
// Print the rotation and translation vectors
|
|
||||||
ROS_INFO_STREAM("Rotation Vector: " << rvecs[i]);
|
|
||||||
ROS_INFO_STREAM("Translation Vector: " << tvecs[i]);
|
|
||||||
|
|
||||||
// Calculate the distance from the camera to the marker
|
|
||||||
double distance = cv::norm(tvecs[i]);
|
|
||||||
ROS_INFO("Distance from camera: %f meters", distance);
|
|
||||||
|
|
||||||
// Convert rotation vector to rotation matrix
|
|
||||||
cv::Mat rotationMatrix;
|
|
||||||
cv::Rodrigues(rvecs[i], rotationMatrix);
|
|
||||||
|
|
||||||
// Extract Euler angles from the rotation matrix
|
|
||||||
cv::Vec3d eulerAngles;
|
|
||||||
eulerAngles[0] = atan2(rotationMatrix.at<double>(2, 1), rotationMatrix.at<double>(2, 2)); // Roll
|
|
||||||
eulerAngles[1] = atan2(-rotationMatrix.at<double>(2, 0), sqrt(pow(rotationMatrix.at<double>(2, 1), 2) + pow(rotationMatrix.at<double>(2, 2), 2))); // Pitch
|
|
||||||
eulerAngles[2] = atan2(rotationMatrix.at<double>(1, 0), rotationMatrix.at<double>(0, 0)); // Yaw
|
|
||||||
|
|
||||||
ROS_INFO_STREAM("Euler Angles (Roll, Pitch, Yaw): " << eulerAngles);
|
|
||||||
|
|
||||||
// Save the marker position
|
|
||||||
markerPositions[markerIds[i]] = cv::Point2f(tvecs[i][0], tvecs[i][1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute the transformation matrix (example using homography)
|
|
||||||
if (markerIds.size() >= 3) // Need at least 3 points to compute homography
|
|
||||||
{
|
|
||||||
std::vector<cv::Point2f> srcPoints;
|
|
||||||
std::vector<cv::Point3f> dstPoints;
|
|
||||||
for (const auto& marker : markerPositions)
|
|
||||||
{
|
|
||||||
if (fixedMarkerPositions.find(marker.first) != fixedMarkerPositions.end())
|
|
||||||
{
|
|
||||||
srcPoints.push_back(marker.second);
|
|
||||||
dstPoints.push_back(fixedMarkerPositions[marker.first]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (srcPoints.size() >= 3)
|
|
||||||
{
|
|
||||||
transformationMatrix = cv::findHomography(srcPoints, dstPoints);
|
|
||||||
calibrationDone = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ROS_INFO("No ArUco markers detected");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display the result
|
|
||||||
cv::imshow("Arena Calibration", frame);
|
cv::imshow("Arena Calibration", frame);
|
||||||
if (cv::waitKey(30) == 27) break; // Exit on ESC key
|
if (cv::waitKey(30) == 27) break; // Exit on ESC key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processingThread.join();
|
||||||
|
|
||||||
if (calibrationDone)
|
if (calibrationDone)
|
||||||
{
|
{
|
||||||
// Save the transformation matrix to a configuration file
|
// Save the transformation matrix to a configuration file
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue