互斥锁实现可以计数的信号量

#include <iostream>  
#include <opencv2/opencv.hpp>  
#include <thread>  
#include <conio.h>  
#include <windows.h>  
#include <time.h>  
#include <condition_variable>
#include <semaphore>
using namespace std;
//使用锁来实现一个信号量类
class MySemaphore {
public:
    MySemaphore(int initialValue) : count(initialValue), x(-1) {}

    int acquire() {
        std::unique_lock<std::mutex> lock(mutex);//锁保护{}
        condition.wait(lock, [this]() { return count > 0; });
        count--;
        x++;//帧个数+1
        std::cout << "acquire目前还有" << count << "个信号量" << std::endl;
        return x;
    }

    void release() {
        cout << "释放一个信号量!!" << endl;
        std::unique_lock<std::mutex> lock(mutex);//锁保护{}
        count++;//信号量个数+1

        condition.notify_one();
        std::cout << "目前还有" << count << "个信号量" << std::endl;
    }

    int getX() {
        std::unique_lock<std::mutex> lock(mutex);//锁保护{}
        return x;
    }

private:
    int count;
    int x;
    std::mutex mutex;
    std::condition_variable condition;
};

counting_semaphore sem(0);//现实信号量

int width = 640;  // 设置视频帧宽度
int heigth = 480;  // 设置视频帧高度
int FPS_SET = 30;  // 设置帧率
int key = 0;  // 进程控制标志
std::mutex g_mutex1;  // 创建互斥锁,用于保护共享资源
std::mutex g_mutex2;  // 创建互斥锁,用于保护共享资源
std::map<int64_t, cv::Mat> frames; //创建map,用于存储转换后的帧  // 创建队列,用于存储图像帧
std::map<int64_t, cv::Mat> frames_re; //创建map,用于存储转换后的帧

void reverseFrame(const cv::Mat& inputFrame, cv::Mat& outputFrame) {
    cv::cvtColor(inputFrame, outputFrame, cv::COLOR_BGR2RGB);  // 图像反转函数
}

void getframe(MySemaphore& sem) {
    cout << "正在打开摄像头" << endl;

    cv::VideoCapture cap;
    /* cap.open(1);*/
    cap.open("H:\\WeChatfile\\WeChat Files\\wxid_4h6srkxhh8z022\\FileStorage\\Video\\2023-10\\df8caca82576ca92c088b26ab901b241.mp4");
    cap.set(cv::CAP_PROP_FRAME_WIDTH, width);  // 设置视频帧宽度
    cap.set(cv::CAP_PROP_FRAME_HEIGHT, heigth);  // 设置视频帧高度
    cap.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'));  // 设置视频流格式
    cap.set(cv::CAP_PROP_FPS, FPS_SET);  // 设置帧率

    if (!cap.isOpened()) {
        cout << "打开失败" << endl;
        return;
    }
    cout << "打开成功" << endl;
    int i = 0;
    int delay = 1000 / FPS_SET;
    cv::Mat frame2;
    while (key != 27) {
        //while (frames.size() > 10)//定义缓冲区大小
        //    Sleep(delay);

        Sleep(delay);
        cap >> frame2;
        std::unique_lock<std::mutex> lock1(g_mutex1);
        frames[i] = frame2;
        lock1.unlock();
        //释放一个帧信号量
        sem.release();
        i++;

    }
    cout << "正在解除摄像头占用" << endl;
    cap.release();
    cout << "成功解除摄像头占用" << endl;
}



void changeframe(MySemaphore& sem) {

    cv::Mat frame1;
    cv::Mat reversedframe;
    int index;
    do {

        index = sem.acquire();//获取帧信号量

        std::unique_lock<std::mutex> lock1(g_mutex1);//上锁
        frame1 = frames[index];//获取当前处理的是第几帧
        lock1.unlock();


        reverseFrame(frame1, reversedframe);  // 反转图像帧


        std::unique_lock<std::mutex> lock2(g_mutex2);//上锁
        frames_re[index] = reversedframe;
        lock2.unlock();
    } while (key != 27);

}
void showframe() {
    int font_face = cv::FONT_HERSHEY_COMPLEX;
    double font_scale = 1;
    int thickness = 2;
    int baseline;
    cv::Point origin;
    origin.x = 10;
    origin.y = 30;

    int FPS = 0;
    double time = 0;
    LARGE_INTEGER nFreq;
    LARGE_INTEGER nBeginTime;
    LARGE_INTEGER nEndTime;
    QueryPerformanceFrequency(&nFreq);//查询性能计数器的频率

    cv::Mat frame;
    cv::namedWindow("frame");
    int i = 0;//全局变量判断当前应该是第几帧哦
    do {

        cout << "显示while开始运行" << endl;
        QueryPerformanceCounter(&nBeginTime);
        std::unique_lock<std::mutex> lock2(g_mutex2);
        auto it = frames_re.find(i); // 查找键为5的元素查找第i帧是否含有

        if (it != frames_re.end()) {
            cout << "显示成功" << endl;


            frame = frames_re[i];
            lock2.unlock();
            i++;
            string s = "FPS:" + to_string(FPS);
            cv::putText(frame, s.c_str(), origin, font_face, font_scale, cv::Scalar(0, 255, 255), thickness, 8, 0);
            if (!frame.empty())
                cv::imshow("frame", frame);

            cv::waitKey(1000 / FPS_SET);
            QueryPerformanceCounter(&nEndTime);
            time = (double)(nEndTime.QuadPart - nBeginTime.QuadPart) / (double)nFreq.QuadPart;
            FPS = 1 / time;
        }
        else
        {
            cout << "显示失败" << endl;
            lock2.unlock();

        }
    } while (key != 27);

    cv::destroyWindow("frame");
}

int main() {
    MySemaphore sem(0); // 初始信号量为0
    thread t1(getframe, std::ref(sem));  // 启动获取帧的线程
    t1.detach();
    thread t2(showframe);  // 启动显示帧的线程
    t2.detach();
    thread t3(changeframe, std::ref(sem));  // 启动转换帧的线程
    t3.detach();
    thread t4(changeframe, std::ref(sem));  // 启动转换帧的线程
    t4.detach();
    thread t5(changeframe, std::ref(sem));  // 启动转换帧的线程
    t5.detach();


    //不让主线程结束
    while (1) {
        Sleep(500);
        if (_kbhit())
            break;
    }

    key = 27;  // 通知其他线程结束
    Sleep(1000);  // 等待线程结束
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值