[英]OpenCV VideoCapture says video has 0 frames (C++ and Python)
[英]How to transfer cv::VideoCapture frames through socket in client-server model (OpenCV C++)?
我通过套接字翻译视频,但在另一侧看到视频流,但无法接收视频。 我的视频文件为空。 我认为问题是在接收端转换视频格式可能是错误的。 我应该如何在服务器端对视频进行编码以及应该如何在客户端对视频进行解码?
我使用Linux Ubuntu Mate,OpenCV 2.4.13。
服务器:
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fstream>
#include <cstring>
#include <iostream>
#include "opencv2/opencv.hpp"
#include <opencv/cv.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <string>
#include <iomanip>
#include <pthread.h>
#include <SerialStream.h>
#include <unistd.h>
#include <ctime>
#include <iomanip>
#include "opencv2/opencv.hpp"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/mat.hpp>
#include <opencv2/core/types_c.h>
#include <vector>
#include <arpa/inet.h>
#include <unistd.h>
using namespace std;
using namespace cv;
char answer[] = "Y";
int main()
{
int sock, listener;
struct sockaddr_in addr;
char buf[1024];
int bytes_read;
if( (listener = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket() failed");
exit(1);
}
addr.sin_family = AF_INET;
addr.sin_port = htons(3425);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(listener, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
perror("bind");
exit(2);
}
listen(listener, 1);
ofstream of("readFile.txt");
vector<int> param;
param.push_back(CV_IMWRITE_JPEG_QUALITY);
Mat frame = Mat::zeros(480, 640, CV_8UC3);
Mat receive;
int imgSize = frame.total()*frame.elemSize();
if(! frame.isContinuous() ){
frame = frame.clone();
}
namedWindow("CV Video Client", 1);
uchar *iptr = frame.data;
int key;
uchar sockData[imgSize];
int count_of_receive_frame = 0;
int num_of_recv_bytes;
VideoWriter outputVideo;
Size S = Size((int) 480,(int) 640);
outputVideo.open("receive.avi", CV_FOURCC('X','V','I','D'), 30, S, true);
int i = 0;
char name_of_photo[20];
while(1)
{
sock = accept(listener, NULL, NULL);
if(sock < 0)
{
perror("accept");
exit(3);
}
while(key != 'q'){
if( num_of_recv_bytes = recv(sock, iptr, imgSize, MSG_WAITALL) == -1 ){
cerr << "recv failed, received bytes = " << num_of_recv_bytes << endl;
}
imshow("CV Video Client", frame);
outputVideo.write(frame);
if (key = waitKey(10) >= 0) break;
}
outputVideo.release();
close(sock);
break;
}
return 0;
}
客户:
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fstream>
#include <cstring>
#include <iostream>
#include "opencv2/opencv.hpp"
#include <opencv/cv.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <string>
#include <iomanip>
#include <pthread.h>
#include <unistd.h>
#include <ctime>
#include <iomanip>
#include "opencv2/opencv.hpp"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/mat.hpp>
#include <opencv2/core/types_c.h>
#include <vector>
#include <arpa/inet.h>
#include <unistd.h>
using namespace std;
using namespace cv;
size_t get_file_size( const char * filename );
void file_to_buf( char *buf, size_t _len, std::string filename );
void take_photo(char *name);
char answer[] = "N";
char message[] = "Hello there!\n";
int count_send_img = 0;
int main()
{
string filename = "img.jpg";
int sock;
struct sockaddr_in addr;
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0)
{
perror("socket");
exit(1);
}
addr.sin_family = AF_INET;
addr.sin_port = htons(3425); // или любой другой порт...
addr.sin_addr.s_addr = /*net_addr*/htonl(/*"192.168.1.71"*/INADDR_LOOPBACK);
if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
perror("connect");
exit(2);
}
int bbytee;
cout << "before open the cam" << endl;
VideoCapture cap(0);
if(!cap.isOpened()){
cout<< "Could not open the camera" << endl;
}
cout << "cam opened" << endl;
Mat frame, frameGray;
frame = Mat::zeros(480, 640, CV_8UC3);
if(! frame.isContinuous() ){
frame = frame.clone();
}
int imgSize = frame.total()*frame.elemSize();
while(1){
cap >> frame;
cvtColor(frame, frameGray, CV_BGR2GRAY);
if( (bbytee = send(sock, frameGray.data, imgSize, 0)) < 0 ){
cerr<< "bytes = " << bbytee << endl;
break;
}
}
close(sock);
return 0;
}
环境:OpenCV 3.3,G ++ 5.4,Ubuntu 16.04
如果要保存视频,则应将CV_FOURCE
设置为MJPG
。
VideoWriter outputVideo;
Size S = Size((int) 640,(int) 480);
outputVideo.open("receive.avi", CV_FOURCC('M','J','P','G'), 30, S, true);
这是我的结果:
客户端 (Client.cpp):
//!2017.12.19 19:19:01 CST
//!2017.12.19 22:19:38 CST
//!2017.12.19 22:39:37 CST
// 客户端
// 使用 OpenCV 读取视频(并处理),然后使用 SOCKET 上传到服务器。
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <string>
#include <vector>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
int sock;
struct sockaddr_in addr;
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0){
perror("socket");
exit(1);
}
addr.sin_family = AF_INET;
addr.sin_port = htons(3425);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0){
perror("connect");
exit(2);
}
int bbytee;
cout << "before open the cam" << endl;
VideoCapture cap(0);
if(!cap.isOpened()) {
cout<< "Could not open the camera" << endl;
close(sock);
return -1;
}
Mat frame;
frame = Mat::zeros(480, 640, CV_8UC3);
int imgSize = frame.cols*frame.rows*3;
int cnt=0;
//Mat frame;
while(1) {
cap >> frame;
if(frame.empty()) {
cerr<<"[client] VideoCapture(0) error!"<<endl;
}
cout<< ++cnt << ":"<< frame.isContinuous()<<"," <<frame.size()<<endl;;
if( (bbytee = send(sock, frame.data, imgSize, 0)) < 0 ) {
cerr<< "bytes = " << bbytee << endl;
break;
}
cv::imshow("client", frame);
if(cv::waitKey(100) == 'q') {
break;
}
}
close(sock);
return 0;
}
服务端 (Server.cpp):
//!2017.12.19 19:19:01 CST
//!2017.12.19 22:19:38 CST
//!2017.12.19 22:39:37 CST
// 服务器
// 监听客户端请求,读取视频流(并处理),保存。
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <string>
#include <vector>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
int sock, listener;
struct sockaddr_in addr;
if( (listener = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("[server] socket() failed");
exit(1);
}
addr.sin_family = AF_INET;
addr.sin_port = htons(3425);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(listener, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("[server] binding faild!");
exit(2);
}
listen(listener, 1);
int num_of_recv_bytes;
VideoWriter outputVideo;
Size S = Size((int) 640,(int) 480);
outputVideo.open("receive.avi", CV_FOURCC('M','J','P','G'), 30, S, true);
int imgSize = 480*640*3;
Mat frame = Mat::zeros(480, 640, CV_8UC3);
uchar *iptr = frame.data;
int key;
int cnt=0;
while(1){
cout << ++cnt<<endl;
sock = accept(listener, NULL, NULL);
if(sock < 0){
perror("[server] accept() faild!");
exit(3);
}
while(key != 'q') {
if( num_of_recv_bytes = recv(sock, iptr, imgSize, MSG_WAITALL) == -1 ) {
cerr << "recv failed, received bytes = " << num_of_recv_bytes << endl;
}
outputVideo<< frame;
imshow("server", frame);
if (key = waitKey(100) >= 0) break;
}
outputVideo.release();
close(sock);
break;
}
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.