├── 001.py ├── README.md ├── char.jpg ├── headers.txt ├── imgdata.txt ├── metin.jpg └── windowcapture.py /001.py: -------------------------------------------------------------------------------- 1 | from math import pi 2 | from operator import truediv 3 | from string import printable 4 | import cv2 as cv 5 | import numpy as np 6 | import os 7 | import os.path 8 | import win32api, win32con 9 | from numpy.lib.shape_base import tile 10 | from PIL import ImageGrab 11 | from windowcapture import WindowCapture 12 | import keyboard 13 | import time 14 | from math import sqrt 15 | import random 16 | import win32gui, win32ui, win32con 17 | 18 | 19 | 20 | 21 | 22 | os.chdir(os.path.dirname(os.path.abspath(__file__))) 23 | 24 | # List all windows headers for headers.txt 25 | def ListWindowNames(): 26 | def winEnumHandler(hwnd, ctx): 27 | if win32gui.IsWindowVisible(hwnd): 28 | print(win32gui.GetWindowText(hwnd)) 29 | win32gui.EnumWindows(winEnumHandler, None) 30 | 31 | 32 | 33 | def findClickPositions(needle_img_path, haystack_img, threshold, debug_mode=None): 34 | 35 | # https://docs.opencv.org/4.2.0/d4/da8/group__imgcodecs.html 36 | 37 | needle_img = cv.imread(needle_img_path, cv.IMREAD_UNCHANGED) 38 | locations = [] 39 | # Save the dimensions of the needle image 40 | 41 | needle_w = needle_img.shape[1] 42 | needle_h = needle_img.shape[0] 43 | 44 | 45 | 46 | 47 | # There are 6 methods to choose from: 48 | # TM_CCOEFF, TM_CCOEFF_NORMED, TM_CCORR, TM_CCORR_NORMED, TM_SQDIFF, TM_SQDIFF_NORMED 49 | method = cv.TM_CCOEFF_NORMED 50 | result = cv.matchTemplate(haystack_img, needle_img, method) 51 | 52 | # Get the all the positions from the match result that exceed our threshold 53 | locations = np.where(result >= threshold) 54 | locations = list(zip(*locations[::-1])) 55 | # print(locations) 56 | 57 | # You'll notice a lot of overlapping rectangles get drawn. We can eliminate those redundant 58 | # locations by using groupRectangles(). 59 | # First we need to create the list of [x, y, w, h] rectangles 60 | rectangles = [] 61 | for loc in locations: 62 | rect = [int(loc[0]), int(loc[1]), needle_w, needle_h] 63 | # Add every box to the list twice in order to retain single (non-overlapping) boxes 64 | rectangles.append(rect) 65 | rectangles.append(rect) 66 | # Apply group rectangles. 67 | # The groupThreshold parameter should usually be 1. If you put it at 0 then no grouping is 68 | # done. If you put it at 2 then an object needs at least 3 overlapping rectangles to appear 69 | # in the result. I've set eps to 0.5, which is: 70 | # "Relative difference between sides of the rectangles to merge them into a group." 71 | rectangles, weights = cv.groupRectangles(rectangles, groupThreshold=1, eps=0.5) 72 | #print(rectangles) 73 | 74 | points = [] 75 | if len(rectangles): 76 | #print('Found needle.') 77 | 78 | line_color = (0, 255, 0) 79 | line_type = cv.LINE_4 80 | marker_color = (255, 0, 255) 81 | marker_type = cv.MARKER_CROSS 82 | 83 | # Loop over all the rectangles 84 | for (x, y, w, h) in rectangles: 85 | 86 | # Determine the center position 87 | center_x = x + int(w/2) 88 | center_y = y + int(h/2) 89 | # Save the points 90 | points.append((center_x, center_y)) 91 | 92 | if debug_mode == 'rectangles': 93 | # Determine the box position 94 | top_left = (x, y) 95 | bottom_right = (x + w, y + h) 96 | # Draw the box 97 | cv.rectangle(haystack_img, top_left, bottom_right, color=line_color, 98 | lineType=line_type, thickness=2) 99 | elif debug_mode == 'points': 100 | # Draw the center point 101 | cv.drawMarker(haystack_img, (center_x, center_y), 102 | color=marker_color, markerType=marker_type, 103 | markerSize=20, thickness=2) 104 | 105 | #if debug_mode: 106 | # cv.imshow('Matches', haystack_img) 107 | # cv.waitKey() 108 | # cv.imwrite('result_click_point.jpg', haystack_img) 109 | 110 | return points 111 | 112 | 113 | def tryAllHeaders(): 114 | file = open("headers.txt","r") 115 | headers = [] 116 | for header in file: 117 | clearheader = header.replace('\n','') 118 | headers.append(clearheader) 119 | # print(headers) 120 | for header in headers: 121 | try: 122 | wincap = WindowCapture(header) 123 | return header 124 | break 125 | except: 126 | continue 127 | 128 | def findmob(wincap,header,mobTreshold): 129 | file = open("imgdata.txt","r") 130 | mobs = [] 131 | for mob in file: 132 | clearmob = mob.replace('\n','') 133 | mobs.append(clearmob) 134 | for mob in mobs: 135 | screen = wincap.get_screenshot() 136 | points = findClickPositions(mob, screen,mobTreshold, debug_mode='points' ) 137 | if (len(points)>0): 138 | 139 | return mob 140 | break 141 | 142 | 143 | 144 | char = "char.jpg" 145 | i = 0 146 | missingWindowHeight = 110 147 | mobTreshold = 0.6 148 | playerTreshold = 0.6 149 | 150 | # Try All headers 151 | header = tryAllHeaders() 152 | wincap = WindowCapture(header) 153 | # Find Correct mob 154 | correctmob = findmob(wincap, header, mobTreshold) 155 | loop_time = time.time() 156 | while keyboard.is_pressed('end') == False: 157 | try: 158 | 159 | 160 | screen = wincap.get_screenshot() 161 | 162 | mobPoints = findClickPositions(correctmob, screen, mobTreshold, debug_mode='rectangles') 163 | print(mobPoints) 164 | playerLocation = findClickPositions(char, screen, playerTreshold, debug_mode='points') 165 | 166 | 167 | cv.imshow("Points", screen) 168 | cv.waitKey(5) 169 | i += 1 170 | 171 | except: 172 | print("Cant find mob or character") 173 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # opencv-bot-main 2 | Knight Online OpenCv2 Anti-AFK Object Detection 3 | https://www.youtube.com/watch?v=0IGN_3g3UDw 4 | 5 | 6 | ![image](https://user-images.githubusercontent.com/36090819/205471288-ef6374ac-c0f1-4991-a9e2-3599f2a142eb.png) 7 | 8 | 9 | 10 | _____________________________________________________________ 11 | 12 | 13 | ![image](https://user-images.githubusercontent.com/36090819/205486747-c76ab2d9-b8e0-45af-948a-0414ccee241b.png) 14 | 15 | headers.txt ---> Oyunun Pencere ismini yazınız 16 | 17 | _____________________________________________________________ 18 | 19 | 20 | ![image](https://user-images.githubusercontent.com/36090819/205486837-d61f318d-12af-44b2-83f6-c0874deeff50.png) 21 | 22 | metin.jpg --> Tespit etmesi gereken nesnenin fotoğrafını koyun. Yazı olur eşya olur fark etmez. Aktif pencerede bunu arayacaktır. 23 | 24 | _____________________________________________________________ 25 | 26 | 27 | ![image](https://user-images.githubusercontent.com/36090819/205486888-78106a19-14a2-4042-8da1-79d018956c64.png) 28 | 29 | char.jpg --> Charın nick'in olduğu kısımdır. Eğer Tespit döngüsü yazarsanız charın kordinatına en yakın mobu seçtirmek için kullanılabilir. 30 | 31 | _____________________________________________________________ 32 | 33 | 34 | 001.py'yi çalıştırın. Kütüphaneleri kurmayı unutmayın. 35 | 36 | 37 | 38 | 39 | _____________________________________________________________ 40 | 41 | 42 | https://youtu.be/p_F_u3HpFXM 43 | 44 | 45 | 46 | ## 💰 You can help me by Donating 47 | 48 | [![BuyMeACoffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-ffdd00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black)](https://buymeacoffee.com/handeveloper1) 49 | 50 | ## 📺 Check out my YouTube Channel 51 | 52 | [![YouTube](https://img.shields.io/badge/YouTube-%23FF0000.svg?style=for-the-badge&logo=youtube&logoColor=white)](https://www.youtube.com/@handeveloper1) 53 | -------------------------------------------------------------------------------- /char.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/handeveloper1/KecoonBot-opencv-bot-main---with-Python/311c8c14c691ac9401f0f5c638d4cc7726a4aa14/char.jpg -------------------------------------------------------------------------------- /headers.txt: -------------------------------------------------------------------------------- 1 | ISTIRAP Client[27516] -------------------------------------------------------------------------------- /imgdata.txt: -------------------------------------------------------------------------------- 1 | metin.jpg -------------------------------------------------------------------------------- /metin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/handeveloper1/KecoonBot-opencv-bot-main---with-Python/311c8c14c691ac9401f0f5c638d4cc7726a4aa14/metin.jpg -------------------------------------------------------------------------------- /windowcapture.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import win32gui, win32ui, win32con 3 | 4 | 5 | 6 | class WindowCapture: 7 | 8 | # properties 9 | w = 0 10 | h = 0 11 | hwnd = None 12 | cropped_x = 0 13 | cropped_y = 0 14 | offset_x = 0 15 | offset_y = 0 16 | 17 | # constructor 18 | def __init__(self, window_name): 19 | # find the handle for the window we want to capture 20 | self.hwnd = win32gui.FindWindow(None, window_name) 21 | if not self.hwnd: 22 | raise Exception('Window not found: {}'.format(window_name)) 23 | 24 | # get the window size 25 | window_rect = win32gui.GetWindowRect(self.hwnd) 26 | self.w = window_rect[2] - window_rect[0]-150 27 | self.h = window_rect[3] - window_rect[1]-55 28 | 29 | # account for the window border and titlebar and cut them off 30 | border_pixels = 1 31 | titlebar_pixels = 100 32 | self.w = self.w - (border_pixels * 2) 33 | self.h = self.h - titlebar_pixels - border_pixels 34 | self.cropped_x = border_pixels 35 | self.cropped_y = titlebar_pixels 36 | 37 | # set the cropped coordinates offset so we can translate screenshot 38 | # images into actual screen positions 39 | self.offset_x = window_rect[0] + self.cropped_x 40 | self.offset_y = window_rect[1] + self.cropped_y 41 | 42 | def get_screenshot(self): 43 | 44 | # get the window image data 45 | wDC = win32gui.GetWindowDC(self.hwnd) 46 | dcObj = win32ui.CreateDCFromHandle(wDC) 47 | cDC = dcObj.CreateCompatibleDC() 48 | dataBitMap = win32ui.CreateBitmap() 49 | dataBitMap.CreateCompatibleBitmap(dcObj, self.w, self.h) 50 | cDC.SelectObject(dataBitMap) 51 | cDC.BitBlt((0, 0), (self.w, self.h), dcObj, (self.cropped_x, self.cropped_y), win32con.SRCCOPY) 52 | 53 | # convert the raw data into a format opencv can read 54 | #dataBitMap.SaveBitmapFile(cDC, 'debug.bmp') 55 | signedIntsArray = dataBitMap.GetBitmapBits(True) 56 | img = np.fromstring(signedIntsArray, dtype='uint8') 57 | img.shape = (self.h, self.w, 4) 58 | 59 | # free resources 60 | dcObj.DeleteDC() 61 | cDC.DeleteDC() 62 | win32gui.ReleaseDC(self.hwnd, wDC) 63 | win32gui.DeleteObject(dataBitMap.GetHandle()) 64 | 65 | # drop the alpha channel, or cv.matchTemplate() will throw an error like: 66 | # error: (-215:Assertion failed) (depth == CV_8U || depth == CV_32F) && type == _templ.type() 67 | # && _img.dims() <= 2 in function 'cv::matchTemplate' 68 | img = img[...,:3] 69 | 70 | # make image C_CONTIGUOUS to avoid errors that look like: 71 | # File ... in draw_rectangles 72 | # TypeError: an integer is required (got type tuple) 73 | # see the discussion here: 74 | # https://github.com/opencv/opencv/issues/14866#issuecomment-580207109 75 | img = np.ascontiguousarray(img) 76 | 77 | return img 78 | 79 | # find the name of the window you're interested in. 80 | # once you have it, update window_capture() 81 | # https://stackoverflow.com/questions/55547940/how-to-get-a-list-of-the-name-of-every-open-window 82 | def list_window_names(self): 83 | def winEnumHandler(hwnd, ctx): 84 | if win32gui.IsWindowVisible(hwnd): 85 | print(hex(hwnd), win32gui.GetWindowText(hwnd)) 86 | win32gui.EnumWindows(winEnumHandler, None) 87 | 88 | # translate a pixel position on a screenshot image to a pixel position on the screen. 89 | # pos = (x, y) 90 | # WARNING: if you move the window being captured after execution is started, this will 91 | # return incorrect coordinates, because the window position is only calculated in 92 | # the __init__ constructor. 93 | def get_screen_position(self, pos): 94 | return (pos[0] + self.offset_x, pos[1] + self.offset_y) 95 | --------------------------------------------------------------------------------