我正在用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;
}