在OpenCL-OpenCV-Realtime-Threads中正确使用互斥锁
Correctly using mutex in OpenCL-OpenCV-Realtime-Threads?
本文关键字:OpenCL-OpenCV-Realtime-Threads 更新时间:2023-10-16
我试图在gpu线程中通过usb网络摄像头实时获得立体声视频流(比通过cpu获取和处理图像快得多),在第二个线程中处理该流以获取面部并通过键盘在主函数中控制线程(将在稍后实现)。目前,代码正常运行(显示链接/Rechts,并在我的脸周围画一个矩形)约30秒,然后崩溃,因为"……未处理的异常(opencv_core2499 .dll)".
我尝试使用互斥锁保护来处理变量"链接"/"Rechts"和面孔,但我不确定如何在Mat-context中使用它们,因为我没有找到任何适合OpenCV的例子。另外:它是正确的如何引用链接/Rechts/面对线程/它是最快的线程安全的品种?
我的互斥锁被排除在代码之外。谢谢你的帮助。
#include <thread>
#include <iostream>
#include <functional>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/ocl/ocl.hpp"
#include <mutex>
using namespace std;
using namespace cv;
Mat Links = Mat::zeros(960,1080, CV_8UC3);
Mat Rechts = Mat::zeros(960,1080, CV_8UC3);
Mat facesMat =Mat::zeros(960,1080,CV_8UC3);
std::vector<Rect> faces;
void change(Mat& Links, Mat& Rechts)
{
Mat captureFrame;
VideoCapture LeftCam(1);
VideoCapture RightCam(0);
LeftCam.set(CV_CAP_PROP_FRAME_WIDTH,1920);
LeftCam.set(CV_CAP_PROP_FRAME_HEIGHT,1080);
RightCam.set(CV_CAP_PROP_FRAME_WIDTH,1920);
RightCam.set(CV_CAP_PROP_FRAME_HEIGHT,1080);
FileStorage fs, fs2, fs3, fs4;
Mat map1x, map1y, map2x, map2y;
Mat mapi1x, mapi1y, mapi2x, mapi2y;
fs.open("mx1.xml", FileStorage::READ);
fs2.open("my1.xml", FileStorage::READ);
fs3.open("mx2.xml", FileStorage::READ);
fs4.open("my2.xml", FileStorage::READ);
fs["mx1"] >> map1x;
fs2["my1"] >> map1y;
fs3["mx2"] >> map2x;
fs4["my2"] >> map2y;
fs.release();
fs2.release();
fs3.release();
fs4.release();
ocl::oclMat map1xocl(map1x), map1yocl(map1y), map2xocl(map2x), map2yocl(map2y);
while (true)
{
cv::Mat3b frame0, frame1, LeftframeRaw, RightframeRaw, LeftRoi, RightRoi, framecon;
LeftCam >> frame0;
RightCam >> frame1;
LeftRoi = frame0(Rect(420,60,1080,960)); //960*1080 passend zuschneiden
RightRoi = frame1(Rect(420,60,1080,960));
ocl::oclMat Leftr(LeftRoi), Rightr(RightRoi), Leftt, Lefttf, Rightt, Righttf, LeftRemappedocl, RightRemappedocl;
ocl::transpose(Leftr, Leftt); //ACHTUNG: ocl::transpose src darf nicht dst-image sein, sonst gibts starke Bildartefakte!
ocl::transpose(Rightr, Rightt);
ocl::flip(Leftt, Lefttf, 1); //ACHTUNG: ocl::flip src darf nicht dst-image sein, sonst gibts starke Bildartefakte!
ocl::flip(Rightt, Rightt, 1);
ocl::remap(Lefttf, LeftRemappedocl, map1xocl, map1yocl, CV_INTER_LINEAR, BORDER_CONSTANT, 0);
ocl::remap(Rightt, RightRemappedocl, map2xocl, map2yocl, CV_INTER_LINEAR, BORDER_CONSTANT, 0);
Links = LeftRemappedocl.clone(); //kopiere sauber in neues Mat: leer
Rechts = RightRemappedocl.clone(); //kopiere sauber in neues Mat: leer
}
}
void facefind(Mat& f, vector<Rect>&e)
{
CascadeClassifier face_cascade;
face_cascade.load("haarcascade_frontalface_alt.xml");
while (true)
{
Mat Lokalesf;
Lokalesf = f.clone();
Mat grau;
cvtColor(Lokalesf, grau, CV_BGR2GRAY);
equalizeHist(grau, grau);
face_cascade.detectMultiScale(grau, faces, 1.1, 3, CASCADE_SCALE_IMAGE|CV_HAAR_SCALE_IMAGE, Size(30,30));
e=faces; //kopiere sauber in neues vector<rect>
}
}
int main()
{
Mat stereo;
std::thread t1(change,std::ref(Links),std::ref(Rechts));
std::thread t2(facefind,std::ref(Links),std::ref(faces));
while (true)
{
for(int i = 0; i < faces.size(); i++)
{
Point pt1(faces[i].x + faces[i].width, faces[i].y + faces[i].height);
Point pt2(faces[i].x, faces[i].y);
rectangle(Links, pt1, pt2, cvScalar(0, 255, 0, 0), 1, 8, 0);
}
imshow("rechts", Rechts);
imshow("links", Links);
waitKey(10);
}
t1.join();
t2.join();
return 0;
}
编辑:我试着理解Mr.Worshipme的代码,并包括我的代码使其工作。我得到了两个关于大小的断言错误。宽度/高度在cv::imshow和ROI,谁能帮我吗?#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <cmath>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/ocl/ocl.hpp"
#include <functional>
using namespace std;
using namespace cv;
typedef unsigned char uchar;
typedef unsigned int uint;
class FaceDetector
{
mutex imageLock, facesLock;
condition_variable imageAqcuired;
bool newImageAvailable;
Mat _img;
Mat _imgToWorkOn;
Mat _faceImages;
bool quit;
void acquireImage()
{
Mat captureFrame;
VideoCapture LeftCam(1);
LeftCam.set(CV_CAP_PROP_FRAME_WIDTH,1920);
LeftCam.set(CV_CAP_PROP_FRAME_HEIGHT,1080);
FileStorage fs, fs2;
Mat map1x, map1y;
Mat mapi1x, mapi1y;
fs.open("mx1.xml", FileStorage::READ);
fs2.open("my1.xml", FileStorage::READ);
fs["mx1"] >> map1x;
fs2["my1"] >> map1y;
fs.release();
fs2.release();
ocl::oclMat map1xocl(map1x), map1yocl(map1y);
while (!quit)
{
unique_lock<mutex> ulock(imageLock);
imageAqcuired.wait(ulock,[&](){return !newImageAvailable;}); //only take
//new image after current one was consumed
cv::Mat3b frame0, frame1, LeftframeRaw, RightframeRaw, LeftRoi, RightRoi,framecon;
LeftCam >> frame0;
LeftRoi=frame0(Rect(420,60,1080,960)); //960*1080 passend zuschneiden
ocl::oclMat Leftr(LeftRoi), Leftt, Lefttf, LeftRemappedocl;
ocl::transpose(Leftr, Leftt); //ACHTUNG: ocl::transpose src darf nicht dst-image sein, sonst gibts starke Bildartefakte!
ocl::flip(Leftt, Lefttf, 1); //ACHTUNG: ocl::flip src darf nicht dst-image sein, sonst gibts starke Bildartefakte!
ocl::remap(Lefttf, LeftRemappedocl, map1xocl, map1yocl, CV_INTER_LINEAR, BORDER_CONSTANT, 0);
_img = LeftRemappedocl.clone();
ulock.unlock();
newImageAvailable = true;
imageAqcuired.notify_one(); //notify that a new image is available
}
}
void processImage()
{
CascadeClassifier face_cascade;
face_cascade.load("haarcascade_frontalface_alt.xml");
while (!quit)
{
unique_lock<mutex> ulock(imageLock);
imageAqcuired.wait(ulock,[&](){return newImageAvailable;}); //wait untill a new image is available
_imgToWorkOn = _img;
ulock.unlock();
newImageAvailable = false;
imageAqcuired.notify_one(); //notify the current image can be replaced by a newer one
unique_lock<mutex> lockFace(facesLock);
Mat grau;
cvtColor(_imgToWorkOn, grau, CV_BGR2GRAY);
equalizeHist(grau, grau);
std::vector<Rect> faces;
face_cascade.detectMultiScale(grau, faces, 1.1, 3, CASCADE_SCALE_IMAGE|CV_HAAR_SCALE_IMAGE, Size(30,30));
for(int i = 0; i < faces.size(); i++)
{
Point pt1(faces[i].x + faces[i].width, faces[i].y + faces[i].height);
Point pt2(faces[i].x, faces[i].y);
rectangle(_imgToWorkOn, pt1, pt2, cvScalar(0, 255, 0, 0), 1, 8, 0);
}
_faceImages = _imgToWorkOn;
lockFace.unlock();
}
}
public:
FaceDetector() : newImageAvailable(false) {}
void start() {
quit = false;
thread t1(&FaceDetector::acquireImage,this);
t1.detach();
thread t2(&FaceDetector::processImage,this);
t2.detach();
}
void stop() {
quit = true;
}
Mat getImage() {
lock_guard<mutex> lock(imageLock);
return _img;
}
Mat getProcessedImage() {
lock_guard<mutex> lock(facesLock);
return _faceImages;
}
};
int main()
{
Mat img = Mat::zeros(960,1080, CV_8UC3); //notwendig
Mat imgs = Mat::zeros(960,1080, CV_8UC3); //notwendig
bool quit(false);
FaceDetector faceDet;
faceDet.start();
thread input([](bool &quitFlag) { getchar(); quitFlag = true; },ref(quit)); //stop on user press Enter
input.detach();
while (!quit) {
Mat img = faceDet.getImage();
imshow("links", img);
Mat imgs = faceDet.getProcessedImage();
imshow("gsichter", imgs);
waitKey(1);
this_thread::sleep_for(chrono::milliseconds(33)); //no need to show more than 30 fps...
}
faceDet.stop();
return 0;
}
编辑2:再次编辑代码,以允许深度复制的垫子图像,因为它被建议(facetracker目前不做任何事情和ocl-mat-stuff/facecascade擦除代码的简单性),并得到了代码的工作,但它的行为奇怪。我的摄像头在运行的时候会亮起一个led灯,大约每隔500毫秒它就会亮起来,通过imshow给我显示一张新图像,然后它就会回到待机状态,尽管它应该尽可能快地更新_img。我不知道如何在互斥环境中设置视频捕获,只运行一次来设置帧。宽度和高度,然后作为网络摄像头图像缓冲区自由运行。下面是上述代码:
#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <cmath>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/ocl/ocl.hpp"
#include <functional>
using namespace std;
using namespace cv;
typedef unsigned char uchar;
typedef unsigned int uint;
class FaceDetector
{
mutex imageLock, facesLock;
condition_variable imageAqcuired;
bool newImageAvailable;
Mat _img;
Mat _imgToWorkOn;
Mat _faceImages;
bool quit;
int c;
void acquireImage()
{
while (!quit)
{
unique_lock<mutex> ulock(imageLock);
imageAqcuired.wait(ulock,[&](){return !newImageAvailable;}); //only take new image after current one was consumed
VideoCapture captureDevice(0);
if (c = 1)
{
captureDevice.set(CV_CAP_PROP_FRAME_WIDTH, 620);
captureDevice.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
c = 0;
}
Mat captureFrame;
captureDevice>>captureFrame;
transpose(captureFrame,captureFrame);
flip(captureFrame,captureFrame,1);
_img = captureFrame.clone();
ulock.unlock();
newImageAvailable = true;
imageAqcuired.notify_one(); //notify that a new image is available
}
}
void processImage()
{
while (!quit)
{
unique_lock<mutex> ulock(imageLock);
imageAqcuired.wait(ulock,[&](){return newImageAvailable;}); //wait untill a new image is available
_imgToWorkOn = _img.clone();
ulock.unlock();
newImageAvailable = false;
imageAqcuired.notify_one(); //notify the current image can be replaced by a newer one
unique_lock<mutex> lockFace(facesLock);
//arbeit
lockFace.unlock();
}
}
public:
FaceDetector() : newImageAvailable(false) {}
void start() {
quit = false;
thread t1(&FaceDetector::acquireImage,this);
t1.detach();
thread t2(&FaceDetector::processImage,this);
t2.detach();
}
void stop() {
quit = true;
}
Mat getImage() {
if (quit)
return Mat();
lock_guard<mutex> lock(imageLock);
return _img;
}
Mat getProcessedImage() {
if (quit)
return Mat();
lock_guard<mutex> lock(facesLock);
return _faceImages;
}
};
int main()
{
bool quit(false);
int c = 1;
FaceDetector faceDet;
faceDet.start();
thread input([](bool &quitFlag) { getchar(); quitFlag = true; },ref(quit)); //stop on user press Enter
input.detach();
while (!quit) {
Mat img = faceDet.getImage();
Mat imgc = img.clone();
imshow("links", imgc);
/*
imgs = faceDet.getProcessedImage();
Mat imgsc = imgs.clone();
imshow("gsichter", imgsc);
*/
waitKey(30);
this_thread::sleep_for(chrono::milliseconds(33)); //no need to show more than 30 fps...
}
faceDet.stop();
return 0;
}
我制作了一个示例代码供您根据需要修改。如果有不清楚的地方,欢迎提问。
#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <cmath>
using namespace std;
typedef unsigned char uchar;
typedef unsigned int uint;
class FaceDetector
{
mutex imageLock, facesLock;
condition_variable imageAqcuired;
bool newImageAvailable;
vector<uchar> _img;
vector<uchar> _imgToWorkOn;
vector<uchar> _faceImages;
bool quit;
void acquireImage()
{
while (!quit)
{
unique_lock<mutex> ulock(imageLock);
imageAqcuired.wait(ulock,[&](){return !newImageAvailable;}); //only take new image after current one was consumed
//aqcuire image from camera into _img here
ulock.unlock();
newImageAvailable = true;
imageAqcuired.notify_one(); //notify that a new image is available
}
}
void processImage()
{
while (!quit)
{
unique_lock<mutex> ulock(imageLock);
imageAqcuired.wait(ulock,[&](){return newImageAvailable;}); //wait untill a new image is available
_imgToWorkOn = _img;
ulock.unlock();
newImageAvailable = false;
imageAqcuired.notify_one(); //notify the current image can be replaced by a newer one
unique_lock<mutex> lockFace(facesLock);
//process _imgToWorkOn, face detect...
lockFace.unlock();
}
}
public:
FaceDetector() : _img(100000),_imgToWorkOn(100000), _faceImages(100000), newImageAvailable(false) {}
void start() {
quit = false;
thread t1(&FaceDetector::acquireImage,this);
t1.detach();
thread t2(&FaceDetector::processImage,this);
t2.detach();
}
void stop() {
quit = true;
}
vector<uchar> getImage() {
if (quit)
return vector<uchar>();
lock_guard<mutex> lock(imageLock);
return _img;
}
vector<uchar> getProcessedImage() {
if (quit)
return vector<uchar>();
lock_guard<mutex> lock(facesLock);
return _faceImages;
}
};
int main()
{
bool quit(false);
FaceDetector faceDet;
faceDet.start();
thread input([](bool &quitFlag) { getchar(); quitFlag = true; },ref(quit)); //stop on user press Enter
input.detach();
while (!quit) {
vector<uchar> img = faceDet.getImage();
if (img.size())
{ /*show image*/ }
img = faceDet.getProcessedImage();
if (img.size()) { /*show image*/ }
this_thread::sleep_for(chrono::milliseconds(33)); //no need to show more than 30 fps...
}
faceDet.stop();
return 0;
}
相关文章:
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 使用std::vector的OpenCL矩阵乘法
- 尝试导入pybind-opencv模块时出现libgtk错误
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- OpenCV EqualizeHist()从彩色图像创建黑白图像
- 将OpenCV C++重写为EmguCV C#-如何使用指针
- OpenCV C++.快速计算混淆矩阵
- OPENCV:实际启用了OpenCL
- OpenCV OpenCL Thread Saftey - Deadlock (将 cv::Mat 更改为 UMat)
- 了解OpenCV中OpenCL的用法(材质/单元对象)
- 使用OpenCL支持构建OpenCV
- opencl and opencv 3.0 Beta
- OpenCL以OpenCV为先导
- OpenCV 3 OpenCL UMat绘图功能
- 性能不佳基于OpenCL的OpenCV平方实现
- 在OpenCL-OpenCV-Realtime-Threads中正确使用互斥锁
- 与opencl和opencv的协方差矩阵
- 使用OpenCV和OpenCL的容器类型
- 通过强制转换OpenCV UMat的句柄实例化OpenCL cl_mem