From 02e452c4971bb90925cae8ffa247a2d869e974c5 Mon Sep 17 00:00:00 2001 From: space2lim Date: Thu, 10 Oct 2024 01:19:11 +0900 Subject: [PATCH] init --- .python-version | 1 + main.py | 240 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 241 insertions(+) create mode 100644 .python-version create mode 100644 main.py diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..171a6a9 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.12.1 diff --git a/main.py b/main.py new file mode 100644 index 0000000..cf1c269 --- /dev/null +++ b/main.py @@ -0,0 +1,240 @@ +import pygetwindow as gw # Get size & coords of specific window with It's handle(hwnd), not title +from pywinauto import Desktop # Get size & coords of specific window with It's title *USE THIS!!!* +from mss import mss # Capture windows with given coords +import cv2 # You know what It is +import numpy as np # sure +import time +from skimage.metrics import structural_similarity as ssim + +def resize_with_ratio(image, scale=1.5, inter=cv2.INTER_LINEAR): + # 이미지 크기 가져오기 + (h, w) = image.shape[:2] + + # 너비와 높이를 1.5배로 확대 + new_size = (int(w * scale), int(h * scale)) + + # 리사이즈 적용 + resized = cv2.resize(image, new_size, interpolation=inter) + + return resized + +def pad_to_match_size(card1, card2): + # 카드 1과 카드 2의 크기 확인 + h1, w1 = card1.shape[:2] + h2, w2 = card2.shape[:2] + + # 두 카드의 최대 너비와 높이 계산 + max_h = max(h1, h2) + max_w = max(w1, w2) + + # 카드 1에 패딩 추가 (상하좌우에 패딩을 균일하게 추가) + pad_top_1 = (max_h - h1) // 2 + pad_bottom_1 = max_h - h1 - pad_top_1 + pad_left_1 = (max_w - w1) // 2 + pad_right_1 = max_w - w1 - pad_left_1 + padded_card1 = cv2.copyMakeBorder(card1, pad_top_1, pad_bottom_1, pad_left_1, pad_right_1, cv2.BORDER_CONSTANT, value=[0, 0, 0]) + + # 카드 2에 패딩 추가 + pad_top_2 = (max_h - h2) // 2 + pad_bottom_2 = max_h - h2 - pad_top_2 + pad_left_2 = (max_w - w2) // 2 + pad_right_2 = max_w - w2 - pad_left_2 + padded_card2 = cv2.copyMakeBorder(card2, pad_top_2, pad_bottom_2, pad_left_2, pad_right_2, cv2.BORDER_CONSTANT, value=[0, 0, 0]) + + return padded_card1, padded_card2 + +# def compare_cards(card1, card2): #============================================= L2 norm +# resized_card1, resized_card2 = pad_to_match_size(card1, card2) +# return cv2.norm(resized_card1, resized_card2, cv2.NORM_L2) + +# def compare_cards(card1, card2): #============================================= ORB + # orb = cv2.ORB_create() + + # # 카드에서 특징점 검출 + # kp1, des1 = orb.detectAndCompute(card1, None) + # kp2, des2 = orb.detectAndCompute(card2, None) + + # # BFMatcher로 특징점 매칭 + # bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) + # matches = bf.match(des1, des2) + + # # 매칭 결과를 거리 기준으로 정렬 + # matches = sorted(matches, key=lambda x: x.distance) + + # # 거리 합산으로 차이 계산 (거리가 클수록 더 많은 차이) + # return sum([match.distance for match in matches]) + +# def compare_cards(card1, card2): #============================================= 정적배경차분 +# resized_card1, resized_card2 = pad_to_match_size(card1, card2) + +# # 이미지 차이 계산 +# diff = cv2.absdiff(resized_card1, resized_card2) + +# # 차이가 나는 픽셀의 합계를 계산 +# difference_score = np.sum(diff) + +# return difference_score + +# def compare_cards(card1, card2): #============================================= Canny edge detection +# resized_card1, resized_card2 = pad_to_match_size(card1, card2) + +# # Canny Edge Detection 적용 +# edges1 = cv2.Canny(resized_card1, 30, 150) +# edges2 = cv2.Canny(resized_card2, 30, 150) + +# # 이미지 차이 계산 (엣지 차이) +# diff = cv2.absdiff(edges1, edges2) + +# # 차이가 나는 픽셀의 합계를 계산 +# difference_score = np.sum(diff) + +# return difference_score + +# def compare_cards(card1, card2): #============================================= 히스토그램 비교 +# resized_card1, resized_card2 = pad_to_match_size(card1, card2) + +# # 히스토그램 계산 +# hist1 = cv2.calcHist([resized_card1], [0], None, [256], [0, 256]) +# hist2 = cv2.calcHist([resized_card2], [0], None, [256], [0, 256]) + +# # 히스토그램을 정규화 +# hist1 = cv2.normalize(hist1, hist1) +# hist2 = cv2.normalize(hist2, hist2) + +# # 히스토그램 차이 계산 (Chi-Square 비교) +# score = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CHISQR) + +# return score + +# def compare_cards(card1, card2): #============================================= 템플릿 매칭 +# resized_card1, resized_card2 = pad_to_match_size(card1, card2) + +# # 템플릿 매칭 +# result = cv2.matchTemplate(resized_card1, resized_card2, cv2.TM_CCOEFF_NORMED) + +# # 매칭 값 (1에 가까울수록 유사, 0에 가까울수록 차이) +# min_val, max_val, _, _ = cv2.minMaxLoc(result) + +# return max_val + + +# def compare_cards(card1, card2): #============================================= 로그적용 정적배경차분 +# resized_card1, resized_card2 = pad_to_match_size(card1, card2) + +# # LoG 필터 적용 +# log_card1 = cv2.Laplacian(cv2.GaussianBlur(resized_card1, (3, 3), 0), cv2.CV_64F) +# log_card2 = cv2.Laplacian(cv2.GaussianBlur(resized_card2, (3, 3), 0), cv2.CV_64F) +# # log_card1 = cv2.Laplacian(resized_card1, cv2.CV_64F) +# # log_card2 = cv2.Laplacian(resized_card2, cv2.CV_64F) + +# # 이미지 차이 계산 +# diff = cv2.absdiff(log_card1, log_card2) + +# # 차이 합계 계산 +# difference_score = np.sum(diff) + +# return difference_score + + +def compare_cards(card1, card2): #============================================= SSIM + resized_card1, resized_card2 = pad_to_match_size(card1, card2) + + # SSIM 비교 (grayscale로 변환한 후) + ssim_score, _ = ssim(resized_card1, resized_card2, full=True) + + return ssim_score + + +target_window = "S22 Ultra" +windows = Desktop(backend="uia").windows() + +selected_window = None +for w in windows: + if target_window.lower() in w.window_text().lower(): # 대소문자 구분 없이 비교 + selected_window = w + break + +if selected_window != None: + rect = selected_window.rectangle() + monitor_coords = {"top": rect.top, "left": rect.left, "width": rect.width(), "height": rect.height()} + + with mss() as sct: + while True: + rect = selected_window.rectangle() + monitor_coords = {"top": rect.top, "left": rect.left, "width": rect.width(), "height": rect.height()} + + + sct_img = sct.grab(monitor_coords) + img = np.array(sct_img) + + # Now we're gonna do some CV things + + # Preprocessing + gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + blur = cv2.GaussianBlur(gray, (5, 5), 0) + _, thresh = cv2.threshold(blur, 245, 255, cv2.THRESH_BINARY_INV) + + kernel = np.ones((3, 3), np.uint8) + thresh = cv2.erode(thresh, kernel, iterations=1) + _, thresh = cv2.threshold(thresh, 100, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) + + # Find contour + contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + cv2.imshow("Preprocessed", thresh) + + + cards = [] + for i, cnt in enumerate(contours): + x, y, w, h = cv2.boundingRect(cnt) + if 60 < w < 200 and 100 < h < 300: # 카드 크기 + aspect_ratio = float(w) / h + if 0.5 < aspect_ratio < 1.0: # 카드 비율 + card_gray = gray[y:y+h, x:x+w] + card_resized = resize_with_ratio(card_gray, 2) + _, card_thresh = cv2.threshold(card_resized, 130, 255, cv2.THRESH_BINARY_INV) + card_kernel = np.ones((1, 1), np.uint8) # 커널 크기로 글자 두께 조절 + card_eroded = cv2.erode(card_thresh, card_kernel, iterations=1) + cv2.imshow("card", card_eroded) + cards.append((card_eroded, cnt)) # 카드 이미지와 윤곽선 정보 함께 저장 + cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) + + # 차이 계산 + differences = [] + if len(cards) > 1: + for i in range(len(cards)): + min_diff = float('inf') # 비교 시 최소값을 찾기 위한 초기값 설정 + card_image_1, _ = cards[i] # 기준 카드 이미지 + + for j in range(len(cards)): + if i != j: # 자기 자신과는 비교하지 않음 + card_image_2, _ = cards[j] # 비교할 다른 카드 이미지 + diff = compare_cards(card_image_1, card_image_2) # 두 카드 이미지 비교 + if diff < min_diff: + min_diff = diff # 최소 차이값 업데이트 + + differences.append((i, min_diff)) + + # 차이비교 + if differences: + max_different_card = max(differences, key=lambda x: x[1]) # 차이가 가장 큰 카드 (간혹 방식에 따라 반대일 수 있음) + min_different_card = min(differences, key=lambda x: x[1]) # 차이가 가장 작은 카드 + + # 가장 큰 차이가 있는 카드의 윤곽선 + _, cnt_max = cards[max_different_card[0]] + x_max, y_max, w_max, h_max = cv2.boundingRect(cnt_max) + cv2.rectangle(img, (x_max, y_max), (x_max + w_max, y_max + h_max), (0, 0, 255), 2) # 빨간색 + cv2.putText(img, f'Conf: {max_different_card}%', (x_max, y_max - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (255, 0, 0), 2) + + # 가장 작은 차이가 있는 카드의 윤곽선 + _, cnt_min = cards[min_different_card[0]] + x_min, y_min, w_min, h_min = cv2.boundingRect(cnt_min) + cv2.rectangle(img, (x_min, y_min), (x_min + w_min, y_min + h_min), (255, 0, 0), 2) # 파란색 + cv2.putText(img, f'Conf: {min_different_card}%', (x_min, y_min - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (255, 0, 0), 2) + + print("\rtotal cards: {}".format(len(cards)), end="") + cv2.imshow("Capturing target", img) + + if cv2.waitKey(1) & 0xFF == ord('q'): + break + + cv2.destroyAllWindows() \ No newline at end of file