使用ZeroMQ+GDI+Opencv实现电脑远程画面

运行效果 

下载地址(压缩文件密码:123456789) https://wwkm.lanzouf.com/izpqr0ja7msh

第一步 编译ZeroMQ

在github官网找到ZeroMQ,使用cmake进行编译生成dll\lib

第二步 编译Opencv

在github官网找到Opencv,使用cmake进行编译生成dll\lib

第三步 写代码(服务端程序)

// ServerTmp.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <zmq.h>
#include <opencv2\opencv.hpp>

#pragma comment(lib,"opencv_world343.lib")
#pragma comment(lib,"libzmq-v140-mt-4_3_2.lib")

using namespace cv;
using namespace std;


BITMAPINFOHEADER createBitmapHeader(int width, int height);
Mat captureScreenMat(HWND hwnd);

int main()
{
	int b1, b2, b3;
	void * con = zmq_init(1);
	void * sck = zmq_socket(con, ZMQ_PUB);
	zmq_bind(sck, "tcp://*:8966");
	zmq_version(&b1, &b2, &b3);

	String s= cv::getVersionString();
	printf("OPENCV Vers: %s\n", s);
	printf("ZeroMQ Vers: %d.%d.%d\n", b1,b2,b3);
	std::vector<uchar> data_encode;
	//cv::namedWindow("0", 1);
	
	while (true)
	{
		HWND hwnd = GetDesktopWindow();
		Mat src = captureScreenMat(hwnd);
		data_encode.clear();
		cv::imencode(".jpg", src, data_encode);  // 编码图片
		//cv::imshow("0", src);
		zmq_msg_t msg;
		zmq_msg_init_size(&msg, data_encode.size());
		memcpy((char*)zmq_msg_data(&msg), (char*)data_encode.data(), data_encode.size());
		int ok = zmq_sendmsg(sck, &msg, 0);
		printf("Send Size: %d\n", ok);
		waitKey(350);
	}
    return 0;
}



BITMAPINFOHEADER createBitmapHeader(int width, int height)
{
	BITMAPINFOHEADER  bi;

	// create a bitmap
	bi.biSize = sizeof(BITMAPINFOHEADER);
	bi.biWidth = width;
	bi.biHeight = -height;  //this is the line that makes it draw upside down or not
	bi.biPlanes = 1;
	bi.biBitCount = 32;
	bi.biCompression = BI_RGB;
	bi.biSizeImage = 0;
	bi.biXPelsPerMeter = 0;
	bi.biYPelsPerMeter = 0;
	bi.biClrUsed = 0;
	bi.biClrImportant = 0;

	return bi;
}


Mat Sharpen(Mat input, int percent, int type)
{
	Mat result;
	Mat s = input.clone();
	Mat kernel;
	switch (type)
	{
	case 0:
		kernel = (Mat_<int>(3, 3) <<
			0, -1, 0,
			-1, 4, -1,
			0, -1, 0
			);
	case 1:
		kernel = (Mat_<int>(3, 3) <<
			-1, -1, -1,
			-1, 8, -1,
			-1, -1, -1
			);
	default:
		kernel = (Mat_<int>(3, 3) <<
			0, -1, 0,
			-1, 4, -1,
			0, -1, 0
			);
	}
	filter2D(s, s, s.depth(), kernel);
	result = input + s * 0.01 * percent;
	return result;

}

Mat captureScreenMat(HWND hwnd)
{
	Mat src;

	// get handles to a device context (DC)
	HDC hwindowDC = GetDC(hwnd);
	HDC hwindowCompatibleDC = CreateCompatibleDC(hwindowDC);
	SetStretchBltMode(hwindowCompatibleDC, COLORONCOLOR);

	// define scale, height and width
	int screenx = GetSystemMetrics(SM_XVIRTUALSCREEN);
	int screeny = GetSystemMetrics(SM_YVIRTUALSCREEN);
	int width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
	int height = GetSystemMetrics(SM_CYVIRTUALSCREEN);

	// create mat object
	src.create(height, width, CV_8UC4);

	// create a bitmap
	HBITMAP hbwindow = CreateCompatibleBitmap(hwindowDC, width, height);
	BITMAPINFOHEADER bi = createBitmapHeader(width, height);

	// use the previously created device context with the bitmap
	SelectObject(hwindowCompatibleDC, hbwindow);

	// copy from the window device context to the bitmap device context
	StretchBlt(hwindowCompatibleDC, 0, 0, width, height, hwindowDC, screenx, screeny, width, height, SRCCOPY);  //change SRCCOPY to NOTSRCCOPY for wacky colors !
	GetDIBits(hwindowCompatibleDC, hbwindow, 0, height, src.data, (BITMAPINFO*)&bi, DIB_RGB_COLORS);            //copy from hwindowCompatibleDC to hbwindow

	DeleteObject(hbwindow);
	DeleteDC(hwindowCompatibleDC);
	ReleaseDC(hwnd, hwindowDC);

	Mat newsrc = src;
	//画出鼠标的位置
	POINT pointp; 
	GetCursorPos(&pointp);

	cv::line(src, Point(pointp.x, pointp.y), Point(pointp.x, pointp.y), Scalar(0, 80, 0), 20);
	cv:circle(src, Point(pointp.x, pointp.y), 10, Scalar(255, 155, 255),5);

	cv::resize(src, newsrc, Size(width / 1.5, height / 1.5), 0, 0);
	Sharpen(newsrc, 80, 0);
	

	return newsrc;
}

第四步 写代码(客户端程序)

// ConsoleApplication4.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <zmq.h>
#include <opencv2\opencv.hpp>

#pragma comment(lib,"opencv_world343.lib")
#pragma comment(lib,"libzmq-v140-mt-4_3_2.lib")

using namespace cv;
using namespace std;



int main(int agrv, char *argv[])
{
	if (agrv != 3) {
		printf("input command  [IP] [PORT]\n[please input Enter]\n");
		getchar();
		return 0;
	}
	char *ip = argv[1];
	char *port = argv[2];

	char ipbuf[100];
	sprintf(ipbuf,"tcp://%s:%s", ip, port);
	printf("connect:[ %s ]\n", ipbuf);

	void * con = zmq_init(1);
	void * sck = zmq_socket(con, ZMQ_SUB);
	int ok= zmq_connect(sck, ipbuf);
	zmq_setsockopt(sck, ZMQ_SUBSCRIBE, nullptr, 0);

	printf("%d\n", ok);

	zmq_msg_t msg;
	cv::namedWindow("ServerDesktop", 1);
	std::vector<uchar> data_reply;
	cv::Mat img_decode;
	while (true)
	{
		zmq_msg_init(&msg);
		ok = zmq_recvmsg(sck, &msg, 0);
		size_t size= zmq_msg_size(&msg);
		printf("%d\n", size);
		data_reply.resize(size);
		memcpy(data_reply.data(), zmq_msg_data(&msg), size);
		img_decode = cv::imdecode(data_reply, cv::IMREAD_COLOR);
		cv::imshow("ServerDesktop", img_decode);
		cv::waitKey(1);
		
	}

	
    return 0;
}

第五步 在在服务端运行(双击打开就行),客户端运行前需要输入运行信息举例(Client.exe 【IP地址】 【端口8966】)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值