Siemka. Możecie mi pomóc zwiększyć dokładność programu lub zaproponować jakieś inne pomysły?
Potrzebuję programu do śledzenia położenia kuli na płaszczyźnie za pomocą kamery. Wymaganiami jest optymalność, chciałbym to zaimplementować na mikrokontrolerze STM32, oraz dokładność i czas reakcji. Nie mogę dopuścić do sytuacji aby kula spadła z płaszczyzny, dlatego muszę szybko znajdować jej położenie by odpowiednio zareagować silnikami, najlepiej min. 30fps.
Napisałem na kompie przykładowy program realizujący takie zadanie, lecz przy ruchu kamery czasami program nie znajduje kuli lub znajduje je tam gdzie ich nie ma. Dopasowanie okręgu nie zawsze jest też precyzyjne. Problem stanowi również rodzaj oświetlenia, a im szybszy ruch tym większe problemy.
Może moglibyście mi doradzić co mógłbym zmienić by poprawić jakość znajdowania położenia kuli lub wskazać coś co warto byłoby przeczytać :D
Poniżej wstawiam kod.
int main(int argc, char** argv) {
// Load input image
VideoCapture capture = VideoCapture(1);
cv::Mat bgr_image;
while (waitKey(20) != 27) {
capture >> bgr_image;
bgr_image.copyTo(orig_image);
cv::medianBlur(bgr_image, bgr_image, 3);
// Convert input image to HSV
cv::Mat hsv_image;
cv::cvtColor(bgr_image, hsv_image, cv::COLOR_BGR2HSV);
// Threshold the HSV image, keep only the red pixels
cv::Mat lower_red_hue_range;
cv::Mat upper_red_hue_range;
cv::inRange(hsv_image, cv::Scalar(0, 100, 100), cv::Scalar(10, 255, 255), lower_red_hue_range);
cv::inRange(hsv_image, cv::Scalar(160, 100, 100), cv::Scalar(179, 255, 255), upper_red_hue_range);
// Combine the above two images
cv::Mat red_hue_image;
cv::addWeighted(lower_red_hue_range, 1.0, upper_red_hue_range, 1.0, 0.0, red_hue_image);
cv::GaussianBlur(red_hue_image, red_hue_image, cv::Size(9, 9), 2, 2);
// Use the Hough transform to detect circles in the combined threshold image
std::vector<cv::Vec3f> circles;
cv::HoughCircles(red_hue_image, circles, HOUGH_GRADIENT, 1, red_hue_image.rows / 8, 100, 20, 0, 0);
// Loop over all detected circles and outline them on the original image
for (size_t current_circle = 0; current_circle < circles.size(); ++current_circle) {
cv::Point center(std::round(circles[current_circle][0]), std::round(circles[current_circle][1]));
int radius = std::round(circles[current_circle][2]);
cv::circle(orig_image, center, radius, cv::Scalar(0, 255, 0), 5);
}
// Show images
cv::namedWindow("Threshold lower image", cv::WINDOW_AUTOSIZE);
cv::imshow("Threshold lower image", lower_red_hue_range);
cv::namedWindow("Threshold upper image", cv::WINDOW_AUTOSIZE);
cv::imshow("Threshold upper image", upper_red_hue_range);
cv::namedWindow("Combined threshold images", cv::WINDOW_AUTOSIZE);
cv::imshow("Combined threshold images", red_hue_image);
cv::namedWindow("Detected red circles on the input image", cv::WINDOW_AUTOSIZE);
cv::imshow("Detected red circles on the input image", orig_image);
}
return 0;
}
Nie mogę dopuścić do sytuacji aby kula spadła z płaszczyzny
" - więc mocowanie do podłogi odpada.