opencv和opencvsharp關鍵代碼

opencv和opencvsharp關鍵代碼

讀取攝像頭,寫入視頻

#include <opencv2/opencv.hpp>
#include <thread>
using namespace std;
using namespace cv;
/*int main() {
	VideoCapture cap(0);
	Mat pic;
	int i = 1;
	char k;
	string a, b;
	while (1) {
		//a = format("window%d", i);
		b = format("D:\\Tu%d.png", i);
		k = waitKey(30);
		cap >> pic;
		namedWindow(a, 1);
		//imshow(a, pic);


		if (k == 's') {
			i++;
			imwrite(b, pic);
			pic.release();
		}
		if (k == 'k') {
			break;
		}
	}
	return 0;
}*/
/*int main() {
	VideoCapture cap(0);
	Mat pic;

	this_thread::sleep_for(chrono::milliseconds(500));
	string a, b;

		b = format("D:\\Tu.png");

		cap >> pic;


			imwrite(b, pic);
			pic.release();
			cap.release();
	return 0;
}*/
/*int main() {
	cv::VideoWriter videoWriter;
	VideoCapture cap(0);
	int w = 640;
	int h = 480;
	cv::Size videoSize(w, h);
	double dfs = cap.get(CAP_PROP_FPS);//獲得幀率 
	videoWriter = cv::VideoWriter("D://out.avi", VideoWriter::fourcc('D', 'I', 'V', 'X'), 20.0, videoSize);
	//videoWriter.open("D://out.avi", VideoWriter::fourcc('D', 'I', 'V', 'X'), dfs, videoSize);
	this_thread::sleep_for(chrono::milliseconds(1500));
	//int i = 0;
	while (cap.isOpened())
	{
		//i++;
		Mat pic;
		cap.read(pic);
		if (pic.empty()) {
			break;
		}
		videoWriter.write(pic);
		//imshow("frame", pic);
		//waitKey(20);
	}
	cap.release();  
	videoWriter.release();
	destroyAllWindows();
}
*/

遠程發送視頻流

#include<opencv2\opencv.hpp>
#include <math.h>
#include <process.h>
#include "winsock.h"
//socket庫的lib
#pragma comment(lib,"ws2_32.lib")

#define PORT 8080

using namespace cv;
using namespace std;

SOCKET socksvr, tcpsvr, tcpsockclient;
CHAR szRecv[1472] = { 0 };
CHAR szSend[1472] = { 0 };
struct sockaddr_in clientaddr = { 0 };
struct sockaddr_in tcpclientaddr = { 0 };
int nLen = sizeof(clientaddr);
int tcpnLen = sizeof(tcpclientaddr);
volatile HANDLE udpreceive, tcpreceive;
UINT threadid, tcpthreadid;
int start = 0;


void delay(int s)
{
	while (s > 0)s--;
}
void TCPServerInit()
{
	tcpsvr = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (INVALID_SOCKET == tcpsvr)
	{
		return;
	}
	/*************建立服務器端套接字地址***********************/
	/********************綁定IP和端口號******************/
	struct sockaddr_in svraddr = { 0 };
	svraddr.sin_family = AF_INET;//代表internet協議族
	svraddr.sin_port = htons(PORT);
	//htonl()函數是將u_long型變量從主機字節順序變爲TCP/IP網絡字節順序。
	svraddr.sin_addr.S_un.S_addr = inet_addr("192.168.1.25");//inet_addr("127.0.0.1");//htonl(INADDR_ANY);//此宏爲0,當前機器上任意IP地址,也可以指定當前機的ip和端口。//127.0
														  //綁定,將服務器端套接字與服務器端套接字地址綁定
	bind(tcpsvr, (struct sockaddr *)&svraddr, sizeof(svraddr));//指定名字,類型,長度。綁定套接字。
																//偵聽
	listen(tcpsvr, SOMAXCONN);//第一個參數是套接字,第二個參數是等待連接隊列的最大長度。
}
void UDPServerInit()
{
	//創建socket
	socksvr = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (INVALID_SOCKET == socksvr)
	{
		return;
	}
	//服務器套接字地址
	//綁定ip與端口,先定義端口等一些信息。
	struct sockaddr_in svraddr = { 0 };
	svraddr.sin_family = AF_INET;
	svraddr.sin_port = htons(PORT);
	svraddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	bind(socksvr, (struct sockaddr*)&svraddr, sizeof(svraddr));

}



void TCPSendImage(Mat image)
{
	//int i;
	//int datanum;
	//send(tcpsockclient, "ss", 2, 0);//發送函數。
	//sendto(socksvr, "ss", 2, 0, (struct sockaddr*)&clientaddr, nLen);
	if (start == 0)closesocket(tcpsockclient);
	else send(tcpsockclient, (const char*)image.data, image.cols*image.rows, 0);
	//for (i = 0; i < image.rows; i += 2)
	//{
	//	send(tcpsockclient, (const char*)image.ptr<uchar>(i), image.cols * 2, 0);//發送函數。
	//	//sendto(socksvr, (const char*)image.ptr<uchar>(i), image.cols * 2, 0, (struct sockaddr*)&clientaddr, nLen);
	//	//datanum=recvfrom(socksvr, szRecv, sizeof(szRecv), 0, (struct sockaddr*)&clientaddr, &nLen);

	//	//delay(100000);
	//}
	//send(tcpsockclient, "ee", 2, 0);//發送函數。
	//sendto(socksvr, "ee", 2, 0, (struct sockaddr*)&clientaddr, nLen);
	//datanum = recvfrom(socksvr, szRecv, sizeof(szRecv), 0, (struct sockaddr*)&clientaddr, &nLen);
}


void SendImage(Mat image)
{
	int i;
	int datanum;
	sendto(socksvr, "ss", 2, 0, (struct sockaddr*)&clientaddr, nLen);
	for (i = 0; i < image.rows; i += 2)
	{
		sendto(socksvr, (const char*)image.ptr<uchar>(i), image.cols * 2, 0, (struct sockaddr*)&clientaddr, nLen);
		//datanum=recvfrom(socksvr, szRecv, sizeof(szRecv), 0, (struct sockaddr*)&clientaddr, &nLen);

		delay(200000);
	}
	sendto(socksvr, "ee", 2, 0, (struct sockaddr*)&clientaddr, nLen);
	//datanum = recvfrom(socksvr, szRecv, sizeof(szRecv), 0, (struct sockaddr*)&clientaddr, &nLen);
}

UINT WINAPI TCPListenThread(void* pParam)
{
	int datanum;
	printf("TCP listening!\n");
	while (1)
	{
		//以下是建立客戶端套接字並建立連接函數。有一個確認的過程。
		//注:後面填的是客戶端地址長度的地址。
		tcpsockclient = accept(tcpsvr, (struct sockaddr*)&tcpclientaddr, &tcpnLen);//建立連接函數
		printf("TCP客戶端已連接\n");
		while (1) {
			if (start == 0) {
				datanum = recv(tcpsockclient, szRecv, sizeof(szRecv), 0); //接收函數,一直處於偵聽模式,等待服務器端發送數據的到來。//構造ip地址
				printf("Recieve:%s From:%s:%d\n", szRecv, inet_ntoa(tcpclientaddr.sin_addr), ntohs(tcpclientaddr.sin_port));
				if (datanum == 2 && szRecv[0] == 's'&&szRecv[1] == 's')
				{
					start = 2;
					printf("Start!\n");
				}
			}
			else if (start == 2) {
				datanum = recv(tcpsockclient, szRecv, sizeof(szRecv), 0); //接收函數,一直處於偵聽模式,等待服務器端發送數據的到來。//構造ip地址
				if (datanum == 2 && szRecv[0] == 'e'&&szRecv[1] == 'e')
				{
					start = 0;
					printf("End!\n");
					break;
				}
			}
		}


	}
	CloseHandle(tcpreceive);
	return 0;
}
UINT WINAPI UDPListenThread(void* pParam)
{

	int datanum;
	printf("UDP listening!\n");
	while (1)
	{

		if (start == 0) {
			datanum = recvfrom(socksvr, szRecv, sizeof(szRecv), 0, (struct sockaddr*)&clientaddr, &nLen);//構造ip地址
			printf("Recieve:%s From:%s:%d\n", szRecv, inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
			if (datanum == 2 && szRecv[0] == 's'&&szRecv[1] == 's')
			{
				start = 1;
				printf("Start!\n");
			}
		}
		else if (start == 1) {
			datanum = recvfrom(socksvr, szRecv, sizeof(szRecv), 0, (struct sockaddr*)&clientaddr, &nLen);//構造ip地址
			if (datanum == 2 && szRecv[0] == 'e'&&szRecv[1] == 'e')
			{

				start = 0;
				printf("End!\n");
			}
		}
		//if(!(szRecv[0] == 's'&&szRecv[1] == 's')&&!(szRecv[0] == 'e'&&szRecv[1] == 'e'))
		//{
		//	sprintf(szSend, "Received %d bytes data!\n", datanum);
		//	sendto(socksvr, szSend, sizeof(szSend), 0, (struct sockaddr*)&clientaddr, nLen);//發送時構造ip地址和端口。
		//}

	}
	CloseHandle(udpreceive);
	return 0;
}

/*
int main(int argc, char** argv) {
	WSADATA wsa = { 0 }; //WinSockApi 取WSA+DATA組成套接字結構體
	WSAStartup(MAKEWORD(2, 2), &wsa);
	//UDPServerInit();
	TCPServerInit();
	udpreceive = (HANDLE)_beginthreadex(NULL, 0, UDPListenThread, 0, 0, &threadid);
	tcpreceive = (HANDLE)_beginthreadex(NULL, 0, TCPListenThread, 0, 0, &tcpthreadid);
	//DrawCir();
	Mat img;
	VideoCapture cap(0);
	if (!cap.isOpened()) return -1;
	VideoWriter me("dir.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'), 20, { 640, 480 });
	int startre = 0;
	while (1)
	{
		cap >> img;
		namedWindow("circles", 1);
		//cvtColor(img, gray, CV_BGR2GRAY);
		imshow("circles", img);
		if (startre)me << img;
		if (start == 1) {
			SendImage(~img);
		}
		else if (start == 2) {
			TCPSendImage(~img);
		}
		waitKey(1);
	}
	//
	//清理套接字資源
	closesocket(tcpsvr);
	closesocket(socksvr);
	WSACleanup();
	return 0;
}
*/

socket server:

// Server.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
//

#include "pch.h"
#include <iostream>
#include "winsock2.h"
#include <opencv2\opencv.hpp>

#pragma comment(lib, "ws2_32.lib")
#include <process.h>
#include <vector>
#include "opencv2/imgcodecs/legacy/constants_c.h"

//using namespace std;

volatile HANDLE tcpreceive;
UINT tcpthreadid;

const int BUF_SIZE = 64;
WSADATA         wsd;            //WSADATA變量
SOCKET          sServer;        //服務器套接字
SOCKET          sClient;        //客戶端套接字
SOCKADDR_IN     addrServ;;      //服務器地址
char            buf[BUF_SIZE];  //接收數據緩衝區
char            sendBuf[BUF_SIZE];//返回給客戶端得數據
int             retVal;         //返回值
int				start = 0;

UINT WINAPI TCPListenThread(void* pParam)
{
	int datanum;
	printf("TCP listening!\n");
	while (1)
	{
		//接受客戶端請求
		sockaddr_in addrClient;
		int addrClientlen = sizeof(addrClient);
		sClient = accept(sServer, (sockaddr FAR*)&addrClient, &addrClientlen);
		if (INVALID_SOCKET == sClient)
		{
			//cout << "accept failed!" << endl;
			closesocket(sServer);   //關閉套接字
			WSACleanup();           //釋放套接字資源;
			return -1;
		}

		while (true)
		{
			retVal = recv(sClient, buf, BUF_SIZE, 0);
			if (SOCKET_ERROR == retVal)
			{
				//cout << "recv failed!" << endl;
				closesocket(sServer);   //關閉套接字
				closesocket(sClient);   //關閉套接字     
				WSACleanup();           //釋放套接字資源;
				return -1;
			}
			if (buf[0] == '0')
				break;
			//cout << "客戶端發送的數據: " << buf << endl;

			//cout << "向客戶端發送數據: ";
			//cin >> sendBuf;
			start = 1;
			
		}
	}
	return 0;
}

int main(int argc, char* argv[])
{
	//初始化套結字動態庫
	if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
	{
		//cout << "WSAStartup failed!" << endl;
		return 1;
	}

	//創建套接字
	sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (INVALID_SOCKET == sServer)
	{
		//cout << "socket failed!" << endl;
		WSACleanup();//釋放套接字資源;
		return  -1;
	}

	//服務器套接字地址 
	addrServ.sin_family = AF_INET;
	addrServ.sin_port = htons(4999);
	addrServ.sin_addr.s_addr = INADDR_ANY;
	//綁定套接字
	bind(sServer, (LPSOCKADDR)&addrServ, sizeof(SOCKADDR_IN));
	if (SOCKET_ERROR == retVal)
	{
		//cout << "bind failed!" << endl;
		closesocket(sServer);   //關閉套接字
		WSACleanup();           //釋放套接字資源;
		return -1;
	}

	//開始監聽 
	retVal = listen(sServer, 1);
	if (SOCKET_ERROR == retVal)
	{
		//cout << "listen failed!" << endl;
		closesocket(sServer);   //關閉套接字
		WSACleanup();           //釋放套接字資源;
		return -1;
	}
	tcpreceive = (HANDLE)_beginthreadex(NULL, 0, TCPListenThread, 0, 0, &tcpthreadid);
	cv::Mat img;
	cv::VideoCapture cap(0);

	if (!cap.isOpened()) return -1;
	//while (cap.isOpened())
	//{
	
	//cvtColor(img, gray, CV_BGR2GRAY);
	//cv::VideoWriter videoWriter;
	//int w = 640;
	//int h = 480;
	//cv::Size videoSize(w, h);
	//videoWriter = cv::VideoWriter("D://out.avi", cv::VideoWriter::fourcc('D', 'I', 'V', 'X'), 20.0, videoSize);
	while (1)
	{
		cap >> img;
		cv::namedWindow("circles", 1);
		//cvtColor(img, gray, CV_BGR2GRAY);
		std::vector<unsigned char> inImage;
		cv::imencode(".jpg", img, inImage);

		//unsigned char * p = &inImage.at(0);

		//std::vector<unsigned char> inImage2;
		//inImage2.insert(inImage2.end(), p,p + strlen((char*)p));
		//cv::Mat show = cv::imdecode(inImage2, CV_LOAD_IMAGE_COLOR);
		//imshow("circles11", show);
		std::string str_encode(inImage.begin(), inImage.end());
		const char * sss = str_encode.c_str();

		std::vector<char> inImage2;
		int size = str_encode.size();
		for (int i = 0; i < size; i++) {
			inImage2.push_back(sss[i]);
		}

		cv::Mat show = cv::imdecode(inImage2, CV_LOAD_IMAGE_COLOR);
		imshow("circles11", show);
		if (start == 1) {
			
			//cv::Mat img2(h, w, CV_8UC1, img.data);
			//videoWriter.write(img);
			//videoWriter.release();
			std::string str_encode(inImage.begin(), inImage.end());
			send(sClient, sss, str_encode.size(), 0);
			//char * chars = (char *)img.data;
			//int w = 640;
			//int h = 480;
			//cv::Mat img2(w, h, CV_8UC1, chars);
			//imshow("circles", img2);
			
			//start = 0;
		}
		cv::waitKey(20);
	}

	
	//退出
	closesocket(sServer);   //關閉套接字
	closesocket(sClient);   //關閉套接字
	WSACleanup();           //釋放套接字資源;
	return 0;
}

// 運行程序: Ctrl + F5 或調試 >“開始執行(不調試)”菜單
// 調試程序: F5 或調試 >“開始調試”菜單

// 入門提示: 
//   1. 使用解決方案資源管理器窗口添加/管理文件
//   2. 使用團隊資源管理器窗口連接到源代碼管理
//   3. 使用輸出窗口查看生成輸出和其他消息
//   4. 使用錯誤列表窗口查看錯誤
//   5. 轉到“項目”>“添加新項”以創建新的代碼文件,或轉到“項目”>“添加現有項”以將現有代碼文件添加到項目
//   6. 將來,若要再次打開此項目,請轉到“文件”>“打開”>“項目”並選擇 .sln 文件

socket client:

// VideoClient.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。
//

#include "pch.h"
#include <iostream>
#include "winsock2.h"

#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable:4996) //必須加上
#include <opencv2\opencv.hpp>
#include "opencv2/imgcodecs/legacy/constants_c.h"
using namespace std;
//BOOL RecvLine(SOCKET s, char* buf); //讀取一行數據

int main(int argc, char* argv[])
{
	const int BUF_SIZE = 1024;

	WSADATA wsd; //WSADATA變量
	SOCKET sHost; //服務器套接字
	SOCKADDR_IN servAddr; //服務器地址
	char buf[BUF_SIZE]; //接收數據緩衝區
	char bufRecv[102400] = {0};
	int retVal; //返回值
				//初始化套結字動態庫
	if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
	{
		cout << "WSAStartup failed!" << endl;
		return -1;
	}
	//創建套接字
	sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (INVALID_SOCKET == sHost)
	{
		cout << "socket failed!" << endl;
		WSACleanup();//釋放套接字資源
		return  -1;
	}

	//設置服務器地址
	servAddr.sin_family = AF_INET;
	servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	servAddr.sin_port = htons((short)4999);
	int nServAddlen = sizeof(servAddr);

	//連接服務器
	retVal = connect(sHost, (LPSOCKADDR)&servAddr, sizeof(servAddr));
	if (SOCKET_ERROR == retVal)
	{
		cout << "connect failed!" << endl;
		closesocket(sHost); //關閉套接字
		WSACleanup(); //釋放套接字資源
		return -1;
	}
	cout << " 向服務器發送數據:  ";
	cin >> buf;
	retVal = send(sHost, buf, strlen(buf), 0);
	while (true)
	{
		//向服務器發送數據
		//ZeroMemory(buf, BUF_SIZE);
		
		if (SOCKET_ERROR == retVal)
		{
			cout << "send failed!" << endl;
			closesocket(sHost); //關閉套接字
			WSACleanup(); //釋放套接字資源
			return -1;
		}
		//RecvLine(sHost, bufRecv);

		int len = recv(sHost, bufRecv, 102400, 0); // 接收服務器端的數據, 只接收5個字符

		std::vector<char> inImage;
		for (int i = 0; i < len; i++) {
			inImage.push_back(bufRecv[i]);
		}

		cv::Mat show = cv::imdecode(inImage, CV_LOAD_IMAGE_COLOR);
		imshow("circles112", show);
		cv::waitKey(1);
		
		//cv::VideoWriter videoWriter;
		//int w = 640;
		//int h = 480;
		//cv::Size videoSize(w, h);
		//videoWriter = cv::VideoWriter("D://out.avi", cv::VideoWriter::fourcc('D', 'I', 'V', 'X'), 20.0, videoSize);
		//videoWriter.write(show);
		//videoWriter.release();
	}
	//退出
	closesocket(sHost); //關閉套接字
	WSACleanup(); //釋放套接字資源
	return 0;
}

// 運行程序: Ctrl + F5 或調試 >“開始執行(不調試)”菜單
// 調試程序: F5 或調試 >“開始調試”菜單

// 入門提示: 
//   1. 使用解決方案資源管理器窗口添加/管理文件
//   2. 使用團隊資源管理器窗口連接到源代碼管理
//   3. 使用輸出窗口查看生成輸出和其他消息
//   4. 使用錯誤列表窗口查看錯誤
//   5. 轉到“項目”>“添加新項”以創建新的代碼文件,或轉到“項目”>“添加現有項”以將現有代碼文件添加到項目
//   6. 將來,若要再次打開此項目,請轉到“文件”>“打開”>“項目”並選擇 .sln 文件

opencvsharp
播放視頻,保存視頻, 使用picture播放

using System;
using OpenCvSharp;
using System.Windows.Forms;
using OpenCvSharp.Extensions;
using System.Threading;

namespace RiceCooker
{
    class CapUtil
    {
        //this.pictureBox1.Paint += PictureBox1_Paint;
        private void PictureBox1_Paint(object sender, PaintEventArgs e)
        {
            if (imgshow != null)
            {


               // Invalidate(); pictureBox1.Invalidate();
                //e.Graphics.DrawImage(imgshow, 0, 0);

            }
        }
            System.Drawing.Bitmap imgshow;
        private void button1_Click(object sender, EventArgs e)
        {
            //CamFunc_01();

            /*cap.Open(0);                             //打開攝像頭
            int sleepTime = (int)Math.Round(1000 / cap.Fps);
            Cv2.WaitKey(sleepTime);
            if (!cap.IsOpened()) return;             //判斷攝像頭是否已經打開
            Thread.Sleep(1000);
            bool flag = true;
            while (flag)
            {
                Mat capMat = new Mat();
                //capMat = cap.RetrieveMat();
                cap.Read(capMat);
                if (capMat.Empty()) continue;

                Cv2.ImShow("CamFunc_00", capMat);  //顯示
                
                Cv2.ImWrite("D:\\test.png", capMat);
                capMat.Release();
                flag = false;
            }*/
            //Thread threadA = new Thread(run_cap);
            //threadA.Start();


            // Read movie frames and write them to VideoWriter 

        }
        void run_cap()
        {
            Mat src = new Mat();
            FrameSource frame = Cv2.CreateFrameSource_Camera(0);
            while (true)
            {

                frame.NextFrame(src);

                System.Drawing.Bitmap bitmap = BitmapConverter.ToBitmap(src);


                //Invalidate();
                //pictureBox1.Invalidate();


                imgshow = bitmap;

            }

        }
        static void CamFunc_0()
        {
            VideoCapture cap = new VideoCapture();
            Mat bgMat = new Mat();
            Mat capMat = new Mat();

            bool isFirstFrame = true;                //判斷是不是第一幀

            cap.Open(0);                             //打開攝像頭
            if (!cap.IsOpened()) return;             //判斷攝像頭是否已經打開
            Thread.Sleep(1000);
            while (true)                           //逐幀獲取攝像頭畫面
            {
                capMat = cap.RetrieveMat();      //獲取攝像頭畫面
                if (capMat.Empty()) continue;
                //   Cv2.CvtColor(capMat, capMat, ColorConversionCodes.BGR2GRAY);   //轉成灰度圖
                if (isFirstFrame)
                {
                    isFirstFrame = false;
                    bgMat = capMat;
                }

                for (int i = 0; i < capMat.Rows; i += 10)
                {
                    for (int j = 0; j < capMat.Cols; j += 10)
                    {
                        //這樣寫不知道有沒有什麼問題,但是能實現效果,先就這樣寫,獲取像素點的rgb值做對比,其中50是差值,可根據自己需求來調節
                        if (Math.Abs(capMat.Get<Vec3b>(i, j).Item0 - bgMat.Get<Vec3b>(i, j).Item0) > 50 || Math.Abs(capMat.Get<Vec3b>(i, j).Item1 - bgMat.Get<Vec3b>(i, j).Item1) > 50 || Math.Abs(capMat.Get<Vec3b>(i, j).Item2 - bgMat.Get<Vec3b>(i, j).Item2) > 50)
                        {
                            Cv2.Circle(capMat, new Point(j, i), 2, Scalar.White, 4); //畫圓,在capMat的(j,i)位置畫半徑爲2,厚度爲4的白色的實心圓
                        }
                    }
                }

                Cv2.ImShow("CamFunc_00", capMat);  //顯示
                Cv2.WaitKey(20);
            }
        }
        static void CamFunc_01()     //前後兩幀對比,此時物體需要一直移動才能被檢測出
        {
            VideoCapture cap = new VideoCapture();
            Mat lastMat = new Mat();
            Mat capMat = new Mat();

            bool isEvenFrame = true;           //判斷是不是偶數幀,即爲參照幀    

            cap.Open(0);                             //打開攝像頭
            if (!cap.IsOpened()) return;             //判斷攝像頭是否已經打開

            while (true)                           //逐幀獲取攝像頭畫面
            {
                capMat = cap.RetrieveMat();           //獲取攝像頭畫面
                //cap.Read(capMat);
                if (capMat.Empty()) continue;
                //   Cv2.CvtColor(capMat, capMat, ColorConversionCodes.BGR2GRAY);   //轉成灰度圖
                if (isEvenFrame)
                {
                    isEvenFrame = false;
                    lastMat = capMat;
                }

                else
                {
                    for (int i = 0; i < capMat.Rows; i += 10)   //遍歷capMat所有像素
                    {
                        for (int j = 0; j < capMat.Cols; j += 10)
                        {
                            //這樣寫不知道有沒有什麼問題,但是能實現效果,先就這樣寫,獲取像素點的rgb值做對比,其中50是差值,可根據自己需求來調節
                            if (Math.Abs(capMat.Get<Vec3b>(i, j).Item0 - lastMat.Get<Vec3b>(i, j).Item0) > 50 || Math.Abs(capMat.Get<Vec3b>(i, j).Item1 - lastMat.Get<Vec3b>(i, j).Item1) > 50 || Math.Abs(capMat.Get<Vec3b>(i, j).Item2 - lastMat.Get<Vec3b>(i, j).Item2) > 50)
                            {
                                Cv2.Circle(capMat, new Point(j, i), 2, Scalar.White, 4); //畫圓,在capMat的(j,i)位置畫半徑爲2,厚度爲4的白色的實心圓
                            }
                        }
                    }
                    isEvenFrame = true;
                }
                Cv2.ImShow("CamFunc_01", capMat); //顯示
                Cv2.WaitKey(20);

            }
        }
    }
}

socket server:

using System;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.IO;
using OpenCvSharp;

namespace RiceCooker
{
    class Server
    {
        private int port;//監聽端口號
        private static byte[] result = new byte[1024];
        private static Socket server;//服務器Socket
        private IPAddress ip;//Ip地址
        private static Socket client;//客戶端Socket
        private static Thread myThread;//啓動監聽線程
        private static Thread receiveThread;//接收數據線程
        public Server(string ipadr, int port)
        {
            this.port = port;//初始化端口
            ip = IPAddress.Parse(ipadr);//初始化ip地址

        }
        public void setConnection()
        {
            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//實例化socket對象(採用網絡流傳輸方式,TCP協議傳輸)
            server.Bind(new IPEndPoint(ip, port));//綁定ip及端口
            Console.WriteLine("綁定端口ip" + this.ip + ":" + this.port);
            server.Listen(10);//監聽端口
            Console.WriteLine("正在監聽IP" + this.ip + "  端口:" + this.port + "......");
            myThread = new Thread(ListenClientConnect);
            myThread.Start();
        }

        private static void ListenClientConnect()
        {
            while (true)
            {
                client = server.Accept();
                receiveThread = new Thread(ReceiveMessage);
                receiveThread.Start(client);
            }
        }

        /// <summary>  
        /// 接收消息  
        /// </summary>  
        /// <param name="clientSocket"></param>  
        private static void ReceiveMessage(object clientSocket)
        {

            client = (Socket)clientSocket;
            while (true)
            {
                try
                {
                    //通過clientSocket接收數據  
                    int receiveNumber = client.Receive(result);//獲取接收數據的長度
                    StreamWriter resultMessage = new StreamWriter("out.txt", true);//輸出流實例化
                    resultMessage.WriteLine("接收客戶端{0}消息{1}", client.RemoteEndPoint.ToString(), Encoding.ASCII.GetString(result, 0, receiveNumber));
                    resultMessage.Close();
                    Console.WriteLine("信息獲取成功");
                    byte[] arrMsg = Encoding.UTF8.GetBytes("dfadsfs");

                    VideoCapture cap = new VideoCapture();
                    cap.Open(0);
                    Thread.Sleep(1000);
                    //int i = 0;
                    //while (i < 100)
                    //{
                     //   i++;
                        Mat frame = new Mat();
                        cap.Read(frame);
                        if (frame.Empty())
                            break;
                        byte[] arrList = new byte[1024 * 1024];
                        Cv2.ImEncode(".jpg", frame,out arrList);
                        //string str = frame.DataPointer;
                        client.Send(arrList);
                    //}
                    
                }
                catch (Exception ex)
                {
                    Console.WriteLine("從服務器獲取數據錯誤" + "錯誤信息" + ex.Message);
                    client.Shutdown(SocketShutdown.Both);
                    client.Close();
                    break;
                }
            }
        }
    }
}

socket client

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using OpenCvSharp;

namespace RiceCookerClient
{
    class Client
    {
        private byte[] result = new byte[1024];
        public void Send()
        {
            //設定服務器IP地址  
            IPAddress ip = IPAddress.Parse("127.0.0.1");
            Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                clientSocket.Connect(new IPEndPoint(ip, 4999)); //配置服務器IP與端口  
                Console.WriteLine("連接服務器成功");
                Thread thread = new Thread(ReciveMsg);
                thread.IsBackground = true;
                thread.Start(clientSocket);
            }
            catch
            {
                Console.WriteLine("連接服務器失敗,請按回車鍵退出!");
                return;
            }
            //for (int i = 0; i < 10; i++)
            //{
                try
                {
                    Thread.Sleep(1000);    //等待1秒鐘  
                    string sendMessage = "client send Message Hellp" + DateTime.Now;
                    clientSocket.Send(Encoding.ASCII.GetBytes(sendMessage));
                    Console.WriteLine("向服務器發送消息:{0}" + sendMessage);
                    
                }
                catch
                {
                    clientSocket.Shutdown(SocketShutdown.Both);
                    clientSocket.Close();
                    //break;
                }
            //}
            Console.WriteLine("發送完畢,按回車鍵退出");
            Console.ReadLine();
        }
        void ReciveMsg(object o)
        {
            Socket client = o as Socket;
            while (true)
            {
                try
                {
                    ///定義客戶端接收到的信息大小
                    byte[] arrList = new byte[1024 * 1024];
                    ///接收到的信息大小(所佔字節數)
                    int length = client.Receive(arrList);

                    Mat mat = Cv2.ImDecode(arrList, ImreadModes.AnyColor);
                    Cv2.ImShow("123", mat);
                    //Size dsize = new Size(640, 480);
                    //using (VideoWriter writer = new VideoWriter("D://out.avi", VideoWriter.FourCC('D', 'I', 'V', 'X'), 20.0, dsize))
                    //{
                        //Mat frame = new Mat(arrList);
                    //    writer.Write(mat);
                   // }

                    //string msg = DateTime.Now + Encoding.UTF8.GetString(arrList, 0, length);
                    //Console.WriteLine("接收:{0}" + msg);

                }
                catch (Exception e)
                {
                    ///關閉客戶端
                    client.Close();
                }

            }
        }
    }
}

==c++使用socket,用mat的ptr指針的數據進行通信
socket server:

#include "opencv2/opencv.hpp"
#include <WinSock2.h>
#include <Windows.h>
#pragma comment (lib, "ws2_32.lib")  //加載 ws2_32.dll
#pragma warning(disable : 4996)

//待傳輸圖像默認大小爲 640*480,可修改
#define IMG_WIDTH 640	// 需傳輸圖像的寬
#define IMG_HEIGHT 480	// 需傳輸圖像的高
//默認格式爲CV_8UC3
#define BUFFER_SIZE IMG_WIDTH*IMG_HEIGHT*3/32 
using namespace cv;


struct sentbuf{
	char buf[BUFFER_SIZE];
	int flag;
};
sentbuf data;
void sendMat(SOCKET sockClient, Mat image);

int main(int, char**)
{
	VideoCapture cap(0); // open the default camera
	if (!cap.isOpened())  // check if we succeeded
		return -1;
	Mat frame;
	//初始化 DLL
	WSADATA wsaData;
	::WSAStartup(MAKEWORD(2, 0), &wsaData);
	//創建套接字
	SOCKET servSock = ::socket(AF_INET, SOCK_STREAM, 0);

	//綁定套接字
	sockaddr_in sockAddr;
	sockAddr.sin_family = AF_INET;
	sockAddr.sin_addr.S_un.S_addr = inet_addr("192.168.199.222");
	sockAddr.sin_port = htons(1234);
	::bind(servSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
	//進入監聽狀態
	listen(servSock, 5);
	//接收客戶端請求
	SOCKADDR clntAddr;
	int nSize = sizeof(SOCKADDR);
	SOCKET clntSock = accept(servSock, (SOCKADDR*)&clntAddr, &nSize);
	std::cout << "linked\n";
	for (;;)
	{
		cap >> frame; // get a new frame from camera
		sendMat(clntSock, frame);
	}
	// the camera will be deinitialized automatically in VideoCapture destructor

	//關閉套接字
	closesocket(clntSock);
	closesocket(servSock);

	//終止 DLL 的使用
	WSACleanup();
	return 0;
}
void sendMat(SOCKET sockClient, Mat image) {
	for (int k = 0; k < 32; k++) {
		int num1 = IMG_HEIGHT / 32 * k;
		for (int i = 0; i < IMG_HEIGHT / 32; i++) {
			int num2 = i * IMG_WIDTH * 3;
			uchar* ucdata = image.ptr<uchar>(i + num1);
			for (int j = 0; j < IMG_WIDTH * 3; j++) {
				data.buf[num2 + j] = ucdata[j];
			}
		}
		if (k == 31)
			data.flag = 2;
		else
			data.flag = 1;
		send(sockClient, (char *)(&data), sizeof(data), 0);
	}
}

socket client:

#include <opencv2/opencv.hpp>
#include <WinSock2.h>
#include <Windows.h>
#pragma comment (lib, "ws2_32.lib")
#pragma warning(disable : 4996)
using namespace cv;

//待傳輸圖像默認大小爲 640*480,可修改
#define IMG_WIDTH 640	// 需傳輸圖像的寬
#define IMG_HEIGHT 480	// 需傳輸圖像的高
//默認格式爲CV_8UC3
#define BUFFER_SIZE IMG_WIDTH*IMG_HEIGHT*3/32 
struct recvbuf
{
	char buf[BUFFER_SIZE];
	int flag;
};
recvbuf data_recv;
Mat recieveMat(SOCKET sockServer);
int main() {
	
	//初始化 DLL
	WSADATA data;
	WORD w = MAKEWORD(2, 0);
	::WSAStartup(w, &data);
	// 創建套接字
	SOCKET s;
	s = ::socket(AF_INET, SOCK_STREAM, 0);

	// 構造ip地址
	sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_addr.S_un.S_addr = inet_addr("192.168.199.222");
	addr.sin_port = htons(1234);
	std::cout << "connecting\n";
	::connect(s, (sockaddr*)&addr, sizeof(addr));
	std::cout << "linked\n";
	while (true) {
		Mat frame = recieveMat(s);
		if (frame.data) imshow("Camera", frame);
		if (waitKey(1) >= 0)break;
	}
	::closesocket(s);
	::WSACleanup();

}


Mat recieveMat(SOCKET sockServer) {
	Mat img(IMG_HEIGHT, IMG_WIDTH, CV_8UC3, cv::Scalar(0));
	int needRecv = sizeof(recvbuf);
	int count = 0;
	for (int i = 0; i < 32; i++) {
		int pos = 0;
		int len0 = 0;
		while (pos < needRecv) {
			len0 = recv(sockServer, (char*)(&data_recv) + pos, needRecv - pos, 0);
			pos += len0;
		}
		count = count + data_recv.flag;
		int num1 = IMG_HEIGHT / 32 * i;
		for (int j = 0; j < IMG_HEIGHT / 32; j++) {
			int num2 = j * IMG_WIDTH * 3;
			uchar* ucdata = img.ptr<uchar>(j + num1);
			for (int k = 0; k < IMG_WIDTH * 3; k++) {
				ucdata[k] = data_recv.buf[num2 + k];
			}
		}
		if (data_recv.flag == 2) {
			if (count == 33) {
				return img;
			}
			else {
				count = 0;
				i = 0;
			}
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章