多线程读取数据

时间:2018-06-04 12:49:54

标签: c++ multithreading opencv mutex

我正在用C ++编写SFML和OpenCV中的行检测接口;我有2个类:Interface和ImageProccessing。我需要2个while循环(一个用于在屏幕上绘制整个界面,另一个用于线检测)所以我决定使用线程。我使用:

在Interface构造函数中创建了一个新线程
ImageProccessingThread = new std::thread(&ImageProccessing::start, context.imageproc, toString(getContext().connection->getIP()), getContext().connection->getPort());

它需要2个参数(IP和网络摄像头端口)。线程正常工作,因为当我从它显示窗口时,一切都很好。问题出在主线程中。我想从ImageProccessing类复制cv :: Mat,将其转换为SFML图像并显示。我处理转换和显示(在主线程中捕获的另一个网络摄像头图像上测试)。但我不能从ImageProccessingThread复制Mat并在主线程中使用它。使用:

getContext().imageproc->getOriginal().copyTo(frameRGB);

if (frameRGB.empty())

说没有图像 - 它是空的。就像线程处理单独的数据一样。我当时认为这是同步问题,所以我尝试使用互斥锁。在ImageProccessing类中,我添加了:

mtx.lock();
result.copyTo(imgResult);
imgThresholded.copyTo(imgThresh);
mtx.unlock();

但它什么都没有。我做错了什么?

编辑:

有关复制的更多说明

副本参与Interface类。

接口:

cv::Mat frameRGB, frameRGBA;

getContext().imageproc->getOriginal().copyTo(frameRGB);

if (frameRGB.empty())
{
    std::cout << "Can't copy" << std::endl;
    system("PAUSE");
    return;
}

cv::cvtColor(frameRGB, frameRGBA, cv::COLOR_BGR2RGBA);

camImage.create(frameRGBA.cols, frameRGBA.rows, frameRGBA.ptr());

if (!camTexture.loadFromImage(camImage))
{
    std::cout << "No image" << std::endl;
    system("PAUSE");
    return;
}

camSprite.setTexture(camTexture);
camSprite.setPosition(1214.f, 30.f);

我从ImageProccessing getter获得cv :: Mat

ImageProccessing:

ImageProccessing.hpp:

#pragma once
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <math.h>
#include <SFML/Network.hpp>
#include <fstream>

class ImageProccessing
{
public:
    ImageProccessing();
    ~ImageProccessing();
    sf::Int16 doProccessing();
    void setup();
    void number_of_lines(int*, cv::Mat*, int, int, bool);
    bool zeros(float min);
    void tresh();
    void update(cv::Mat imgOriginal);
    int start(std::string, unsigned short);
    void Parameters_load(struct Config);
    struct Config Parameters_check();
    void show(bool);
    cv::Mat getOriginal();
    cv::Mat getThreshholded();
    bool getStarted();
    void changeTest(bool change);
    bool getTest();
private:
    bool Test;
    bool isStarted;
    cv::VideoCapture cap;
    cv::Mat imgOriginal;
    cv::Mat roi_left;
    cv::Mat roi_right;
    cv::Mat contours1;
    cv::Mat imgThresholded;
    cv::Mat result;
    cv::Mat imgResult;
    cv::Mat imgThresh;
    int iLowH;
    int iHighH;
    int iLowS;
    int iHighS;
    int iLowV;
    int iHighV;
    int max_angle;
    int min_angle;
    int mid_angle_left;
    int mid_angle_right;
    int point_height;
    float cut_off;
    int houghVote_left;
    int houghVote_right;
    int size_destruct;
    int size_fill;
    void average(float, float);
    FILE* files;
    std::vector<cv::Vec2f> lines;
};

ImageProccessing.cpp的部分内容:

cv::Mat ImageProccessing::getOriginal()
{
    return imgResult;
}

sf::Int16 ImageProccessing::doProccessing()
{
    sf::Int16 value = 0;
    std::vector<Vec2f> lines_left;
    std::vector<Vec2f> lines_right;
    roi_left = contours1(Rect(0, 0, int(float(contours1.cols) *cut_off), imgOriginal.rows));
    roi_right = contours1(Rect(int(float(contours1.cols) *(1 - cut_off)), 0, int(float(contours1.cols)*cut_off), imgOriginal.rows));
    lines = lines_left;
    this->number_of_lines(&houghVote_left, &roi_left, min_angle, mid_angle_left, true);
    lines_left = lines;
    lines = lines_right;
    this->number_of_lines(&houghVote_right, &roi_right, mid_angle_right, max_angle, false);
    lines_right = lines;
    std::cout << "houghVote" << houghVote_left << " " << houghVote_right << "\n";
    std::cout << "lines" << lines_left.size() << "lines1" << lines_right.size() << "\n";
    std::cout << "min " << min_angle * PI / 180 << ", max" << max_angle * PI / 180 << "\n";
    //fprintf(files, "houghVote %d %d lines %d lines1 %d min %f max %f", houghVote_left, houghVote_right, lines_left.size(), lines_right.size(), min_angle * PI / 180, max_angle * PI / 180);
    imgOriginal.copyTo(result);

    if (lines_left.size() < 30) {
        lines = lines_left;
        average(10, 1.5);
        lines_left = lines;
    }
    if (lines_right.size() < 30) {
        lines = lines_right;
        average(10, 1.5);
        lines_right = lines;
    }

    unsigned __int64 begin = 0;
    Mat hough(imgOriginal.size(), CV_8U, Scalar(0));
    Vec2f closest;
    float min_distance_left = float(result.cols) / 2;
    while (begin < lines_left.size()) {

        float rho = lines_left[begin][0];   // first element is distance rho
        float theta = lines_left[begin][1]; // second element is angle theta
        float a = -(cos(theta) / sin(theta));
        float b = rho / sin(theta);
        float dist = (result.cols / 2) - ((result.rows / point_height) - b) / a;
        //cout << dist << endl;
        if (min_distance_left > dist && dist > 0) {
            min_distance_left = dist;
        }
        //cout << min_distance_left << endl;
        fprintf(files, "line: (%f,%f) \n", dist, min_distance_left);
        // point of intersection of the line with first row 
        Point pt1(int(rho / cos(theta)), 0);
        // point of intersection of the line with last row
        Point pt2(int((rho - result.rows*sin(theta)) / cos(theta)), result.rows);
        // draw a white line

        line(result, pt1, pt2, Scalar(255), 8);
        line(hough, pt1, pt2, Scalar(255), 8);
        //}
        //std::cout << "line: (" << rho << "," << theta << ")\n";
        fprintf(files, "line: (%f,%f) \n", rho, theta);

        ++begin;
    }
    begin = 0;
    float min_distance_right = float(result.cols) / 2;
    while (begin < lines_right.size()) {

        float rho = lines_right[begin][0];   // first element is distance rho
        float theta = lines_right[begin][1]; // second element is angle theta
        float a = -(cos(theta) / sin(theta));
        float b = rho / sin(theta);
        float dist = (0.5f - cut_off)*contours1.cols + ((result.rows / point_height) - b) / a;
        //cout << dist << endl;
        if (min_distance_right > dist && dist > 0) {
            min_distance_right = dist;
        }
        //cout << min_distance_right << endl;
        fprintf(files, "line: (%f,%f) \n", dist, min_distance_right);

        //if (theta < 30.*PI / 180. || theta > 150.*PI / 180.) { //     filter theta angle to find lines with theta between 30 and 150 degrees (mostly vertical)

        // point of intersection of the line with first row
        Point pt1(int(rho / cos(theta) + contours1.cols*(1 - cut_off)), 0);
        // point of intersection of the line with last row
        Point pt2(int((rho - result.rows*sin(theta)) / cos(theta) + contours1.cols*(1 - cut_off)), result.rows);
        // draw a white line
        line(result, pt1, pt2, Scalar(255), 8);
        line(hough, pt1, pt2, Scalar(255), 8);
        //}
        //std::cout << "line: (" << rho << "," << theta << ")\n";
        fprintf(files, "line: (%f,%f) \n", rho, theta);
        ++begin;
    }

    Point x1(result.cols / 2, 0);
    Point x2(result.cols / 2, result.rows);
    Point midle;
    line(result, x1, x2, Scalar(255), 8);
    x1 = { int((result.cols / 2) - min_distance_left),result.rows / point_height };
    x2 = { int((result.cols / 2) + min_distance_right),result.rows / point_height };
    midle = (x1 + x2) / 2;
    circle(result, midle, 10, Scalar(0, 0, 255), -1);
    line(result, x1, x2, Scalar(255), 8);
    value = midle.x - (result.cols / 2);

    mtx.lock();
    result.copyTo(imgResult);
    imgThresholded.copyTo(imgThresh);
    mtx.unlock();
    //this->show(1);
    return value;
}

int ImageProccessing::start(string ip, unsigned short port)
{

    //test
    sf::UdpSocket socket;
    socket.setBlocking(false);
    sf::Packet packet;
    sf::Int16 value = 0;
    packet << value;
    sf::IpAddress recipient = ip;

    VideoCapture cap(0);
    //VideoCapture cap("http://"+ip+":8080/stream/video.mjpeg"); //capture the video from web cam


    if (!cap.isOpened())  // if not success, exit program
    {
        cout << "Cannot open the web cam" << endl;
        system("pause");
        return -1;
    }
    //this->setup();
    Mat imgOriginal;
    while (true) {
        bool bSuccess = cap.read(imgOriginal); // read a new frame from video
        if (!bSuccess) //if not success, break loop
        {
            cout << "Cannot read a frame from video stream" << endl;
            break;
        }
        //wysylanie
        this->update(imgOriginal);
        this->tresh();
        if (this->zeros(0.001f)) {
            value = 1000;
            //this->show(0);
        }
        else {
            value = this->doProccessing();
        }
        packet.clear();
        packet << value;
        if (socket.send(packet, recipient, port) != sf::Socket::Done)
        {
            std::cout << "Some error" << std::endl;
            return 12;
        }
        //koniec wysylania

        //waitKey(0);
        if (waitKey(10) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
        {
            value = 1000;
            packet.clear();
            packet << value;
            if (socket.send(packet, recipient, port) != sf::Socket::Done)
            {
                std::cout << "Some error" << std::endl;
                return 12;
            }
            cout << "esc key is pressed by user" << endl;
            break;
            return 1;
        }
    }

    isStarted = true;
}

0 个答案:

没有答案