Beep.h
cpp
#pragma once
#include <cstdio>
#include <windows.h>
#define qdo 262
#define qre 294
#define qmi 330 //q前缀为低音,1后缀为高音,s前缀为半音阶
#define qfa 349
#define qso 392
#define qla 440
#define qsi 494
#define do 523
#define re 578
#define mi 659
#define fa 698
#define so 784
#define la 880
#define si 988
#define do1 1046
#define re1 1175
#define mi1 1318
#define fa1 1480
#define so1 1568
#define la1 1760
#define si1 1976
#define sqdo 277
#define sqre 311
#define sqfa 370
#define sqso 415
#define sqla 466
#define sdo 554
#define sre 622
#define sfa 740
#define sso 831
#define sla 932
#define sdo1 1046
#define sre1 1245
#define sfa1 1480
#define sso1 1661
#define sla1 1865
#define pai 400
#define ban 200
#define ting 128
Screenshot.h
cpp
#pragma once
#include <Windows.h>
#include <opencv2/opencv.hpp>
class Screenshot
{
public:
Screenshot();
double static getZoom();
cv::Mat getScreenshot();
cv::Mat getScreenshot(int x, int y, int width, int height);
private:
int m_width;
int m_height;
HDC m_screenDC;
HDC m_compatibleDC;
HBITMAP m_hBitmap;
LPVOID m_screenshotData = nullptr;
};
Sreenshot.cpp
cpp
#include "Screenshot.h"
using cv::Mat;
Screenshot::Screenshot()
{
double zoom = getZoom();
m_width = GetSystemMetrics(SM_CXSCREEN) * zoom;
m_height = GetSystemMetrics(SM_CYSCREEN) * zoom;
m_screenshotData = new char[m_width * m_height * 4];
memset(m_screenshotData, 0, m_width);
// 获取屏幕 DC
m_screenDC = GetDC(NULL);
m_compatibleDC = CreateCompatibleDC(m_screenDC);
// 创建位图
m_hBitmap = CreateCompatibleBitmap(m_screenDC, m_width, m_height);
SelectObject(m_compatibleDC, m_hBitmap);
}
/* 获取整个屏幕的截图 */
Mat Screenshot::getScreenshot()
{
// 得到位图的数据
BitBlt(m_compatibleDC, 0, 0, m_width, m_height, m_screenDC, 0, 0, SRCCOPY);
GetBitmapBits(m_hBitmap, m_width * m_height * 4, m_screenshotData);
// 创建图像
Mat screenshot(m_height, m_width, CV_8UC4, m_screenshotData);
return screenshot;
}
/** @brief 获取指定范围的屏幕截图
* @param x 图像左上角的 X 坐标
* @param y 图像左上角的 Y 坐标
* @param width 图像宽度
* @param height 图像高度
*/
Mat Screenshot::getScreenshot(int x, int y, int width, int height)
{
Mat screenshot = getScreenshot();
return screenshot(cv::Rect(x, y, width, height));
}
/* 获取屏幕缩放值 */
double Screenshot::getZoom()
{
// 获取窗口当前显示的监视器
HWND hWnd = GetDesktopWindow();
HMONITOR hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
// 获取监视器逻辑宽度
MONITORINFOEX monitorInfo;
monitorInfo.cbSize = sizeof(monitorInfo);
GetMonitorInfo(hMonitor, &monitorInfo);
int cxLogical = (monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left);
// 获取监视器物理宽度
DEVMODE dm;
dm.dmSize = sizeof(dm);
dm.dmDriverExtra = 0;
EnumDisplaySettings(monitorInfo.szDevice, ENUM_CURRENT_SETTINGS, &dm);
int cxPhysical = dm.dmPelsWidth;
return cxPhysical * 1.0 / cxLogical;
}
main.cpp
cpp
#include "Screenshot.h"
#include "Beep.h"
#include<Windows.h>
using namespace std;
using namespace cv;
// 发出警报
void warning()
{
while (true)
{
Beep(la, pai);
}
}
// 显示截取的图像
void show(Mat img_wite,Mat img_red)
{
imshow("src", img_wite);
waitKey();
system("pause");
imshow("src", img_red);
waitKey();
system("pause");
}
// 图像锐化
void alter(Mat img_wite)
{
for (int j = 0; j < img_wite.rows; j++)
{
for (int i = 0; i < img_wite.cols; i++)
{
//printf("%d %d %d \n", img_wite.at<cv::Vec3b>(j, i)[0], img_wite.at<cv::Vec3b>(j, i)[1], img_wite.at<cv::Vec3b>(j, i)[2]);
// 如果rgb值中其中一个值大于255,则将其值重新赋值为其他俩值的平均数,因为本图像只有灰度
if (img_wite.at<cv::Vec3b>(j, i)[0] == 255)
{
img_wite.at<cv::Vec3b>(j, i)[0] = (img_wite.at<cv::Vec3b>(j, i)[1] + img_wite.at<cv::Vec3b>(j, i)[2]) / 2;
}
if (img_wite.at<cv::Vec3b>(j, i)[1] == 255)
{
img_wite.at<cv::Vec3b>(j, i)[1] = (img_wite.at<cv::Vec3b>(j, i)[0] + img_wite.at<cv::Vec3b>(j, i)[2]) / 2;
}
if (img_wite.at<cv::Vec3b>(j, i)[2] == 255)
{
img_wite.at<cv::Vec3b>(j, i)[2] = (img_wite.at<cv::Vec3b>(j, i)[1] + img_wite.at<cv::Vec3b>(j, i)[0]) / 2;
}
// 然后来判断他是深色背景还是浅色字体
if (img_wite.at<cv::Vec3b>(j, i)[0] +
img_wite.at<cv::Vec3b>(j, i)[1] + img_wite.at<cv::Vec3b>(j, i)[2] > 250
)
{
img_wite.at<cv::Vec3b>(j, i)[0] = 255;
img_wite.at<cv::Vec3b>(j, i)[1] = 255;
img_wite.at<cv::Vec3b>(j, i)[2] = 255;
}
else
{
img_wite.at<cv::Vec3b>(j, i)[0] = 0;
img_wite.at<cv::Vec3b>(j, i)[1] = 0;
img_wite.at<cv::Vec3b>(j, i)[2] = 0;
}
//printf("%d", img_wite.at<cv::Vec3b>(j, i)[2] == 255 ? 1 : 0);
}
//printf("\n");
}
}
// 俩Mat进行比较,判断是否相同
bool comp(Mat mat1, Mat mat2)
{
int diff = 0;
for (int j = 0; j < mat1.rows; j++)
{
for (int i = 0; i < mat1.cols; i++)
{
if (!((int)mat1.at<cv::Vec3b>(j, i)[0] == (int)mat2.at<cv::Vec3b>(j, i)[0] &&
(int)mat1.at<cv::Vec3b>(j, i)[1] == (int)mat2.at<cv::Vec3b>(j, i)[1] &&
(int)mat1.at<cv::Vec3b>(j, i)[2] == (int)mat2.at<cv::Vec3b>(j, i)[2]))
{
diff++;
/* cout << (int)mat1.at<cv::Vec3b>(j, i)[0] << (int)mat2.at<cv::Vec3b>(j, i)[0] << endl;
cout << (int)mat1.at<cv::Vec3b>(j, i)[1] << (int)mat2.at<cv::Vec3b>(j, i)[1] << endl;
cout << (int)mat1.at<cv::Vec3b>(j, i)[2] << (int)mat2.at<cv::Vec3b>(j, i)[2] << endl;*/
//return false;
}
}
}
if (diff>100)
{
return false;
}
else
{
return true;
}
}
int main()
{
system("pause");
Screenshot screenshot1;
Screenshot screenshot;
// 截取全屏
//Mat img = screenshot.getScreenshot();
// 截取红白都没有的状态
Mat src_wite;
Mat src_red;
src_wite = screenshot1.getScreenshot(194, 740, 30, 40);
src_red = screenshot1.getScreenshot(338, 740, 30, 40);
alter(src_red);
alter(src_wite);
Mat img_wite;
Mat img_red;
while (true)
{
Sleep(1000);
img_wite = screenshot.getScreenshot(194, 740, 30, 40);
img_red = screenshot.getScreenshot(338, 740, 30, 40);
// 图像锐化
alter(img_red);
alter(img_wite);
// 如果俩都没发生变化,返回的都是true
if (comp(img_red, src_red)==false || comp(img_wite, src_wite)==false)
{
cout << "开始警报" << endl;
warning();
}
else
{
cout << "安全" << endl;
}
}
// 临时显示截取的图片
//show(img_wite, img_red);
// 释放内存
img_wite.release();
img_red.release();
src_wite.release();
src_red.release();
// 将mat保存
// imwrite("screenshot_part.jpg", img_);
return 0;
}