Example #1
0
 def cal_shadow_mask(self):
     '''
         获取阴影部分的罩层
     '''
     # 根据颜色的统计分布 阴影部分的颜色取值
     # 实际是背景颜色的平移, 所以我们在背景色的阈值上, 左移
     self.shd_lcolor = vutils.justify_rgb_value(self.bg_lcolor - 60)
     self.shd_ucolor = vutils.justify_rgb_value(self.bg_ucolor - 50)
     # 获取阴影的罩层
     self.shd_mask = cv2.inRange(self.img, self.shd_lcolor, self.shd_ucolor)
     # 对获取的阴影罩层进行数学形态运算, 去除噪声
     # 使用 9*9的核进行闭运算
     kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 9))
     # open close
     self.shd_mask = cv2.morphologyEx(self.shd_mask, cv2.MORPH_OPEN, kernel)
Example #2
0
def getChessFootByColor(img):
    '''
        利用颜色检索棋子位置
    '''
    MIN_CHESS_WIDTH = 65
    MAX_CHESS_WIDTH = 80

    MIN_CHESS_HEIGHT = 200
    MAX_CHESS_HEIGHT = 230

    chess_mask = getChessFootMask(img)
    image, contours, hier = cv2.findContours(chess_mask, cv2.RETR_TREE,
                                             cv2.CHAIN_APPROX_SIMPLE)

    contours = vutils.contours_filter(contours,
                                      minHeight=MIN_CHESS_HEIGHT,
                                      maxHeight=MAX_CHESS_HEIGHT,
                                      minWidth=MIN_CHESS_WIDTH,
                                      maxWidth=MAX_CHESS_WIDTH)

    if len(contours) == 1:
        # 刚好匹配到目标棋子
        (x, y, w, h) = cv2.boundingRect(contours[0])
        # 返回棋子坐标
        return (int(x + w / 2), int(y + h))
    else:
        return None
Example #3
0
def getLittleWhitePointCenter(img, offset=(0,0), debug=False):
    '''
        找到下一跳的中心白点
    '''
    lowerb = (245, 245, 245)
    upperb = (245, 245, 245)
    
    
    mask = cv2.inRange(img, lowerb, upperb)
    image, contours, hierarchy = cv2.findContours(image=mask, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE)
    contours = vutils.contours_filter(contours, minWidth=35, maxWidth=45, minHeight=20, maxHeight=30)
    
    if len(contours) != 1:
        return None
    
    
    (x, y, w, h) = cv2.boundingRect(contours[0])
    cx = int(x+w/2+offset[0])
    cy = int(y+h/2+offset[1])

    if debug == False:
        return (cx, cy)
    else:
        canvas = img.copy()
        print("w: {}, h: {}".format(w, h))
        cv2.rectangle(canvas, (x,y), (x+w, y+h), (0,0,255), thickness=4)
        return (cx, cy), canvas
Example #4
0
def getLittleWhitePointCenter(img, offset=(0,0), debug=False):
    '''
        找到下一跳的中心白点
    '''
    lowerb = (245, 245, 245)
    upperb = (245, 245, 245)
    
    
    mask = cv2.inRange(img, lowerb, upperb)
    image, contours, hierarchy = cv2.findContours(image=mask, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE)
    contours = vutils.contours_filter(contours, minWidth=35, maxWidth=45, minHeight=20, maxHeight=30)
    
    if len(contours) != 1:
        if debug:
            # 没有发现小白块 或者发现了多个
            return (None, np.hstack((img, cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR))))
        return None
    
    # 确定白点的中心点
    (x, y, w, h) = cv2.boundingRect(contours[0])
    cx = int(x+w/2+offset[0])
    cy = int(y+h/2+offset[1])

    if debug == False:
        return (cx, cy)
    else:
        canvas = img.copy()
        cv2.rectangle(canvas, (x,y), (x+w, y+h), (0,0,255), thickness=4)
        return (cx, cy), canvas
Example #5
0
    def cal_background_mask(self):
        '''
            计算图像背景罩层
        '''

        # 采集图像顶部 高度为100像素点的区域,对背景颜色进行统计
        # 你也可以根据你的画面自行修改

        bg_sample = self.img[200:400, 0:200]

        # 分析背景样本图片, 得到背景颜色的阈值
        (self.bg_lcolor, self.bg_ucolor) = vutils.cal_rgb_margin(bg_sample)

        # 因为摄像头采集的时候, 光照分布, 导致图片不同区域的背景颜色差异.
        # 背景色以顶部为准, 并适当放大一下背景色的取值范围, 我们这里取20
        self.bg_lcolor = vutils.justify_rgb_value(self.bg_lcolor - 20)
        self.bg_ucolor = vutils.justify_rgb_value(self.bg_ucolor + 20)
        # 获取背景罩层
        self.bg_mask = cv2.inRange(self.img, self.bg_lcolor, self.bg_ucolor)
        # 对背景罩层进行处理 数学形态学运算, 去除噪声
        # 用7*7 的核对背景图片进行闭运算
        kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))
        self.bg_mask = cv2.morphologyEx(self.bg_mask, cv2.MORPH_CLOSE, kernel)
Example #6
0
def getChessFootPosi(img):
    MIN_CHESS_WIDTH = 65
    MAX_CHESS_WIDTH = 80

    MIN_CHESS_HEIGHT = 200
    MAX_CHESS_HEIGHT = 230

    chess_mask = getChessBinImg(img)
    image, contours, hier = cv2.findContours(chess_mask, cv2.RETR_TREE,
                                             cv2.CHAIN_APPROX_SIMPLE)
    contours = vutils.contours_filter(contours,
                                      minHeight=MIN_CHESS_HEIGHT,
                                      maxHeight=MAX_CHESS_HEIGHT,
                                      minWidth=MIN_CHESS_WIDTH,
                                      maxWidth=MAX_CHESS_WIDTH)
    rects = []
    for c in contours:
        (x, y, w, h) = cv2.boundingRect(c)

        rects.append((x, y, w, h))

    return rects, contours
Example #7
0
    def cal_top_box_center(self):
        '''
            获取最顶层盒子的中心
        '''

        canvas = np.copy(self.img)

        image, contours, hier = cv2.findContours(self.box_mask, cv2.RETR_TREE,
                                                 cv2.CHAIN_APPROX_SIMPLE)

        contours = vutils.contours_filter(contours, minHeight=50, minWidth=50)

        boxes = []

        for c in contours:
            x, y, w, h = cv2.boundingRect(c)
            boxes.append((x, y, w, h))

        top_box = boxes[0]
        top_contour = contours[0]

        for i in range(1, len(contours)):
            # 对比box的y坐标的值, 获取最小 也就是最靠上方的盒子
            box = boxes[i]
            if top_box[1] > box[1]:
                top_box = box
                top_contour = contours[i]

        # print("box : {}".format(top_box))

        (x, y, w, h) = top_box

        # 这里有个问题, 如果两个box离的很近
        # 当前的盒子跟下一跳的盒子的区域会联通, 所以需要裁减
        # 通过判断chess是否在box中, 来判断是否相邻的两个盒子被当成一个。
        if vutils.isPointInRectangle(top_box, self.chs_fposi):
            # 检测到盒子连体, 采用备用方案, 获取下一个盒子的中心。

            miny = 100000
            ptop = None
            for points in top_contour:
                (px, py) = points[0]
                if py < miny:
                    miny = py
                    ptop = (px, py)
            # 把最顶上的坐标中x点作为box中心点。
            cx = ptop[0]
            dh = int(abs(cx - self.chs_fposi[0]) / math.sqrt(3))
            cy = self.chs_fposi[1] - dh

            radius = abs(cy - ptop[1])

            (x, y, w, h) = (cx - radius, ptop[1], 2 * radius, 2 * radius)

            # 再次判断chess底部是否落在矩形区域内
            # 进行对应的放缩
            # 下面的这段代码纯属靠凡哥发挥 实验有效。
            if vutils.isPointInRectangle((x, y, w, h), self.chs_fposi):
                # 这里移动值, 我选的是chess矩形区域的宽度
                delta = self.chs_rect[2]
                if self.chs_fposi[0] < x:
                    x -= delta
                else:
                    x += delta
                w -= delta
                h -= delta
            self.nbox_rect = (x, y, w, h)

            # 重新调整中心
            self.nbox_center = (int(x + w / 2), int(y + h / 3))

        else:
            self.nbox_rect = (x, y, w, h)
            (x, y, w, h) = self.nbox_rect
            # 计算中心点, 立体盒子的高的1/3处大概就是中心点y坐标的位置
            # 中心点的x左边标定为宽度的1/2处.
            self.nbox_center = (int(x + w / 2), int(y + h / 3))
        (x22, y22, w22, h22) = self.nbox_rect
        x33, y33 = self.chs_fposi
        x44, y44 = self.nbox_center
        cv2.rectangle(canvas, (x22, y22), (x22 + w22, y22 + h22), (255, 0, 0),
                      5)
        cv2.circle(canvas, (x33, y33), 5, (0, 0, 255), -1)
        cv2.circle(canvas, (x44, y44), 5, (0, 0, 255), -1)
        cv2.imshow('canvas', canvas)
Example #8
0
while True:

    img = ADBHelper.getScreenShotByADB()
    # 获取棋子的位置
    chess_posi = getChessFootPosi(img)
    # 获取下一跳中心的位置
    center_posi,canvas = getNextJumpPlatCenter(img)

    if chess_posi is None or center_posi is None:
        break
    
    cv2.imshow('NextCenterFinder', canvas)
    
    # 计算距离
    distance = vutil.cal_distance(chess_posi, center_posi)
    # 折算延迟
    delay = distance2time(distance)

    rc = ADBHelper.pressOnScreen((500, 500), delay=delay)
    if rc:
        print("成功点击 并延时 3s")
        if debug == True:
            # 保存日志  注意需要创建文件路径
            img_name =  f"{datetime.datetime.now():%Y-%m-%d-%H-%M-%S-%f.png}"
            cv2.imwrite('./output/AutoJump/screenshot/'+img_name, img)
            cv2.imwrite('./output/AutoJump/log/'+img_name, canvas)


    key = cv2.waitKey(3000)
Example #9
0
# -*- coding: utf-8 -*-
from FGJumperMaster import FGJumperMaster
from ADBHelper import ADBHelper
from FGVisonUtil import FGVisionUtil as vutil
import cv2
import numpy as np
import time
import datetime

# 初次读入图片
img = ADBHelper.getScreenShotByADB()
vutil.printImgInfo(img)

adb = ADBHelper(1080, 1920)

cv2.namedWindow('image', flags=cv2.WINDOW_NORMAL | cv2.WINDOW_FREERATIO)

keyPressed = -1


def distance2time(distance):
    ratio = 1.53
    # 事件必须是整数类型
    return int(distance * ratio)


def saveSampleImg(jmaster, img, tag=True):
    img_name = f"{datetime.datetime.now():%Y-%m-%d-%H-%M-%S.png}"

    if tag:
        cv2.imwrite("./samples/right/" + img_name, img)
Example #10
0
def getNextJumpPlatCenter(img, debug=False):
    '''
        获取下一跳平台的中心
    '''
    # 声明画布
    canvas = img.copy()

    edge = getCannyEdge(img)
    # 获取边缘信息
    image, contours, hierarchy = cv2.findContours(image=edge, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE)
    contours = vutils.contours_filter(contours, minWidth=10, minHeight=10)
    
    # 找到最大
    next_box_cnt = min(contours, key=lambda cnt: tuple(cnt[cnt[:,:,1].argmin()][0])[1])
    
    # 顶点序号
    top_point_idx = next_box_cnt[:,:,1].argmin()
    # 顶点
    top_point = tuple(next_box_cnt[top_point_idx,0,:2])
    
    # 背景色取样
    img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    refer_back_color = img_hsv[top_point[1], top_point[0]]

    left_idx_itr = 1
    right_idx_itr = -1
    if next_box_cnt[top_point_idx+left_idx_itr,0, 0] > top_point[0]:
        left_idx_itr, right_idx_itr = right_idx_itr, left_idx_itr 

    right_pt_idx = top_point_idx+right_idx_itr
    left_pt_idx = top_point_idx+left_idx_itr

    right_point = None
    left_point = None

    # 寻找右边的边缘点
    while True:
        # 当前right point
        right_point = tuple(next_box_cnt[right_pt_idx,0,:2])
        next = tuple(next_box_cnt[right_pt_idx+right_idx_itr,0,:2])
        
        if not isNextPoint(right_point, next, x_direction=1):
            break
        elif isInShadow(refer_back_color, img_hsv[next[1]+5, next[0]]):
            # 判断边缘下方的五个像素是不是阴影
            break
        
        right_pt_idx += right_idx_itr
    
    # 寻找左边的边缘点
    while True:
        left_point = tuple(next_box_cnt[left_pt_idx,0,:2])
        next = tuple(next_box_cnt[left_pt_idx+left_idx_itr,0,:2])

        if not isNextPoint(left_point, next, x_direction=-1):
            break
        elif isInShadow(refer_back_color, img_hsv[next[1]+5, next[0]]):
            break

        left_pt_idx += left_idx_itr
    # 调整三个点的位置
    (top_point, left_point, right_point) = adjust_points(top_point, left_point, right_point)
    down_point = (left_point[0]+right_point[0]-top_point[0],left_point[1]+right_point[1]-top_point[1])

    # 生成下一跳平台的搜索区域
    # TODO 检索椭圆形 四边形
    contour = np.array([
        [list(top_point)],
        [list(right_point)],
        [list(down_point)],
        [list(left_point)]])

    (x, y, w, h) = cv2.boundingRect(contour)
    # 在矩形区域内检索小白点提示
    res_pt = getLittleWhitePointCenter(img[y:y+h, x:x+w], offset=(x,y))
    
    center_point = None
    if res_pt is not None:
        # print("find white point")
        # print(res_pt)
        center_point = res_pt
    else:
        # 取left_point与right_point 中间处作为中心点
        cx = int((left_point[0]+right_point[0])/2)
        cy = int((left_point[1]+right_point[1])/2)
        center_point = (cx, cy)

    if debug == True:
        cv2.drawContours(image=canvas, contours=[next_box_cnt], contourIdx=-1, color=(125,125,125), thickness=1)
        canvas[top_point[1],top_point[0]] = [0,0,255]

        canvas[left_point[1],left_point[0]] = [0, 255, 0]
        canvas[right_point[1], right_point[0]] = [255, 0, 0]

        next_right = tuple(next_box_cnt[right_pt_idx+right_idx_itr,0,:2])
        canvas[next_right[1], next_right[0]] = [0,0,0]
        next_left = tuple(next_box_cnt[left_pt_idx+left_idx_itr,0,:2])
        canvas[next_left[1], next_left[0]] = [0,0,0]

        print('LEFT: {}, TOP: {}, RIGHT: {}'.format(left_point, top_point, right_point))

    else:
        # 设定圆圈半径
        pt_radius = 10
        # 绘制轮廓
        cv2.drawContours(image=canvas, contours=[next_box_cnt], contourIdx=-1, color=(0,0,255), thickness=3)
        cv2.circle(canvas, top_point, pt_radius, (0, 255, 0), thickness=-1)
        cv2.circle(canvas, left_point, pt_radius, (0, 255, 255), thickness=-1)
        cv2.circle(canvas, right_point, pt_radius, (255, 0, 0), thickness=-1)
        cv2.circle(canvas, down_point, pt_radius, (255,255,0), thickness=-1)
        # 绘制检索框
        # x,y,w,h = next_plat_rect
        # cv2.rectangle(canvas, (x,y), (x+w, y+h), (255,255,255), thickness=2)
        cv2.circle(canvas, center_point, pt_radius, (45,100,255), thickness=-1)
    
    return center_point,canvas
Example #11
0
def getNextJumpPlatCenter(img, debug=False):
    '''
        获取下一跳平台的中心
    '''
    # 声明画布
    canvas = img.copy()
    # 获取边缘图像
    edge = getCannyEdge(img)
    # 获取边缘信息
    image, contours, hierarchy = cv2.findContours(image=edge, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE)
    # 对轮廓点集进行过滤
    contours = vutils.contours_filter(contours, minWidth=50, minHeight=50)
    
    # 找到最高顶点所在轮廓
    next_box_cnt = min(contours, key=lambda cnt: tuple(cnt[cnt[:,:,1].argmin()][0])[1])
    
    # 获取顶点序号
    top_point_idx = next_box_cnt[:,:,1].argmin()
    # 顶点
    top_point = tuple(next_box_cnt[top_point_idx,0,:2])
    
    # 背景色取样
    img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    refer_back_color = img_hsv[top_point[1], top_point[0]]

    # 分别向左向右找到边界点
    left_idx_itr = 1
    right_idx_itr = -1
    # 校正方向对应的序号叠加
    if next_box_cnt[top_point_idx+left_idx_itr,0, 0] > top_point[0]:
        left_idx_itr, right_idx_itr = right_idx_itr, left_idx_itr 

    right_pt_idx = top_point_idx+right_idx_itr
    left_pt_idx = top_point_idx+left_idx_itr

    right_point = None
    left_point = None

    # 寻找右边的边缘点
    while True:
        # 当前right point
        right_point = tuple(next_box_cnt[right_pt_idx,0,:2])
        # 获取下一个右边的点
        next = tuple(next_box_cnt[right_pt_idx+right_idx_itr,0,:2])
        # 判断这个点是否可以延伸
        if not isNextPoint(right_point, next, x_direction=1):
            break
        elif isInShadow(refer_back_color, img_hsv[next[1]+5, next[0]]):
            # 判断边缘下方的五个像素是不是阴影
            break
        
        right_pt_idx += right_idx_itr
    
    # 寻找左边的边缘点
    while True:
        left_point = tuple(next_box_cnt[left_pt_idx,0,:2])
        next = tuple(next_box_cnt[left_pt_idx+left_idx_itr,0,:2])

        if not isNextPoint(left_point, next, x_direction=-1):
            break
        elif isInShadow(refer_back_color, img_hsv[next[1]+5, next[0]]):
            break

        left_pt_idx += left_idx_itr
    # 调整三个点的位置
    (top_point, left_point, right_point) = adjust_points(top_point, left_point, right_point)
    # 通过平行四边形的定理 获取下方的点
    down_point = (left_point[0]+right_point[0]-top_point[0],left_point[1]+right_point[1]-top_point[1])

    # 生成下一跳平台的搜索区域
    contour = np.array([
        [list(top_point)],
        [list(right_point)],
        [list(down_point)],
        [list(left_point)]])

    (x, y, w, h) = cv2.boundingRect(contour)
    # 在矩形区域内检索小白点提示
    res_pt = getLittleWhitePointCenter(img[y:y+h, x:x+w], offset=(x,y))
    
    center_point = None
    if res_pt is not None:
        # 如果存在小白点 就直接作为中心点
        center_point = res_pt
    else:
        # 取left_point与right_point 中间处作为中心点
        cx = int((left_point[0]+right_point[0])/2)
        cy = int((left_point[1]+right_point[1])/2)
        center_point = (cx, cy)
    
    # 设定圆圈半径
    pt_radius = 10
    # 绘制下一跳中心点
    cv2.circle(canvas, center_point, pt_radius, (45,100,255), thickness=-1)
    if debug == True:
        
        # 绘制轮廓
        cv2.drawContours(image=canvas, contours=[next_box_cnt], contourIdx=-1, color=(0,0,255), thickness=3)
        # 绘制平行四边形的四个点
        cv2.circle(canvas, top_point, pt_radius, (0, 255, 0), thickness=-1)
        cv2.circle(canvas, left_point, pt_radius, (0, 255, 255), thickness=-1)
        cv2.circle(canvas, right_point, pt_radius, (255, 0, 0), thickness=-1)
        cv2.circle(canvas, down_point, pt_radius, (255,255,0), thickness=-1)
        
    
    return center_point,canvas