I am planning to detect a orange table tennis ball using OpenCV in Visual Studio and make a table tennis machine. My plan is to print two continuous coordinates only once when each time the ball is moving toward the machine(to calculate other info).
machine <—- human : captures two coordinates
machine —-> human : no coordinates captured
machine <—- human : captures two coordinates
But it’s not working like expected. I’m using two cameras and one is on top and the other is on the side of the table.
Here’s the code:
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#include <cmath>
#include <ctime>
#include <thread>
#include <atomic>
std::atomic<float> shared_m = 0.0;
std::atomic<float> shared_x = 0.0;
std::atomic<float> shared_y = 1000.0;
void processCameras() {
cv::VideoCapture cap1(1, cv::CAP_DSHOW);
cv::VideoCapture cap2(0, cv::CAP_DSHOW);
if (!cap1.isOpened()) {
std::cerr << "Error: Could not open video capture 1." << std::endl;
return;
}
if (!cap2.isOpened()) {
std::cerr << "Error: Could not open video capture 2." << std::endl;
return;
}
cap1.set(cv::CAP_PROP_FPS, 120);
cap2.set(cv::CAP_PROP_FPS, 120);
cv::Scalar lower_orange1(0, 60, 80);
cv::Scalar upper_orange1(40, 200, 255);
cv::Scalar lower_orange2(0, 50, 60);
cv::Scalar upper_orange2(40, 200, 255);
float prev_center_x1 = 0.0;
float prev_center_y1 = 0.0;
float prev_delta_y1 = 1;
int px_prev_center_x2 = 0;
int px_prev_center_y2 = 0;
int px_prev_delta_x2 = 1;
float prev_center_x2 = 0.0;
while (true) {
cv::Mat frame1, frame2;
cap1 >> frame1;
cap2 >> frame2;
if (frame1.empty() || frame2.empty()) {
break;
}
frame1 = frame1(cv::Range(80, 360), cv::Range(0, 640));
frame2 = frame2(cv::Range(130, 271), cv::Range(160, 400));
cv::Mat mask1;
cv::inRange(frame1, lower_orange1, upper_orange1, mask1);
cv::Rect boundingRect1 = cv::boundingRect(mask1);
int x1 = boundingRect1.x;
int y1 = boundingRect1.y;
int w1 = boundingRect1.width;
int h1 = boundingRect1.height;
if (w1 != 0) {
cv::rectangle(frame1, boundingRect1, cv::Scalar(0, 255, 0), 2);
int px_center_x1 = x1 + w1 / 2;
int px_center_y1 = y1 + h1 / 2;
float center_x1 = (float(px_center_x1) - 320.0) * 0.2375;
float center_y1 = (160 - float(px_center_y1)) * 0.2375;
float delta_y1 = center_y1 - prev_center_y1;
if (delta_y1 < 0 && prev_delta_y1 > 0) {
if (center_x1 != prev_center_x1) {
float m = (center_y1 - prev_center_y1) / (center_x1 - prev_center_x1);
shared_m = m;
shared_x = center_x1;
shared_y = center_y1;
float estimated_location = (center_y1 - 225.0) / m + center_x1;
printf("shared_y = %fn", center_y1);
}
else {
float center_x1 = (float(px_center_x1) - 320.0) * 0.2375;
float center_y1 = (160 - float(px_center_y1)) * 0.2375;
float m = 10000.0;
shared_m = m;
shared_x = center_x1;
shared_y = center_y1;
float estimated_location = center_x1;
printf("shared_y = %fn", center_y1);
}
}
prev_center_x1 = center_x1;
prev_center_y1 = center_y1;
prev_delta_y1 = delta_y1;
}
cv::Mat mask2;
cv::inRange(frame2, lower_orange2, upper_orange2, mask2);
cv::Rect boundingRect2 = cv::boundingRect(mask2);
int x2 = boundingRect2.x;
int y2 = boundingRect2.y;
int w2 = boundingRect2.width;
int h2 = boundingRect2.height;
int center_x2 = (x2 + w2) / 2;
int center_y2 = (y2 + h2) / 2;
if (w2 != 0) {
cv::rectangle(frame2, boundingRect2, cv::Scalar(0, 255, 0), 2);
int px_center_x2 = x2 + w2 / 2;
int px_center_y2 = y2 + h2 / 2;
float center_x2 = px_center_x2 * 0.5625 - 90.0;
float px_delta_x2 = px_center_y2 - px_prev_center_y2;
if (px_delta_x2 < 0 && px_prev_delta_x2 > 0 && shared_y != 1000.0) {
float sidecam_m = -center_x2 / 287;
float topcam_m = shared_m;
float topcam_x = shared_x;
float topcam_y = shared_y;
float intersection_x = (287.0 - sidecam_m - center_x2 - topcam_m * topcam_x;
float h = (110 - prev_center_x2) * 0.63542f * (287 - intersection_x);
printf("h = %fn", h);
shared_y = 1000.0;
}
px_prev_center_x2 = px_center_x2;
px_prev_center_y2 = px_center_y2;
px_prev_delta_x2 = px_delta_x2;
prev_center_x2 = center_x2;
}
cv::imshow("Frame1", frame1);
cv::imshow("Frame2", frame2);
if ((cv::waitKey(1) & 0xFF) == 'q') {
break;
}
}
cap1.release();
cap2.release();
cv::destroyAllWindows();
}
Tried comparing two cordinate’s delta and previous delta. But it ramdomly skips printing.
Gyeom Hwangbo is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.