|
@@ -0,0 +1,472 @@
|
|
|
+#include "stdafx.h"
|
|
|
+#include "ImgAssist.h"
|
|
|
+
|
|
|
+
|
|
|
+namespace ImgAssist
|
|
|
+{
|
|
|
+ std::string CaptureGameWnd(HWND hWnd)
|
|
|
+ {
|
|
|
+ TCHAR szName[MAX_PATH] = { 0 };
|
|
|
+ _stprintf_s(szName, _T("%s%p.bmp"), GameGlobal::g_szTempDir, hWnd);
|
|
|
+ CaptureGameWnd(hWnd, szName);
|
|
|
+
|
|
|
+ return std::string(szName);
|
|
|
+ }
|
|
|
+
|
|
|
+ void CaptureGameWnd(HWND hWnd, std::string strSavePath)
|
|
|
+ {
|
|
|
+ HDC hDC = ::GetWindowDC(hWnd);
|
|
|
+ ASSERT(hDC);
|
|
|
+ HDC hMemDC = ::CreateCompatibleDC(hDC);
|
|
|
+ ASSERT(hMemDC);
|
|
|
+
|
|
|
+ RECT rc;
|
|
|
+ ::GetWindowRect(hWnd, &rc);
|
|
|
+ HBITMAP hBitmap = ::CreateCompatibleBitmap(hDC, rc.right - rc.left, rc.bottom - rc.top);
|
|
|
+
|
|
|
+ ASSERT(hBitmap);
|
|
|
+ HBITMAP hOldBmp = (HBITMAP)::SelectObject(hMemDC, hBitmap);
|
|
|
+
|
|
|
+ BOOL bRet = FALSE;
|
|
|
+ BOOL bProcessed = FALSE;
|
|
|
+ // 针对win10 DWM虚拟缩放时的处理
|
|
|
+ if (GetDeviceCaps(hDC, LOGPIXELSX) != 96)
|
|
|
+ {
|
|
|
+ DEVMODE curDevMode;
|
|
|
+ memset(&curDevMode, 0, sizeof(curDevMode));
|
|
|
+ curDevMode.dmSize = sizeof(DEVMODE);
|
|
|
+ BOOL bEnumRet = ::EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &curDevMode);
|
|
|
+ if (bEnumRet < curDevMode.dmPelsWidth)
|
|
|
+ {
|
|
|
+ bProcessed = TRUE;
|
|
|
+ //::SetStretchBltMode(hMemDC, STRETCH_HALFTONE);
|
|
|
+ //bRet = ::StretchBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, 0, 0, curDevMode.dmPelsWidth, curDevMode.dmPelsHeight, SRCCOPY | CAPTUREBLT);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ::PrintWindow(hWnd, hMemDC, 0);
|
|
|
+ BITMAP bitmap = { 0 };
|
|
|
+ ::GetObject(hBitmap, sizeof(BITMAP), &bitmap);
|
|
|
+ BITMAPINFOHEADER bi = { 0 };
|
|
|
+ BITMAPFILEHEADER bf = { 0 };
|
|
|
+ CONST int nBitCount = 24;
|
|
|
+ bi.biSize = sizeof(BITMAPINFOHEADER);
|
|
|
+ bi.biWidth = bitmap.bmWidth;
|
|
|
+ bi.biHeight = bitmap.bmHeight;
|
|
|
+ bi.biPlanes = 1;
|
|
|
+ bi.biBitCount = nBitCount;
|
|
|
+ bi.biCompression = BI_RGB;
|
|
|
+ DWORD dwSize = ((bitmap.bmWidth * nBitCount + 31) / 32) * 4 * bitmap.bmHeight;
|
|
|
+ HANDLE hDib = GlobalAlloc(GHND, dwSize + sizeof(BITMAPINFOHEADER));
|
|
|
+ if (hDib == NULL)
|
|
|
+ return;
|
|
|
+ LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
|
|
|
+ //memcpy(lpbi, &bi, sizeof(BITMAPINFOHEADER));
|
|
|
+ *lpbi = bi;
|
|
|
+ ::GetDIBits(hMemDC, hBitmap, 0, bitmap.bmHeight, (BYTE*)lpbi + sizeof(BITMAPINFOHEADER), (BITMAPINFO*)lpbi, DIB_RGB_COLORS);
|
|
|
+
|
|
|
+ CFile file;
|
|
|
+ CFileException fep;
|
|
|
+ if (file.Open(strSavePath.c_str(), CFile::modeCreate | CFile::modeWrite, &fep)) {
|
|
|
+ bf.bfType = 0x4d42;
|
|
|
+ dwSize += sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
|
|
|
+ bf.bfSize = dwSize;
|
|
|
+ bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
|
|
|
+ file.Write((BYTE*)&bf, sizeof(BITMAPFILEHEADER));
|
|
|
+ file.Write((BYTE*)lpbi, dwSize);
|
|
|
+ file.Close();
|
|
|
+ }
|
|
|
+
|
|
|
+ GlobalUnlock(hDib);
|
|
|
+ GlobalFree(hDib);
|
|
|
+ ::SelectObject(hMemDC, hOldBmp);
|
|
|
+ ::DeleteObject(hBitmap);
|
|
|
+ ::DeleteObject(hMemDC);
|
|
|
+ ::ReleaseDC(hWnd, hDC);
|
|
|
+
|
|
|
+ Sleep(30);
|
|
|
+ }
|
|
|
+
|
|
|
+ cv::Mat CaptureWnd(HWND hWnd)
|
|
|
+ {
|
|
|
+ HDC hdcMemDC = NULL; // 兼容DC;
|
|
|
+ HDC hdcWindow = NULL; // 窗口DC;
|
|
|
+ BITMAP bmpWindow = {0}; // BITMAP窗口对象;
|
|
|
+ HBITMAP hbmpWindow = NULL; // HBITMAP窗口对象;
|
|
|
+ DWORD dwBmpSize = 0; // BITMAP大小;
|
|
|
+ char* lpbitmap = NULL; // BITMAP数据;
|
|
|
+ HANDLE hDIB = NULL;
|
|
|
+ DWORD dwSizeofDIB = 0;
|
|
|
+ byte* pImgData = NULL;
|
|
|
+ // 获取窗口DC;
|
|
|
+ hdcWindow = ::GetWindowDC(hWnd);
|
|
|
+ // 创建窗口DC的兼容DC;
|
|
|
+ hdcMemDC = ::CreateCompatibleDC(hdcWindow);
|
|
|
+
|
|
|
+ RECT rc,rcc;
|
|
|
+ ::GetWindowRect(hWnd, &rc);
|
|
|
+ ::GetClientRect(hWnd, &rcc);
|
|
|
+ int width = rc.right - rc.left;
|
|
|
+ int height = rc.bottom - rc.top;
|
|
|
+ // 创建兼容位图;
|
|
|
+ hbmpWindow = ::CreateCompatibleBitmap(hdcWindow, width, height);
|
|
|
+ // 将位图选入兼容DC;
|
|
|
+ SelectObject(hdcMemDC, hbmpWindow);
|
|
|
+#if 1
|
|
|
+ // 将窗口复制到兼容DC中(当窗口被遮挡时,这个函数效果好)
|
|
|
+ if(!::PrintWindow(hWnd, hdcMemDC, 0))
|
|
|
+ {
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+#else
|
|
|
+ // 将目标DC的内容复制到兼容DC中;
|
|
|
+ if (!BitBlt(hdcMemDC, 0, 0, width, height, hdcWindow, 0, 0, SRCCOPY))
|
|
|
+ {
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ // 通过HBITMAP获取BITMAP
|
|
|
+ GetObject(hbmpWindow, sizeof(BITMAP), &bmpWindow);
|
|
|
+
|
|
|
+ BITMAPFILEHEADER bmfHeader = {0};
|
|
|
+ BITMAPINFOHEADER bi = {0};
|
|
|
+
|
|
|
+ bi.biSize = sizeof(BITMAPINFOHEADER);
|
|
|
+ bi.biWidth = bmpWindow.bmWidth;
|
|
|
+ bi.biHeight = bmpWindow.bmHeight;
|
|
|
+ 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;
|
|
|
+
|
|
|
+ dwBmpSize = ((bmpWindow.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpWindow.bmHeight;
|
|
|
+
|
|
|
+ // Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that
|
|
|
+ // call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc
|
|
|
+ // have greater overhead than HeapAlloc.
|
|
|
+ hDIB = GlobalAlloc(GHND, dwBmpSize);
|
|
|
+ if (hDIB == NULL)
|
|
|
+ {
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ lpbitmap = (char*)GlobalLock(hDIB);
|
|
|
+
|
|
|
+ // Gets the "bits" from the bitmap, and copies them into a buffer
|
|
|
+ // that's pointed to by lpbitmap.
|
|
|
+ GetDIBits(hdcMemDC, hbmpWindow, 0,
|
|
|
+ (UINT)bmpWindow.bmHeight,
|
|
|
+ lpbitmap,
|
|
|
+ (BITMAPINFO*)&bi, DIB_RGB_COLORS);
|
|
|
+
|
|
|
+ // Add the size of the headers to the size of the bitmap to get the total file size.
|
|
|
+ dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
|
|
|
+
|
|
|
+ // Offset to where the actual bitmap bits start.
|
|
|
+ bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
|
|
|
+
|
|
|
+ // Size of the file.
|
|
|
+ bmfHeader.bfSize = dwSizeofDIB;
|
|
|
+
|
|
|
+ // bfType must always be BM for Bitmaps.
|
|
|
+ bmfHeader.bfType = 0x4D42; // BM.
|
|
|
+
|
|
|
+ pImgData = new byte[dwSizeofDIB];
|
|
|
+ memset(pImgData, 0, dwSizeofDIB);
|
|
|
+ memcpy(pImgData, &bmfHeader, sizeof(BITMAPFILEHEADER));
|
|
|
+ memcpy(pImgData + sizeof(BITMAPFILEHEADER), &bi, sizeof(BITMAPINFOHEADER));
|
|
|
+ memcpy(pImgData + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER), lpbitmap, dwBmpSize);
|
|
|
+ GlobalUnlock(hDIB);
|
|
|
+ GlobalFree(hDIB);
|
|
|
+
|
|
|
+ done:
|
|
|
+ //DeleteObject(hbmWindow);
|
|
|
+ //DeleteObject(hdcMemDC);
|
|
|
+ //ReleaseDC(hWnd, hdcWindow);
|
|
|
+ CFile file;
|
|
|
+ CFileException fep;
|
|
|
+ if (file.Open("E:\\1.jpg", CFile::modeCreate | CFile::modeWrite, &fep)) {
|
|
|
+ file.Write(pImgData, dwSizeofDIB);
|
|
|
+ file.Close();
|
|
|
+ }
|
|
|
+
|
|
|
+ cv::Mat s22 = cv::imread("E:\\1.jpg");
|
|
|
+ cv::imwrite("E:\\2.jpg",s22);
|
|
|
+
|
|
|
+ //cv::Mat pic;
|
|
|
+ //int nChannels = bmpWindow.bmBitsPixel == 1 ? 1 : bmpWindow.bmBitsPixel / 8;
|
|
|
+ //pic.create(cv::Size(width, height), CV_8UC4);
|
|
|
+ //memcpy(pic.data, lpbitmap, dwBmpSize);
|
|
|
+ cv::_InputArray pirArrary(pImgData, dwSizeofDIB);
|
|
|
+ cv::Mat src = cv::imdecode(pirArrary, cv::IMREAD_COLOR);
|
|
|
+ cv::imwrite("E:\\3.bmp", src);
|
|
|
+ cv::imwrite("E:\\3.jpg", src);
|
|
|
+
|
|
|
+ cv::Mat matPic(height, width, CV_8UC4, pImgData + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));
|
|
|
+ cv::imwrite("E:\\4.jpg", matPic);
|
|
|
+ return cv::Mat();
|
|
|
+ }
|
|
|
+
|
|
|
+ BOOL OpenImage(std::string strImag, cv::Mat& img)
|
|
|
+ {
|
|
|
+ if (!PathFileExists(strImag.c_str()))
|
|
|
+ return FALSE;
|
|
|
+
|
|
|
+ if (img.data != NULL)
|
|
|
+ img.release();
|
|
|
+
|
|
|
+ img = cv::imread(strImag.c_str(), cv::IMREAD_COLOR);
|
|
|
+ if (img.data == NULL)
|
|
|
+ return FALSE;
|
|
|
+
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ BOOL SetImgThreshold(cv::Mat& srcImg, cv::Mat& thresholdImg, long nThresholdVal, long nMaxThresholdVal, int type)
|
|
|
+ {
|
|
|
+ if (srcImg.data == NULL)
|
|
|
+ return FALSE;
|
|
|
+
|
|
|
+ if (thresholdImg.data && srcImg.data != thresholdImg.data)
|
|
|
+ thresholdImg.release();
|
|
|
+
|
|
|
+ switch (type)
|
|
|
+ {
|
|
|
+ case 0://全局阀值;
|
|
|
+ {
|
|
|
+ // 转成灰阶图;
|
|
|
+ cv::cvtColor(srcImg, thresholdImg, cv::COLOR_BGR2GRAY);
|
|
|
+ // 再高斯模糊处理(滤波);
|
|
|
+ cv::GaussianBlur(thresholdImg, thresholdImg, cv::Size(5, 5), 0, 0);
|
|
|
+ // 二值化;//全局化指定的阀值与返回值相等;
|
|
|
+ double dRetVal = cv::threshold(thresholdImg, thresholdImg, nThresholdVal, nMaxThresholdVal, cv::THRESH_BINARY);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 1://自适应阀值;
|
|
|
+ {
|
|
|
+ // 转成灰阶图;
|
|
|
+ cv::cvtColor(srcImg, thresholdImg, cv::COLOR_BGR2GRAY);
|
|
|
+ // 再高斯模糊处理(滤波);
|
|
|
+ cv::GaussianBlur(thresholdImg, thresholdImg, cv::Size(3, 3), 0, 0);
|
|
|
+ // 自适应阀值;
|
|
|
+ cv::medianBlur(thresholdImg, thresholdImg, 3);
|
|
|
+ // 局部二值化;//blocksize一般取3、5、7
|
|
|
+ cv::adaptiveThreshold(thresholdImg, thresholdImg, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, 3, 4.5);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 2:// otsu阀值;
|
|
|
+ {
|
|
|
+ cv::cvtColor(srcImg, thresholdImg, cv::COLOR_BGR2GRAY);
|
|
|
+ // 高斯模糊;
|
|
|
+ cv::GaussianBlur(thresholdImg, thresholdImg, cv::Size(3, 3), 0, 0);
|
|
|
+ cv::threshold(thresholdImg, thresholdImg, nThresholdVal, nMaxThresholdVal, cv::THRESH_BINARY | cv::THRESH_OTSU);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return TRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ BOOL GetImgMatchtemplate(HWND hWnd, std::string strTempImg, RECT& rc, double lowestMatchValue)
|
|
|
+ {
|
|
|
+ std::string strImage = CaptureGameWnd(hWnd);
|
|
|
+ cv::Mat srcImg, tempImg, matchImg;
|
|
|
+ if (!OpenImage(strImage, srcImg) || !OpenImage(strTempImg, tempImg))
|
|
|
+ {
|
|
|
+ if (srcImg.data) srcImg.release();
|
|
|
+ if (tempImg.data) tempImg.release();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ cv::matchTemplate(srcImg, tempImg, matchImg, cv::TM_CCOEFF_NORMED);
|
|
|
+ // 归一化到0~1
|
|
|
+ //cv::normalize(matchImg, matchImg, 0, 1, cv::NORM_MINMAX, -1);
|
|
|
+
|
|
|
+ double lv_nMinVal = 0.0;
|
|
|
+ double lv_nMaxVal = 0.0;
|
|
|
+ cv::Point lv_nMinLoc = cv::Point(0, 0);
|
|
|
+ cv::Point lv_nMaxLoc = cv::Point(0, 0);
|
|
|
+ cv::Point lv_MatchLoc = cv::Point(0, 0);
|
|
|
+ cv::minMaxLoc(matchImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
|
|
|
+
|
|
|
+ cv::Rect roi = cv::Rect(lv_nMaxLoc.x, lv_nMaxLoc.y, tempImg.cols, tempImg.rows);
|
|
|
+ cv::Mat roiImg = srcImg(roi);
|
|
|
+ cv::imwrite(GameGlobal::BuildImgPath(hWnd, _T("match")), roiImg);
|
|
|
+
|
|
|
+ rc.left = lv_nMaxLoc.x - GameGlobal::frameWidth;
|
|
|
+ rc.top = lv_nMaxLoc.y - GameGlobal::titleBarHeight;
|
|
|
+ rc.right = rc.left + tempImg.cols;
|
|
|
+ rc.bottom = rc.top + tempImg.rows;
|
|
|
+
|
|
|
+ srcImg.release();
|
|
|
+ tempImg.release();
|
|
|
+ matchImg.release();
|
|
|
+ roiImg.release();
|
|
|
+
|
|
|
+ // 是否大于最低匹配度;
|
|
|
+ return (lv_nMaxVal >= lowestMatchValue ? TRUE : FALSE);
|
|
|
+ }
|
|
|
+
|
|
|
+ BOOL GetImgMatchtemplate(std::string strSrcImg, std::string strTempImg, RECT& rc, double lowestMatchValue)
|
|
|
+ {
|
|
|
+ cv::Mat srcImg, tempImg, matchImg;
|
|
|
+ if (!OpenImage(strSrcImg, srcImg) || !OpenImage(strTempImg, tempImg))
|
|
|
+ {
|
|
|
+ if (srcImg.data) srcImg.release();
|
|
|
+ if (tempImg.data) tempImg.release();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ cv::matchTemplate(srcImg, tempImg, matchImg, cv::TM_CCOEFF_NORMED);
|
|
|
+ // 归一化到0~1
|
|
|
+ //cv::normalize(matchImg, matchImg, 0, 1, cv::NORM_MINMAX, -1);
|
|
|
+
|
|
|
+ double lv_nMinVal = 0.0;
|
|
|
+ double lv_nMaxVal = 0.0;
|
|
|
+ cv::Point lv_nMinLoc = cv::Point(0, 0);
|
|
|
+ cv::Point lv_nMaxLoc = cv::Point(0, 0);
|
|
|
+ cv::Point lv_MatchLoc = cv::Point(0, 0);
|
|
|
+ cv::minMaxLoc(matchImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
|
|
|
+
|
|
|
+ cv::Rect roi = cv::Rect(lv_nMaxLoc.x, lv_nMaxLoc.y, tempImg.cols, tempImg.rows);
|
|
|
+ cv::Mat roiImg = srcImg(roi);
|
|
|
+ //cv::imwrite("G:\\bin\\GameAssist\\match.bmp", roiImg);
|
|
|
+
|
|
|
+ rc.left = lv_nMaxLoc.x - GameGlobal::frameWidth;
|
|
|
+ rc.top = lv_nMaxLoc.y - GameGlobal::titleBarHeight;
|
|
|
+ rc.right = rc.left + tempImg.cols;
|
|
|
+ rc.bottom = rc.top + tempImg.rows;
|
|
|
+
|
|
|
+ srcImg.release();
|
|
|
+ tempImg.release();
|
|
|
+ matchImg.release();
|
|
|
+ roiImg.release();
|
|
|
+
|
|
|
+ // 是否大于最低匹配度;
|
|
|
+ return (lv_nMaxVal >= lowestMatchValue ? TRUE : FALSE);
|
|
|
+ }
|
|
|
+
|
|
|
+ BOOL IsMatchIcon(HWND hWnd, std::string strTempImg, RECT srcRect, RECT& matchRect, double lowestMatchValue)
|
|
|
+ {
|
|
|
+ std::string strImg = CaptureGameWnd(hWnd);
|
|
|
+ cv::Mat srcImg, tempImg, matchImg;
|
|
|
+ if (!OpenImage(strImg, srcImg) || !OpenImage(strTempImg, tempImg))
|
|
|
+ {
|
|
|
+ if (srcImg.data) srcImg.release();
|
|
|
+ if (tempImg.data) tempImg.release();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 指定源图片区域来做模块比较,提高效率;
|
|
|
+ cv::Mat imgROI;
|
|
|
+ imgROI = srcImg(cv::Rect(srcRect.left, srcRect.top, srcRect.right - srcRect.left, srcRect.bottom - srcRect.top));
|
|
|
+ cv::imwrite(GameGlobal::BuildImgPath(hWnd, _T("roi")), imgROI);
|
|
|
+ /*
|
|
|
+ m_ImgROI = srcImg([&]()-> cv::Rect {
|
|
|
+ // 注意是x,y,w=cols,h=rows
|
|
|
+ return cv::Rect(srcRect.left, srcRect.top, srcRect.right - srcRect.left, srcRect.bottom - srcRect.top);
|
|
|
+ }());
|
|
|
+ */
|
|
|
+
|
|
|
+ cv::matchTemplate(imgROI, tempImg, matchImg, cv::TM_CCOEFF_NORMED);
|
|
|
+ // 归一化到0~1
|
|
|
+ //cv::normalize(matchImg, matchImg, 0, 1, cv::NORM_MINMAX, -1);
|
|
|
+
|
|
|
+ double lv_nMinVal = 0.0;
|
|
|
+ double lv_nMaxVal = 0.0;
|
|
|
+ cv::Point lv_nMinLoc = cv::Point(0, 0);
|
|
|
+ cv::Point lv_nMaxLoc = cv::Point(0, 0);
|
|
|
+ cv::Point lv_MatchLoc = cv::Point(0, 0);
|
|
|
+ cv::minMaxLoc(matchImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
|
|
|
+
|
|
|
+ cv::Rect roi = cv::Rect(lv_nMaxLoc.x, lv_nMaxLoc.y, tempImg.cols, tempImg.rows);
|
|
|
+ cv::Mat roiImg = imgROI(roi);
|
|
|
+ cv::imwrite(GameGlobal::BuildImgPath(hWnd, _T("match")), roiImg);
|
|
|
+
|
|
|
+ matchRect.left = srcRect.left + lv_nMaxLoc.x - GameGlobal::frameWidth;
|
|
|
+ matchRect.top = srcRect.top + lv_nMaxLoc.y - GameGlobal::titleBarHeight;
|
|
|
+ matchRect.right = matchRect.left + tempImg.cols;
|
|
|
+ matchRect.bottom = matchRect.top + tempImg.rows;
|
|
|
+
|
|
|
+ imgROI.release();
|
|
|
+ srcImg.release();
|
|
|
+ tempImg.release();
|
|
|
+ matchImg.release();
|
|
|
+ roiImg.release();
|
|
|
+
|
|
|
+ // 是否大于最低匹配度;
|
|
|
+ return (lv_nMaxVal >= lowestMatchValue ? TRUE : FALSE);
|
|
|
+ }
|
|
|
+
|
|
|
+ BOOL CropPicture(HWND hWnd, CRect rc, const char* szSaveName)
|
|
|
+ {
|
|
|
+ std::string strImg = CaptureGameWnd(hWnd);
|
|
|
+ cv::Mat srcImg, tempImg, matchImg;
|
|
|
+ if (!OpenImage(strImg, srcImg))
|
|
|
+ {
|
|
|
+ if (srcImg.data) srcImg.release();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 指定源图片区域来做模块比较,提高效率;
|
|
|
+ cv::Mat imgROI;
|
|
|
+ imgROI = srcImg(cv::Rect(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top));
|
|
|
+ return cv::imwrite(szSaveName, imgROI);
|
|
|
+ }
|
|
|
+
|
|
|
+ BOOL IsSimilarPicture(const char* szp1, const char* szp2, double lowestMatchValue)
|
|
|
+ {
|
|
|
+ cv::Mat src, dest, matchImg;
|
|
|
+ src = cv::imread(szp1);
|
|
|
+ dest = cv::imread(szp2);
|
|
|
+
|
|
|
+ cv::matchTemplate(src, dest, matchImg, cv::TM_CCOEFF_NORMED);
|
|
|
+ // 归一化到0~1
|
|
|
+ //cv::normalize(matchImg, matchImg, 0, 1, cv::NORM_MINMAX, -1);
|
|
|
+
|
|
|
+ double lv_nMinVal = 0.0;
|
|
|
+ double lv_nMaxVal = 0.0;
|
|
|
+ cv::Point lv_nMinLoc = cv::Point(0, 0);
|
|
|
+ cv::Point lv_nMaxLoc = cv::Point(0, 0);
|
|
|
+ cv::Point lv_MatchLoc = cv::Point(0, 0);
|
|
|
+ cv::minMaxLoc(matchImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
|
|
|
+
|
|
|
+ src.release();
|
|
|
+ matchImg.release();
|
|
|
+ dest.release();
|
|
|
+
|
|
|
+ // 是否大于最低匹配度;
|
|
|
+ return (lv_nMaxVal >= lowestMatchValue ? TRUE : FALSE);
|
|
|
+ }
|
|
|
+
|
|
|
+ int GetColorOccupiedLength(std::string strImg, int r, int g, int b)
|
|
|
+ {
|
|
|
+ cv::Mat src = cv::imread(strImg.c_str());
|
|
|
+ // 获取图片的矩形大小;
|
|
|
+ int width = src.cols;
|
|
|
+ int height = src.rows;
|
|
|
+
|
|
|
+ int i = 0;
|
|
|
+ for (; i < width; ++i)
|
|
|
+ {
|
|
|
+ cv::Vec3b pixel = src.at<cv::Vec3b>(height / 2, i); // 读取第 height / 2行 第 i 列像素值;
|
|
|
+ if (abs(pixel[0] - b) <= 3 && abs(pixel[1] - g) <= 3 && abs(pixel[2] - r) <= 3)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ src.release();
|
|
|
+
|
|
|
+ GameGlobal::DebugLog(_T("[GameAssist] 颜色占比=%d,%d,%d"), i, width, i * 100 / width);
|
|
|
+
|
|
|
+ return i * 100 / width;
|
|
|
+ }
|
|
|
+
|
|
|
+};
|