В моем коде я хочу запускать Videocapture
в отдельном pthread
непрерывно, в то время как основной поток будет действовать как socket server
для связи с любым клиентом (или наоборот).Как запустить OpenCV Videocapture в отдельном потоке posix в C++ для кросс-платформенной?
Когда client
подключается к server
, то server
немедленно отправить последнюю Videocapture
кадр клиенту и закрыть соединение и снова ждать другого соединения.
Я в настоящее время использую OpenCV 2.3.0
в mingw32
условиях.
Посмотрев некоторые возможные решения на StackOverflow
, я пытался следовать им, но, тем не менее, возможно, я помещаю OpenCV variables
либо locally
или globally
или swapping the threads
т.е. сохраняя Videocapture
нить в main thread
или in the 2nd thread
, программа просто висит молча на mutex locked area
из поток VideoCapture
при подключении клиента.
Я полагаю, что это происходит, когда нить server
начинает запирать mutex
после подключения к клиенту.
Любое обоснование или Возможное решение будет высоко оценено. Кроме того, я использую prebuilt OpenCV версии 2.3.0, и мне нужен код для кросс-платформы. В любом случае, если он указывает на ошибку, я, очевидно, могу перейти к другой версии.
Серверный код
mynet.h
#ifndef __MYNET__
#define __MYNET__
#ifdef _WIN32
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501 /* Windows XP. */
#endif
#include <winsock2.h>
#include <Ws2tcpip.h>
#else
/* Assume that any non-Windows platform uses POSIX-style sockets instead. */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h> /* Needed for getaddrinfo() and freeaddrinfo() */
#include <unistd.h> /* Needed for close() */
#endif
int sockInit(void)
{
#ifdef _WIN32
WSADATA wsa_data;
return WSAStartup(MAKEWORD(1,1), &wsa_data);
#else
return 0;
#endif
}
int sockQuit(void)
{
#ifdef _WIN32
return WSACleanup();
#else
return 0;
#endif
}
/* Note: For POSIX, typedef SOCKET as an int. */
#ifndef _WIN32
typedef int SOCKET;
#else
typedef unsigned int SOCKET;
#endif
int sockClose(SOCKET sock)
{
int status = 0;
#ifdef _WIN32
status = shutdown(sock, SD_BOTH);
if (status == 0) { status = closesocket(sock); }
#else
status = shutdown(sock, SHUT_RDWR);
if (status == 0) { status = close(sock); }
#endif
return status;
}
#if(defined(_WIN32) || defined(WIN32))
#include <windows.h>
#define mysleep(x) Sleep((x))
#else
#include <unistd.h>
#define mysleep(x) usleep((x)*1000)
#endif
#endif
netserver.cpp
#define _GLIBCXX_USE_CXX11_ABI 0
#undef _GLIBCXX_DEBUG
#include "../mynet.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <pthread.h>
using namespace cv;
Mat frame(120, 160, CV_8UC3);;
pthread_mutex_t mutex;
pthread_t thread;
void *myfunc(void *threadid)
{
int n;
int listenfd = 0,connfd = 0;
struct sockaddr_in serv_addr;
unsigned char sendBuff[160*120*3];
Mat hereframe;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
printf("socket retrieve success\n");
memset(&serv_addr, '0', sizeof(serv_addr));
memset(sendBuff, '0', sizeof(sendBuff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(5000);
bind(listenfd, (struct sockaddr*)&serv_addr,sizeof(serv_addr));
if(listen(listenfd, 10) == -1)
{
printf("Failed to listen\n");
}
else
{
connfd = accept(listenfd, (struct sockaddr*)NULL,NULL); // accept awaiting request
if(connfd<=0) printf("Something went wrong with write()! %s\n", strerror(errno));
else
{
while(1)
{
printf("Got client...\n");
pthread_mutex_lock (&mutex);
printf("Copying data...\n");
frame.copyTo(hereframe);
pthread_mutex_unlock (&mutex);
printf("Hereframe size: %dX%d\n", hereframe.rows, hereframe.cols);
memcpy(sendBuff, hereframe.data, 120*160*3);
printf("Sending data...\n");
n = send(connfd, (char*)sendBuff, 120*160*3,0);
if(n<0) printf("Something went wrong with write()! %s\n", strerror(errno));
printf("Closing client after writing %d bytes...\n", n);
printf("Closed...\n");
mysleep(40);
printf("Restartng data...\n");
}
sockClose(connfd);
}
}
sockQuit();
pthread_exit(NULL);
}
int main(void)
{
//cvNamedWindow("Sisplay", CV_WINDOW_AUTOSIZE);
sockInit();
pthread_mutex_init(&mutex,NULL);
VideoCapture cap;
Mat hereframe1;
cap.open(0);
cap.set(CV_CAP_PROP_FRAME_WIDTH, 160);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 120);
if(!cap.isOpened()) printf("Fukced up\n");
int rc;
long t;
rc = pthread_create(&thread, NULL, myfunc, (void *)t);
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
for(;;)
{
cap >> hereframe1;
// printf("Video size: %dX%d\n", hereframe1.rows, hereframe1.cols);
pthread_mutex_lock(&mutex);
hereframe1.copyTo(frame); /* hangs here*/
pthread_mutex_unlock(&mutex);
// cvtColor(frame, gray, CV_BGR2GRAY);
Scalar tempVal = mean(hereframe1);
// printf("Mean = %f\n", tempVal.val[0]);
mysleep(30);
//if(waitKey(30)=='q') break;
// std::swap(prevgray, gray);
}
char *b;
pthread_join(thread,(void**)&b);
return 0;
}
Клиентский код
receiver.cpp
#define _GLIBCXX_USE_CXX11_ABI 0
#include "../mynet.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
using namespace cv;
int main(int argc, char *argv[])
{
int sockfd = 0,n = 0;
unsigned char recvBuff[120*160*3];
struct sockaddr_in serv_addr;
sockInit();
memset(recvBuff, '0',sizeof(recvBuff));
if((sockfd = socket(AF_INET, SOCK_STREAM, 0))< 0)
{
printf("\n Error : Could not create socket \n");
return 1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(5000);
serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))<0)
{
printf("\n Error : Connect Failed \n");
return 1;
}
printf("Connected to server...\n");
Mat frame(120, 160, CV_8UC3);
int csz = 0;
cvNamedWindow("Display", CV_WINDOW_AUTOSIZE);
printf("OK here 0\n");
for(;;)
{
csz = 0;
while((n = recv(sockfd, (char*)recvBuff, sizeof(recvBuff), 0)) > 0)
{
printf("OK here 2\n");
printf("Read %d bytes...\n", n);
csz += n;
if(csz<=120*160*3)
{
memcpy(frame.data+(csz-n), recvBuff, n);
}
if(csz>= 120*160*3) break;
}
printf("OK here 3\n");
printf("Got data of size %d bytes...\n", csz);
imshow("Display", frame);
if(csz < 120*160*3)
{
printf("\n Read Error \n");
}
if(waitKey(30)=='q') break;
// std::swap(prevgray, gray);
}
sockClose(sockfd);
sockQuit();
return 0;
}
Что такое VideoCapture 'cap.open (-1);' Я тоже изучаю OpenCV, но вещь '-1' меня озадачивает. Я знаю, что такое« 0, 1, 2 ... », но что означает '-1'? Кроме того, почему кадр установлен в «Матовый кадр (120, 160, CV_8UC3);»? Почему бы не просто «Матовый кадр»? – zipzit
@zipzit: Nevermind, это должно быть 0. Я исправил. Я установил размер 'frame' раньше, потому что после многообмена и изменения переменных во время моей отладки, когда-то это происходило до того, как перед запуском Videocapture клиент подключился. В этом случае серверный поток не может копировать необработанные данные 'frame' с размером' 120x160x3' байт в области блокировки мьютекса без предварительного определения размера. –
Мне интересно, что такое глобальная переменная 'frame' ... Я думал, что вы назвали ее полезной для перечислений и констант .. но не столько для активной переменной. Для этого нужен глобальный оператор области ((:) :)? – zipzit