Vì vậy, nhiệm vụ của tôi là thế này - Tôi có một luồng GUI với một thanh trượt các giá trị HSV (trong số những thứ khác) và một luồng công việc thực hiện tất cả công việc OpenCV và gửi hình ảnh video đã xử lý trở lại luồng GUI.
Như thường lệ, OpenCV hoạt động theo vòng lặp vô hạn. Vấn đề là một nửa công việc đang chuyển đổi khung hình video hiện tại dựa trên giá trị HSV được gửi từ thanh trượt GUI. Nó hoạt động nếu được gửi trước khi vòng lặp bắt đầu. Nhưng không phải khi nó đang diễn ra, tôi cần nó hoạt động nhanh chóng.
Có cách nào tốt để giao tiếp với chuỗi này và thay đổi giá trị HSV đang được vòng lặp OpenCV sử dụng hay đây là một việc làm ngu ngốc? Tôi có thể nghĩ ra hai giải pháp, một trong số đó có thể không hiệu quả (liên quan đến việc lưu các giá trị vào một tệp). Tôi mới làm quen với Qt và rất dễ bỏ sót điều gì đó trong tài liệu và hướng dẫn.
EDIT: Đây là cách ứng dụng của tôi hoạt động - trong luồng GUI, người dùng chọn một tệp. Tín hiệu có url được gửi đến luồng công nhân và luồng công nhân bắt đầu hoạt động. Khi người dùng thay đổi giá trị HSV, tín hiệu sẽ được gửi để thay đổi giá trị từ một luồng khác. Nếu vòng lặp chưa bắt đầu, chúng sẽ được nhận và QDebug hiển thị cho tôi.
Chỉnh sửa 2: Có thể tôi đã nghĩ sai. Có cách nào để một luồng trích xuất một giá trị từ một luồng khác không? Thay vì chờ đợi chúng được gửi đi?
Chỉnh sửa 3: kalibracja.cpp, dành cho Micka.
int huếMin=0;
int HueMax=180;
int satMin=0;
int satMax=255;
int valMin=15;
int valMax=255;
int satMinDua=133;
HSV::HSV(QObject * cha mẹ) : QObject(cha mẹ)
{
hsvThread = QThread mới;
hsvThread ->start();
moveToThread( hsvThread );
}
HSV::~HSV() //bộ hủy
{
hsvThread ->exit(0);
hsvThread ->wait();
xóa hsvThread;
}
void HSV::processFrames(QString kalibracja) {
trong khi(1) {
cv::VideoCapture kalibrowanyPlik;
kalibrowanyPlik.open(kalibracja.toStdString());
int maxFrames = kalibrowanyPlik.get(CV_CAP_PROP_FRAME_COUNT);
for(int i=0; i
{
cv::Khung chiếu;
cv::Màu xám mờ;
//satMin=kontenerHsv->satMin;
qDebug() << "kalibracja satMin - " << satMin;
qDebug() << "fdfdf - " << satMinDua;
kalibrowanyPlik.read(frame);
cv::cvtColor(khung, màu xám, CV_BGR2GRAY);
Hình ảnh QImage(cvMatToQImage(frame));
QImage đã xử lýImage(cvMatToQImage(xám));
phát ra ProgressChanged(hình ảnh, hình ảnh đã xử lý);
QThread::msleep(750); //để tôi có thể đọc tin nhắn qDebug() một cách dễ dàng
}
}
}
void MainWindow::onProgressChagned(Hình ảnh QImage, Hình ảnh được xử lý QImage) {
QPixmap đã xử lý = QPixmap::fromImage(processedImage);
đã xử lý = đã xử lý.scaledToHeight(379);
ui->nhãnHsv->clear();
ui->labelHsv->setPixmap(đã xử lý);
QPixmap gốc = QPixmap::fromImage(hình ảnh);
gốc = original.scaledToHeight(379);
ui->nhãnKalibracja->clear();
ui->nhãnKalibracja->setPixmap(bản gốc);
}
void HSV::updateHsv(QString hmin, QString hmax, QString smin, QString smax, QString vmin, QString vmax){
satMinDua=smin.toInt();
}
kết nối mainwindow.cpp
HSV *hsv = HSV mới;
(....đủ thứ...)
void MainWindow::updateHsvValues() {
QMetaObject::invokeMethod(hsv, "updateHsv", Qt::QueuedConnection,
Q_ARG(QString, hmin),
Q_ARG(QString, hmax),
Q_ARG(QString, smin),
Q_ARG(QString, smax),
Q_ARG(QString, vmin),
Q_ARG(QString, vmax));
}
Điều đó chắc chắn là có thể, nhưng bạn cần phải cẩn thận.
Một cách để đạt được điều này là:
- Tạo đối tượng lưu trữ giá trị HSV "hiện tại" để sử dụng
- Cung cấp một tham chiếu (hoặc con trỏ) cho đối tượng này tới luồng GUI và luồng OpenCV
- Khi GUI muốn "yêu cầu" luồng xử lý sử dụng các giá trị mới, nó sẽ xuất bản chúng cho đối tượng này
- Khi luồng xử lý sẵn sàng nhập khung tiếp theo (phần thân vòng lặp bắt đầu), nó sẽ nhận giá trị từ đối tượng này.
Bạn chỉ cần đảm bảo rằng các phương thức set và get trên đối tượng dùng chung đó được đồng bộ hóa, ví dụ như sử dụng mutex, để ngăn luồng xử lý đọc một nửa giá trị được ghi (các cuộc chạy đua dữ liệu gây ra hành vi không xác định trong C++).
Tôi là một lập trình viên xuất sắc, rất giỏi!