使用yolov5-lite对屏幕进行目标检测

目录

1. 修改检测网络

1.1 删除int8量化,使用摄像头等用不到的内容

1. 2 修改用到的参数

1.3 设置鼠标移动

1.4 将mian函数改为预测函数

2. 实现屏幕检测

3. 效果展示

4. 代码链接

5. 参考链接


一般情况下,目标检测的内容都是摄像头捕捉到的视频,但有时候我们可能需要检测屏幕画面是否存在某些内容,并在检测出后使用鼠标去指向它...

1. 修改检测网络

模型选用轻量化的yolov5-lite,源码见参考链接1,由于使用不是很顺手,对源码进行了少量修改

1.1 删除int8量化,使用摄像头等用不到的内容

1. 2 修改用到的参数

float unsig_pro;
float myprop = 0.30f;
const float prob_threshold = 0.31f;
const float nms_threshold = 0.60f;
// 获取屏幕长宽
int nWidth = GetSystemMetrics(SM_CXSCREEN);
int	nHeight = GetSystemMetrics(SM_CYSCREEN);
const int target_size = 320;
float scale_x = nWidth / target_size;
float scale_y = nHeight / target_size;

1.3 设置鼠标移动

// 将鼠标移动到置信度最高的目标的中心        
if (i == 0) {
            SetCursorPos(int((x0 + objects[i].rect.width / 2) * scale_x), int((y0 + objects[i].rect.height / 2) * scale_y));
            Sleep(1); // 用于休眠,没啥用,可以删掉
        }

1.4 将mian函数改为预测函数

void detect(cv::Mat mat1, cv::Mat &mat2){
    std::vector objects;
    detect_yolov5(mat1, objects);
    mat2 = draw_objects(mat1, objects);
}

2. 实现屏幕检测

直接上代码,注释写的很详细

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

// 定义鼠标宏
#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0) 

using namespace std;
using namespace cv;

// 从yolov5-lite拿到预测函数
extern void detect(cv::Mat mat1, cv::Mat &mat2);
// 截屏
void Screen();
// hBitmap转IplImage
IplImage* hBitmapToIpl(HBITMAP hBmp);

// 定义变量和指针
HBITMAP	hBmp;
HBITMAP	hOld;
Mat dst;
Mat image;
IplImage* inter;

// 拿到屏幕尺寸
extern int nWidth;
extern int nHeight;
int main()
{
	while (true)
	{
		// 捕捉鼠标右键休眠,滚轮退出,全局可用
		if (KEY_DOWN(VK_RBUTTON)) { Sleep(5000); }
		else if (KEY_DOWN(VK_MBUTTON)) {break; }

		// 屏幕截取
		Screen();
		// hBitmap转IplImage
		inter = hBitmapToIpl(hBmp);
		// IplImage转Mat
		image = cvarrToMat(inter);
		// 图像处理
		resize(image, image, cv::Size(320, 320));
		// 检测
		detect(image, dst);
		// 缩放显示
		resize(dst, dst, cv::Size(nWidth/4, nHeight/4));

		// 窗口置顶
		namedWindow("window");
		HWND hWnd = (HWND)cvGetWindowHandle("window");
		HWND hRawWnd = ::GetParent(hWnd);
		if (NULL != hRawWnd)
		{
			BOOL bRet = ::SetWindowPos(hRawWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
			//assert(bRet);
		}

		// 图像显示
		cv::imshow("window", dst);
		cv::waitKey(1);

		// 释放内存
		DeleteObject(hBmp);
		cvReleaseImage(&inter);
	}
	return 0;
}


IplImage* hBitmapToIpl(HBITMAP hBmp)
{
	BITMAP bmp;
	GetObject(hBmp, sizeof(BITMAP), &bmp);   
	// 通道
	int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel / 8;
	// 通道深度
	int depth = bmp.bmBitsPixel == 1 ? IPL_DEPTH_1U : IPL_DEPTH_8U;
	// 预分配空间
	IplImage* img = cvCreateImage(cvSize(bmp.bmWidth, bmp.bmHeight), depth, nChannels);
	// 申请内存
	BYTE* pBuffer = new BYTE[bmp.bmHeight * bmp.bmWidth * nChannels*5];
	// 将输入图片内容传入中间变量pBuffer 
	GetBitmapBits(hBmp, bmp.bmHeight * bmp.bmWidth * nChannels, pBuffer);
	// 将图片内容从中间变量转到img
	memcpy(img->imageData, pBuffer, bmp.bmHeight * bmp.bmWidth * nChannels);
	// 释放内存
	delete[] pBuffer;
	pBuffer = nullptr;
	// 创建目标图片
	IplImage* dst = cvCreateImage(cvGetSize(img), img->depth, 3);
	// 拷贝并转换颜色
	cvCvtColor(img, dst, CV_BGRA2BGR);
	// 释放内存
	cvReleaseImage(&img);
	return dst;
}


//抓取当前屏幕函数
void Screen() {
	//创建画板
	HDC hScreen = CreateDC(L"DISPLAY", NULL, NULL, NULL);
	HDC	hCompDC = CreateCompatibleDC(hScreen);
	//取屏幕宽度和高度
	int	nWidth = GetSystemMetrics(SM_CXSCREEN);
	int	nHeight = GetSystemMetrics(SM_CYSCREEN);
	//创建Bitmap对象
	hBmp = CreateCompatibleBitmap(hScreen, nWidth, nHeight);
	hOld = (HBITMAP)SelectObject(hCompDC, hBmp);
	BitBlt(hCompDC, 0, 0, nWidth, nHeight, hScreen, 0, 0, SRCCOPY);
	SelectObject(hCompDC, hOld);
	//释放对象
	DeleteDC(hScreen);
	DeleteDC(hCompDC);
}

3. 效果展示

需要注意的是,鼠标右键-》显示设置界面,要将缩放与布局改为100%,不然只能检测部分屏幕;

使用yolov5-lite对屏幕进行目标检测_第1张图片

 当然,也可以不改,根据屏幕分辨率手动设置nWidth和nHeight就可以了,我这里是×2。

4. 代码链接

liuweixue001/screen_detect: 基于yolov5-lite对屏幕进行目标检测 (github.com)

5. 参考链接

ppogg/YOLOv5-Lite: YOLOv5-Lite: lighter, faster and easier to deploy. Evolved from yolov5 and the size of model is only 930+kb (int8) and 1.7M (fp16). It can reach 10+ FPS on the Raspberry Pi 4B when the input size is 320×320~ (github.com)

你可能感兴趣的:(目标检测,计算机视觉,人工智能)