用Opencv+樹莓派+socket 實現遠程監控
網上現在很多基於樹莓派的遠程監控都是用的ssh來完成的,但是這樣不能獲取實時圖片數據用於後續處理,這裏介紹的是一種利用socket編程通過TCP協議實現的網絡傳輸,以實時獲取畫面。
材料:樹莓派(我用的3b+),一個免驅攝像頭,一臺電腦
準備工作:樹莓派安裝系統,同時配置opencv,樹莓派和電腦在同一局域網。
1實現原理
遠程監控自然分爲兩端,一邊是邊緣端用於獲取圖像信息並且發送圖片信息,另一邊也就是接收端用於接受圖像信息並顯示在屏幕上。
1.1 圖像傳輸方法
這裏使用的是socket編程通過TCP協議傳輸圖像信息,具體的socket編程相關原理這裏不做詳細贅述。但是有人會問,圖像信息是怎麼通過TCP傳輸的呢,這裏用到了opencv自帶的圖像解編碼函數:
cv::imencode Mat數據編碼成數據流
cv::imdecode 數據流解碼成Mat
通過imencode將圖片信息變成數據流,用於傳輸,PC端接到後再用imdecode函數解碼爲Mat類型數據。
1.2邊緣端
將攝像頭插到樹莓派上,並用5v,2.5A的電源給樹莓派供電,使用前記得給攝像頭使能。我用紙盒做了一個簡單的定型。
1.3 PC端
PC端這邊用的VS2013+opencv2.49,代碼如下(代碼中的樹莓派IP可以在樹莓派中輸入 sudo ifconfig 裏面的wlan0裏面獲取,注意樹莓派和PC要在同一局域網下):
#include <iostream>
#include <string>
#include <WinSock2.h> //包含WinSock2.h頭文件
#include<opencv2\opencv.hpp>
using namespace std;
using namespace cv;
#pragma comment(lib, "ws2_32.lib") //加載 ws2_32.dll
#pragma warning(disable:4996)
#define BUF_SIZE 100
int main()
{
//****初始化
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
//****創建套接字
SOCKET sock = socket(PF_INET, SOCK_STREAM, 0);
//****創建sockAddr結構體
sockaddr_in sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr));
sockAddr.sin_family = PF_INET;
sockAddr.sin_port = htons(18000);
sockAddr.sin_addr.s_addr = inet_addr("192.168.1.100"); //樹莓派的局域網IP
//****建立連接
connect(sock, (SOCKADDR*)& sockAddr, sizeof(SOCKADDR));
cout << "客戶端發送鏈接請求" << endl;
char tack[20000] = { 0 };
//****接收服務器傳回的數據
Mat src;
Mat test = Mat::zeros(Size(300, 300), CV_8UC1);
Mat tring = Mat::zeros(Size(300, 300), CV_8UC1);
namedWindow("src", CV_WINDOW_AUTOSIZE);
int label = 0;
Mat t;
while (1)
{
if (recv(sock, tack, 18000, NULL) != (-1)) {
cout << "等待服務端發送信息.." << endl;
//cout << tack << endl;
cout << strlen(tack) << endl;
if (strlen(tack) != 4) {
label = 0;
memset(tack, 0, 20000); //重置緩衝區
continue;
}
else {
label = 1;
}
//輸出接收到的數據
if (strlen(tack) == 4 && label == 1) {
label = 1;
vector<uchar>end;
for (int i = 0; i < 18000; i++)
{
end.push_back(tack[i]);
}
src = imdecode(end, 1);
if (!src.data){
printf("no image");
src = t;
}
else{
src.copyTo(t);
}
medianBlur(src, src, 5); //去噪
imshow("src", src);
waitKey(10);
}
else {
continue;
}
memset(tack, 0, 20000); //重置緩衝區
}
}
//關閉套接字、終止使用 DLL
closesocket(sock);
WSACleanup();
return 0;
}
2 實驗效果
把樹莓派放在窗戶邊上:
先運行樹莓派上的程序(我用的電腦自帶的遠程桌面操作),樹莓派和電腦端顯示如下所示: