不好用,識別速度慢,有時候識別不準確
#include <windows.h>
#include <stdio.h>
#include <math.h>
HDC hdcScreen;
void leftClick();
void RGBtoHSV(int r, int g, int b, int* h, int* s, int* v);
int fuzzyFindColor(int x1, int y1, int x2, int y2,int targetH, int targetS, int targetV,int hTol, int sTol, int vTol,int* outX, int* outY);
void leftClick() {// 模擬鼠標左鍵按下mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);// 短暫延遲,模擬真實點擊的持續時間Sleep(50);// 模擬鼠標左鍵釋放mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
}
// 1. RGB轉HSV(純C工具函數,0<=H<=360,0<=S,V<=100)
void RGBtoHSV(int r, int g, int b, int* h, int* s, int* v) {/*作用:將輸入的 0-255 整數(硬件設備的絕對亮度值)轉換為 0-1 的相對比例(消除絕對值影響,統一計算標準)。細節:除以 255.0f(浮點型)而非 255(整數),確保結果為浮點數(避免整數除法導致的截斷)。*/float R = r / 255.0f, G = g / 255.0f, B = b / 255.0f;float max = (R > G ? (R > B ? R : B) : (G > B ? G : B));float min = (R < G ? (R < B ? R : B) : (G < B ? G : B));float delta = max - min;// 計算色相Hif (delta < 1e-6) *h = 0;else if (max == R) *h = (int)(60 * fmod(((G - B) / delta) + 6, 6));else if (max == G) *h = (int)(60 * (((B - R) / delta) + 2));else *h = (int)(60 * (((R - G) / delta) + 4));// 計算飽和度S*s = (max < 1e-6) ? 0 : (int)((delta / max) * 100);// 計算明度V*v = (int)(max * 100);
}// 2. 區域模糊找色(返回第一個匹配點坐標)
// 參數:x1,y1/x2,y2=查找區域;targetH/S/V=目標顏色;h/s/vTol=模糊閾值;outX/outY=輸出坐標
int fuzzyFindColor(int x1, int y1, int x2, int y2,int targetH, int targetS, int targetV,int hTol, int sTol, int vTol,int* outX, int* outY) {// 校驗區域合法性if (x1 > x2 || y1 > y2) return 0;// 獲取屏幕設備上下文(DC)//hdcScreen = CreateDCA("DISPLAY", NULL, NULL, NULL);hdcScreen=GetDC(NULL);//2if (!hdcScreen) return 0;int h, s, v;COLORREF pixel; // 存儲RGB顏色(0x00BBGGRR)int r, g, b;// 遍歷區域內所有像素for (int y = y1; y <= y2; y++) {for (int x = x1; x <= x2; x++) {// 讀取當前像素的RGB值pixel = GetPixel(hdcScreen, x, y);r = GetRValue(pixel); // 提取紅色分量g = GetGValue(pixel); // 提取綠色分量b = GetBValue(pixel); // 提取藍色分量// RGB轉HSVRGBtoHSV(r, g, b, &h, &s, &v);// printf("RGB %d, %d,%d)\n", r, g, b);// printf("hsv %d, %d,%d)\n", h, s, v);// 模糊匹配:判斷HSV是否在閾值范圍內if ((h >= targetH - hTol && h <= targetH + hTol) &&(s >= targetS - sTol && s <= targetS + sTol) &&(v >= targetV - vTol && v <= targetV + vTol)) {*outX = x;*outY = y;//DeleteDC(hdcScreen); // 釋放資源ReleaseDC(NULL, hdcScreen);//2leftClick();return 1; // 找到匹配點}}}//DeleteDC(hdcScreen); // 釋放資源ReleaseDC(NULL, hdcScreen);//2return 0; // 未找到
}// 3. 測試主函數
int main() {while (1){int matchX, matchY;// 需求:在(100,100)-(800,600)區域找HSV(30,80,90),閾值H±3、S±8、V±15int found = fuzzyFindColor(537 , 533, 543, 538,180, 50, 8,179, 49, 7,&matchX, &matchY);if (found) {printf("--------------------------------------------------------------找到匹配點!坐標:(%d, %d)\n", matchX, matchY);Sleep(1000);}else {printf("未找到匹配顏色未找到匹配顏色未找到匹配顏色\n");}//system("pause"); // 暫停查看結果}return 0;
}