FeedLevelDetector.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #include "FeedLevelDetector.h"
  2. #include <opencv2/imgproc.hpp>
  3. #include <iostream>
  4. #include <thread>
  5. FeedLevelDetector::FeedLevelDetector() : captureInterval(10), useCamera(false) {
  6. lastCaptureTime = std::chrono::system_clock::now();
  7. }
  8. void FeedLevelDetector::setCaptureInterval(int interval) {
  9. if (interval == 10 || interval == 30 || interval == 60) {
  10. captureInterval = interval;
  11. } else {
  12. std::cerr << "Invalid interval. Using default (10s)." << std::endl;
  13. }
  14. }
  15. bool FeedLevelDetector::shouldCaptureNow() {
  16. auto now = std::chrono::system_clock::now();
  17. auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(now - lastCaptureTime).count();
  18. return (elapsed >= captureInterval);
  19. }
  20. void FeedLevelDetector::startDetectionFromCamera() {
  21. useCamera = true; // 标记为摄像头模式
  22. camera.open(0); // 打开摄像头
  23. if (!camera.isOpened()) {
  24. std::cerr << "Camera not available!" << std::endl;
  25. return;
  26. }
  27. cv::Mat frame;
  28. while (true) {
  29. camera >> frame; // 获取当前帧
  30. if (frame.empty()) break;
  31. // 显示实时画面(但不处理)
  32. cv::imshow("Camera Feed", frame);
  33. // 按ESC退出
  34. if (cv::waitKey(1) == 27) break;
  35. // 检查是否到达采集时间
  36. if (shouldCaptureNow()) {
  37. cv::Mat processed = preprocessImage(frame);
  38. float distance = findFeedSurface(processed);
  39. // 显示结果
  40. displayResult(frame, distance);
  41. //std::cout << "[Detection] Distance: " << distance << " pixels" << std::endl;
  42. // 更新时间戳
  43. lastCaptureTime = std::chrono::system_clock::now();
  44. // 控制台输出当前距离(可选)
  45. std::cout << "Detected distance: " << distance << " pixels" << std::endl;
  46. }
  47. }
  48. camera.release();
  49. cv::destroyAllWindows();
  50. }
  51. cv::Mat FeedLevelDetector::preprocessImage(const cv::Mat& input) {
  52. cv::Mat gray, blurred;
  53. // 转换为灰度图像
  54. cv::cvtColor(input, gray, cv::COLOR_BGR2GRAY);
  55. cv::imshow("gray image", gray);
  56. // 高斯模糊去噪
  57. //cv::GaussianBlur(gray, blurred, cv::Size(5, 5), 1.5);
  58. cv::GaussianBlur(gray, blurred, cv::Size(7, 7), 3.0);
  59. cv::imshow("blurred image", blurred);
  60. return blurred;
  61. }
  62. float FeedLevelDetector::findFeedSurface(const cv::Mat& image) {
  63. cv::Mat edges;
  64. // Canny边缘检测
  65. //cv::Canny(image, edges, 150, 200);
  66. cv::Canny(image, edges, 50, 100);
  67. cv::imshow("edges image", edges);
  68. //cv::Canny(image, edges, 50, 100);
  69. // 查找轮廓
  70. std::vector<std::vector<cv::Point>> contours;
  71. cv::findContours(edges, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
  72. float minY = image.rows; // 初始设置为图像高度
  73. // 查找所有轮廓中的最高点(距离顶部最近的点)
  74. for (const auto& contour : contours) {
  75. for (const auto& point : contour) {
  76. if (point.y < minY) {
  77. minY = point.y;
  78. }
  79. }
  80. }
  81. // 如果没有找到轮廓,返回图像高度
  82. if (minY == image.rows) {
  83. return image.rows;
  84. }
  85. return minY;
  86. }
  87. void FeedLevelDetector::displayResult(cv::Mat& image, float distance) {
  88. // 创建显示副本
  89. cv::Mat displayImage = image.clone();
  90. // 绘制饲料表面线
  91. cv::line(displayImage, cv::Point(0, distance),
  92. cv::Point(image.cols-1, distance),
  93. cv::Scalar(0, 0, 255), 2);
  94. // 显示距离信息
  95. std::string infoText = "Interval: " + std::to_string(captureInterval) + "s | " +
  96. "Distance: " + std::to_string(distance) + " pixels";
  97. cv::putText(displayImage, infoText,
  98. cv::Point(20, 30),
  99. cv::FONT_HERSHEY_SIMPLEX,
  100. 0.8, cv::Scalar(0, 255, 0), 2);
  101. // 显示处理间隔信息
  102. auto now = std::chrono::system_clock::now();
  103. auto nextCapture = lastCaptureTime + std::chrono::seconds(captureInterval);
  104. auto remain = std::chrono::duration_cast<std::chrono::seconds>(nextCapture - now).count();
  105. // 更新显示
  106. cv::imshow("Feed Level Monitoring", displayImage);
  107. }
  108. float FeedLevelDetector::detectFeedLevel(const std::string& imagePath) {
  109. // 读取图像
  110. cv::Mat image = cv::imread(imagePath);
  111. if (image.empty()) {
  112. std::cerr << "Could not open or find the image: " << imagePath << std::endl;
  113. return -1;
  114. }
  115. // 预处理图像
  116. cv::Mat processed = preprocessImage(image);
  117. // 检测饲料表面
  118. float distance = findFeedSurface(processed);
  119. // 显示结果
  120. displayResult(image, distance);
  121. return distance;
  122. }