使用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);
}
  1. 实现屏幕检测

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

#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);
}
  1. 效果展示

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

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

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

使用yolov5-lite对屏幕进行目标检测
  1. 代码链接

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

  1. 参考链接

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)

Original: https://blog.csdn.net/m0_58772523/article/details/123692862
Author: 不变强不改名
Title: 使用yolov5-lite对屏幕进行目标检测

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/519995/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球