|
@@ -1,6 +1,67 @@
|
|
#include "FeedLevelDetector.h"
|
|
#include "FeedLevelDetector.h"
|
|
#include <opencv2/imgproc.hpp>
|
|
#include <opencv2/imgproc.hpp>
|
|
#include <iostream>
|
|
#include <iostream>
|
|
|
|
+#include <thread>
|
|
|
|
+
|
|
|
|
+FeedLevelDetector::FeedLevelDetector() : captureInterval(10) {
|
|
|
|
+ camera.open(0); // 默认打开第一个摄像头
|
|
|
|
+ if (!camera.isOpened()) {
|
|
|
|
+ std::cerr << "Error: Could not open camera!" << std::endl;
|
|
|
|
+ }
|
|
|
|
+ lastCaptureTime = std::chrono::system_clock::now();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void FeedLevelDetector::setCaptureInterval(int interval) {
|
|
|
|
+ if (interval == 10 || interval == 30 || interval == 60) {
|
|
|
|
+ captureInterval = interval;
|
|
|
|
+ } else {
|
|
|
|
+ std::cerr << "Invalid interval. Using default (10s)." << std::endl;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+bool FeedLevelDetector::shouldCaptureNow() {
|
|
|
|
+ auto now = std::chrono::system_clock::now();
|
|
|
|
+ auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(now - lastCaptureTime).count();
|
|
|
|
+ return (elapsed >= captureInterval);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void FeedLevelDetector::startDetectionFromCamera() {
|
|
|
|
+ if (!camera.isOpened()) {
|
|
|
|
+ std::cerr << "Camera not available!" << std::endl;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ cv::Mat frame;
|
|
|
|
+ while (true) {
|
|
|
|
+ camera >> frame; // 获取当前帧
|
|
|
|
+ if (frame.empty()) break;
|
|
|
|
+
|
|
|
|
+ // 显示实时画面(但不处理)
|
|
|
|
+ cv::imshow("Camera Feed", frame);
|
|
|
|
+
|
|
|
|
+ // 按ESC退出
|
|
|
|
+ if (cv::waitKey(1) == 27) break;
|
|
|
|
+
|
|
|
|
+ // 检查是否到达采集时间
|
|
|
|
+ if (shouldCaptureNow()) {
|
|
|
|
+ cv::Mat processed = preprocessImage(frame);
|
|
|
|
+ float distance = findFeedSurface(processed);
|
|
|
|
+
|
|
|
|
+ // 显示结果
|
|
|
|
+ displayResult(frame, distance);
|
|
|
|
+ //std::cout << "[Detection] Distance: " << distance << " pixels" << std::endl;
|
|
|
|
+
|
|
|
|
+ // 更新时间戳
|
|
|
|
+ lastCaptureTime = std::chrono::system_clock::now();
|
|
|
|
+
|
|
|
|
+ // 控制台输出当前距离(可选)
|
|
|
|
+ std::cout << "Detected distance: " << distance << " pixels" << std::endl;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ camera.release();
|
|
|
|
+ cv::destroyAllWindows();
|
|
|
|
+}
|
|
|
|
|
|
cv::Mat FeedLevelDetector::preprocessImage(const cv::Mat& input) {
|
|
cv::Mat FeedLevelDetector::preprocessImage(const cv::Mat& input) {
|
|
cv::Mat gray, blurred;
|
|
cv::Mat gray, blurred;
|
|
@@ -18,8 +79,8 @@ float FeedLevelDetector::findFeedSurface(const cv::Mat& image) {
|
|
cv::Mat edges;
|
|
cv::Mat edges;
|
|
|
|
|
|
// Canny边缘检测
|
|
// Canny边缘检测
|
|
- //cv::Canny(image, edges, 100, 150);
|
|
|
|
- cv::Canny(image, edges, 100, 200);
|
|
|
|
|
|
+ cv::Canny(image, edges, 100, 150);
|
|
|
|
+ //cv::Canny(image, edges, 100, 200);
|
|
//cv::Canny(image, edges, 50, 100);
|
|
//cv::Canny(image, edges, 50, 100);
|
|
// 查找轮廓
|
|
// 查找轮廓
|
|
std::vector<std::vector<cv::Point>> contours;
|
|
std::vector<std::vector<cv::Point>> contours;
|
|
@@ -45,19 +106,45 @@ float FeedLevelDetector::findFeedSurface(const cv::Mat& image) {
|
|
}
|
|
}
|
|
|
|
|
|
void FeedLevelDetector::displayResult(cv::Mat& image, float distance) {
|
|
void FeedLevelDetector::displayResult(cv::Mat& image, float distance) {
|
|
|
|
+ // 创建显示副本
|
|
|
|
+ cv::Mat displayImage = image.clone();
|
|
|
|
+
|
|
// 绘制饲料表面线
|
|
// 绘制饲料表面线
|
|
- cv::line(image, cv::Point(0, distance),
|
|
|
|
|
|
+ cv::line(displayImage, cv::Point(0, distance),
|
|
cv::Point(image.cols-1, distance),
|
|
cv::Point(image.cols-1, distance),
|
|
cv::Scalar(0, 0, 255), 2);
|
|
cv::Scalar(0, 0, 255), 2);
|
|
|
|
+
|
|
|
|
+ // 显示距离信息
|
|
|
|
+ std::string infoText = "Interval: " + std::to_string(captureInterval) + "s | " +
|
|
|
|
+ "Distance: " + std::to_string(distance) + " pixels";
|
|
|
|
+
|
|
|
|
+ cv::putText(displayImage, infoText,
|
|
|
|
+ cv::Point(20, 30),
|
|
|
|
+ cv::FONT_HERSHEY_SIMPLEX,
|
|
|
|
+ 0.8, cv::Scalar(0, 255, 0), 2);
|
|
|
|
+
|
|
|
|
+ // 显示处理间隔信息
|
|
|
|
+ auto now = std::chrono::system_clock::now();
|
|
|
|
+ auto nextCapture = lastCaptureTime + std::chrono::seconds(captureInterval);
|
|
|
|
+ auto remain = std::chrono::duration_cast<std::chrono::seconds>(nextCapture - now).count();
|
|
|
|
+
|
|
|
|
+// std::string timerText = "Next capture in: " + std::to_string(remain) + "s";
|
|
|
|
+// cv::putText(displayImage, timerText,
|
|
|
|
+// cv::Point(20, 60),
|
|
|
|
+// cv::FONT_HERSHEY_SIMPLEX,
|
|
|
|
+// 0.6, cv::Scalar(255, 255, 0), 1);
|
|
|
|
+
|
|
|
|
+ // 更新显示
|
|
|
|
+ cv::imshow("Feed Level Monitoring", displayImage);
|
|
|
|
|
|
- // 显示距离信息(图像坐标系原点在左上角)
|
|
|
|
- std::string distanceText = "Distance: " + std::to_string(distance) + " pixels";
|
|
|
|
- cv::putText(image, distanceText, cv::Point(20, 30),
|
|
|
|
- cv::FONT_HERSHEY_SIMPLEX, 0.8, cv::Scalar(0, 255, 0), 2);
|
|
|
|
-
|
|
|
|
- // 显示图像
|
|
|
|
- cv::imshow("Feed Level Detection", image);
|
|
|
|
- cv::waitKey(0);
|
|
|
|
|
|
+// // 显示距离信息(图像坐标系原点在左上角)
|
|
|
|
+// std::string distanceText = "Distance: " + std::to_string(distance) + " pixels";
|
|
|
|
+// cv::putText(image, distanceText, cv::Point(20, 30),
|
|
|
|
+// cv::FONT_HERSHEY_SIMPLEX, 0.8, cv::Scalar(0, 255, 0), 2);
|
|
|
|
+//
|
|
|
|
+// // 显示图像
|
|
|
|
+// cv::imshow("Feed Level Detection", image);
|
|
|
|
+// cv::waitKey(0);
|
|
}
|
|
}
|
|
|
|
|
|
float FeedLevelDetector::detectFeedLevel(const std::string& imagePath) {
|
|
float FeedLevelDetector::detectFeedLevel(const std::string& imagePath) {
|