Я обнаружил операцию .detach () и нашел что-то, что, кажется, работает, по крайней мере, когда я запускаю весь свой код, я получаю, казалось бы, очень стабильную работу, я не замечаю разгон памяти или использование процессора, и все открывается / закрывается / завершается без ошибок. Я поместил псевдокод ниже, чтобы продемонстрировать его суть.
Обеспечивает ли операция detach (), что каждый поток уничтожает себя после завершения? Я не горжусь использованием глобалов, но это первая попытка, которая пока позволяет мне работать на полной скорости (30 кадров в секунду). Я заметил, что с помощью этих потоков мое общее время вокруг цикла main () значительно сокращается, так что теперь во времени преобладает ожидание готовности следующего изображения с веб-камеры, как и ожидалось.
// ...
// globals
bool g_histodone = true;
string g_histwindow = "histogram";
Mat g_webcamImage;
// thread routine
void histogram(Mat Image, double offset, double gain, bool agc)
{
Mat scaledImage;
if (agc) {
resizedImage.convertTo(scaledImage, -1, 1, offset);
resizedImage.convertTo(scaledImage, -1, gain);
}
else
resizedImage.copyTo(scaledImage);
// compute histogram image
// ...
// display it
imshow(g_histwindow, histImage);
// notify main()
g_histodone = true;
}
void get_webcam_image(void)
{
// put images into g_webcamImage (actually a group of rotating buffers) as they come in from webcam
}
int main(int argc, const char *argv[])
{
bool agc = true;
bool histo = false;
bool histwindow_not_destroyed = false;
double offset = 0;
double gain = 1;
Mat localImage;
thread th_capture = thread(get_webcam_image); // start thread to get webcam images
thread th_histo = thread(histogram, localImage, offset, gain, agc); // start thread for histogram display
while (true) {
// wait here to grab the next camera image from buffers and put it into a local Mat
g_webcamImage.copyTo(localImage);
// do some optional processing to determine gain/offset (would be its own thread too)
if (agc) {
offset = result 1 from agc thread
gain = result 2 from agc thread
// apply scaling to the Mat
localImage.convertTo(localImage, -1, 1, offset);
localImage.convertTo(localImage, -1, gain);
}
// compute and show histogram
if (histo) {
if (g_histodone) { // previous thread is finished, start another
g_histodone = false;
if (th_histo.joinable())
th_histo.join();
th_histo = thread(histogram, localImage, offset, gain, agc);
}
}
// clean up
else if (histwindow_not_destroyed) {
destroyWindow(g_histwindow);
histwindow_not_destroyed = false; // handshaking
}
// ...
// get user keyboard input
if (key-to-toggle-histogram-pressed) {
histo = !histo;
if (histo)
namedWindow(g_histwindow, WINDOW_AUTOSIZE); // only want window to appear when enabled
else
histwindow_not_destroyed = true; // handshaking
}
else if (key-to-toggle-agc-pressed)
agc = !agc;
else if (key-to-terminate-app-pressed) {
th_capture.detach(); // terminate the webcam capture thread
if (th_histo.joinable())
th_histo.join(); // terminate the histo thread
return 0;
}
}
}
Что касается подхода Фареанора, он выглядит лучше, так как он передает значения в один поток, как я и собирался, но не знал точно, как это сделать; Я не знал потока, если объявленный вне цикла while () мог автоматически видеть переменные при их обновлении (это потому, что поток использует адрес, а не буквальное значение?) Я догадывался, что переменные передаются статически только при время, когда поток был объявлен. Так что приятно знать, я попробую.
Любой совет, как получить переменные, передаваемые из потока в main (), такие как мои вычисленные значения усиления и смещения agc? Если я объявлю структуру, содержащую два двойных числа, то должно ли это работать?
thread th_agc (agcparams = calc_agc, localImage);
где calc_agc - моя подпрограмма типа struct_agcparams для потока, localImage - это Mat, а agcparams содержит двойники усиления / смещения, которые я пытаюсь передать обратно.
или это так?
agcparams = thread th_agc (calc_agc, localImage);